From 628b9423793bf751a8b1bfae2c2262ab0a96a8b5 Mon Sep 17 00:00:00 2001 From: Jonathon Staff Date: Sat, 1 Nov 2014 19:33:59 +0800 Subject: [PATCH 001/356] Added FileTransfer extension --- Extensions/FileTransfer/XMPPFileTransfer.h | 80 + Extensions/FileTransfer/XMPPFileTransfer.m | 11 + .../FileTransfer/XMPPIncomingFileTransfer.h | 80 + .../FileTransfer/XMPPIncomingFileTransfer.m | 959 ++++++++ .../FileTransfer/XMPPOutgoingFileTransfer.h | 140 ++ .../FileTransfer/XMPPOutgoingFileTransfer.m | 2103 +++++++++++++++++ 6 files changed, 3373 insertions(+) create mode 100644 Extensions/FileTransfer/XMPPFileTransfer.h create mode 100644 Extensions/FileTransfer/XMPPFileTransfer.m create mode 100644 Extensions/FileTransfer/XMPPIncomingFileTransfer.h create mode 100644 Extensions/FileTransfer/XMPPIncomingFileTransfer.m create mode 100644 Extensions/FileTransfer/XMPPOutgoingFileTransfer.h create mode 100644 Extensions/FileTransfer/XMPPOutgoingFileTransfer.m diff --git a/Extensions/FileTransfer/XMPPFileTransfer.h b/Extensions/FileTransfer/XMPPFileTransfer.h new file mode 100644 index 0000000000..8874680397 --- /dev/null +++ b/Extensions/FileTransfer/XMPPFileTransfer.h @@ -0,0 +1,80 @@ +// +// Created by Jonathon Staff on 10/21/14. +// Copyright (c) 2014 nplexity, LLC. All rights reserved. +// + +#import +#import "XMPP.h" +#import "XMPPModule.h" +#import "TURNSocket.h" +#import "GCDAsyncSocket.h" + +@class XMPPIDTracker; + +typedef NS_OPTIONS(uint8_t, XMPPFileTransferStreamMethod) { + XMPPFileTransferStreamMethodBytestreams = 1 << 0, // If set, SOCKS5 connections allowed + XMPPFileTransferStreamMethodIBB = 1 << 1, // If set, IBB connections allowed +// XMPPFileTransferStreamMethodJingle = 1 << 2 // If set, Jingle connections allowed + // Note that Jingle is not yet implemented +}; + +/** +* This class defines common elements of the file transfer process that apply to +* both outgoing and incoming transfers. +* +* You'll find more detailed documentation in each of the implementation files. +* +* By default, the stream-method priority is as follows: +* +* 1. SOCKS5 Direct Connection (http://xmpp.org/extensions/xep-0065.html#direct) +* 2. SOCKS5 Mediated (http://xmpp.org/extensions/xep-0065.html#mediated) +* 3. IBB (http://xmpp.org/extensions/xep-0047.html) +*/ +@interface XMPPFileTransfer : XMPPModule { + XMPPFileTransferStreamMethod _streamMethods; + XMPPIDTracker *_idTracker; + GCDAsyncSocket *_asyncSocket; + NSMutableArray *_streamhosts; +} + +/** +* The streamID ("sid") for the file transfer. +*/ +@property (nonatomic, copy) NSString *sid; + +/** +* Use this to disable file transfers via direct connection. +* +* If set to YES, SOCKS5 transfers will only take place if there is a proxy that +* works. If set to NO, SOCKS5 transfers will attempt a direct connection first +* and fall back to a proxy if the direct connection doesn't work. +* +* The default value is NO. +*/ +@property (nonatomic, assign) BOOL disableDirectTransfers; + +/** +* Use this to disable file transfers via SOCKS5. +* +* If set to YES, SOCKS5 transfers will not be used. This means that the +* recipient must support IBB transfers or the transfer will fail. If set to NO, +* a SOCKS5 connection will be attempted first, since this should be the +* preferred method of transfer. +* +* The default value is NO. +*/ +@property (nonatomic, assign) BOOL disableSOCKS5; + +/** +* Use this to disable file transfers via IBB. +* +* If set to YES, IBB transfers will not be used. This means that the +* recipient must support SOCKS5 transfers or the transfer will fail. If set to +* NO, a SOCKS5 connection will be attempted first, since this should be the +* preferred method of transfer. +* +* The default value is NO. +*/ +@property (nonatomic, assign) BOOL disableIBB; + +@end diff --git a/Extensions/FileTransfer/XMPPFileTransfer.m b/Extensions/FileTransfer/XMPPFileTransfer.m new file mode 100644 index 0000000000..1334c8bfd5 --- /dev/null +++ b/Extensions/FileTransfer/XMPPFileTransfer.m @@ -0,0 +1,11 @@ +// +// Created by Jonathon Staff on 10/21/14. +// Copyright (c) 2014 nplexity, LLC. All rights reserved. +// + +#import "XMPPFileTransfer.h" + + +@implementation XMPPFileTransfer + +@end \ No newline at end of file diff --git a/Extensions/FileTransfer/XMPPIncomingFileTransfer.h b/Extensions/FileTransfer/XMPPIncomingFileTransfer.h new file mode 100644 index 0000000000..2da822ccb0 --- /dev/null +++ b/Extensions/FileTransfer/XMPPIncomingFileTransfer.h @@ -0,0 +1,80 @@ +// +// Created by Jonathon Staff on 10/21/14. +// Copyright (c) 2014 nplexity, LLC. All rights reserved. +// + +#import +#import "XMPPFileTransfer.h" + +@class XMPPIQ; + +@interface XMPPIncomingFileTransfer : XMPPFileTransfer + +/** +* (Optional) +* +* Specifies whether or not file transfers should automatically be accepted. If +* set to YES, you will be notified of an incoming Stream Initiation Offer, but +* it will be accepted for you. +* +* The default value is NO. +*/ +@property (nonatomic, assign) BOOL autoAcceptFileTransfers; + +/** +* Sends a response to the file transfer initiator accepting the Stream +* Initiation offer. It will automatically determine the best transfer method +* (either SOCKS5 or IBB) based on what the sender offers as options. +* +* If you've set autoAcceptFileTransfers to YES, this method will be invoked for +* you automatically. +* +* @param offer IQ stanza representing the SI offer (this should be provided by +* the delegate to you). +*/ +- (void)acceptSIOffer:(XMPPIQ *)offer; + +@end + + +#pragma mark - XMPPIncomingFileTransferDelegate + +@protocol XMPPIncomingFileTransferDelegate +@optional + +/** +* Implement this method to receive notifications of a failed incoming file +* transfer. +* +* @param sender XMPPIncomingFileTransfer object invoking this delegate method. +* @param error NSError containing more details of the failure. +*/ +- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender + didFailWithError:(NSError *)error; + +/** +* Implement this method to receive notification of an incoming Stream +* Initiation offer. Keep in mind that if you haven't set +* autoAcceptFileTransfers to YES, then it will be your responsibility to call +* acceptSIOffer: using the sender and offer provided to you. +* +* @param sender XMPPIncomingFileTransfer object invoking this delegate method. +* @param offer IQ stanza containing a Stream Initiation offer. +*/ +- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender + didReceiveSIOffer:(XMPPIQ *)offer; + +/** +* Implement this method to receive notifications of a successful incoming file +* transfer. It will only be invoked if all of the data is received +* successfully. +* +* @param sender XMPPIncomingFileTransfer object invoking this delegate method. +* @param data NSData for you to handle (probably save this or display it). +* @param named Name of the file you just received. +*/ +- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender + didSucceedWithData:(NSData *)data + named:(NSString *)name; + +@end diff --git a/Extensions/FileTransfer/XMPPIncomingFileTransfer.m b/Extensions/FileTransfer/XMPPIncomingFileTransfer.m new file mode 100644 index 0000000000..614236e359 --- /dev/null +++ b/Extensions/FileTransfer/XMPPIncomingFileTransfer.m @@ -0,0 +1,959 @@ +// +// Created by Jonathon Staff on 10/21/14. +// Copyright (c) 2014 nplexity, LLC. All rights reserved. +// + +#if !__has_feature(objc_arc) +#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). +#endif + +#import "XMPPIncomingFileTransfer.h" +#import "XMPPNamespaces.h" +#import "XMPPLogging.h" +#import "idn-int.h" +#import "NSNumber+XMPP.h" +#import "NSData+XMPP.h" + +#if DEBUG +static const int xmppLogLevel = XMPP_LOG_LEVEL_VERBOSE | XMPP_LOG_FLAG_TRACE; +#else + static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; +#endif + +/** +* Tags for _asyncSocket handling. +*/ +#define SOCKS_TAG_WRITE_METHOD 101 +#define SOCKS_TAG_READ_METHOD 102 +#define SOCKS_TAG_WRITE_CONNECT 103 +#define SOCKS_TAG_READ_REPLY 104 +#define SOCKS_TAG_READ_ADDRESS 105 +#define SOCKS_TAG_READ_DATA 106 + +#define TIMEOUT_WRITE -1 +#define TIMEOUT_READ 5.0 + +// XMPP Incoming File Transfer State +typedef NS_ENUM(int, XMPPIFTState) { + XMPPIFTStateNone, + XMPPIFTStateWaitingForSIOffer, + XMPPIFTStateWaitingForStreamhosts, + XMPPIFTStateConnectingToStreamhosts, + XMPPIFTStateConnected, + XMPPIFTStateWaitingForIBBOpen, + XMPPIFTStateWaitingForIBBData +}; + +NSString *const XMPPIncomingFileTransferErrorDomain = @"XMPPIncomingFileTransferErrorDomain"; + +@interface XMPPIncomingFileTransfer () { + XMPPIFTState _transferState; + + XMPPJID *_senderJID; + + NSString *_streamhostsQueryId; + NSString *_streamhostUsed; + + NSMutableData *_receivedData; + NSString *_receivedFileName; + NSUInteger _totalDataSize; + NSUInteger _receivedDataSize; + + dispatch_source_t _ibbTimer; +} + +@end + +@implementation XMPPIncomingFileTransfer + + +#pragma mark - Lifecycle + +- (instancetype)initWithDispatchQueue:(dispatch_queue_t)queue +{ + self = [super initWithDispatchQueue:queue]; + if (self) { + _transferState = XMPPIFTStateNone; + } + return self; +} + +/** +* Standard deconstructor. +*/ +- (void)dealloc +{ + XMPPLogTrace(); + + if (_transferState != XMPPIFTStateNone) { + XMPPLogWarn(@"%@: Deallocating prior to completion or cancellation.", THIS_FILE); + } + + if (_ibbTimer) + dispatch_source_cancel(_ibbTimer); +#if !OS_OBJECT_USE_OBJC + dispatch_release(_ibbTimer); + #endif + _ibbTimer = NULL; + + if (_asyncSocket.delegate == self) { + [_asyncSocket setDelegate:nil delegateQueue:NULL]; + [_asyncSocket disconnect]; + } +} + + +#pragma mark - Public Methods + +/** +* Public facing method for accepting a SI offer. If autoAcceptFileTransfers is +* set to YES, this method will do nothing, since the internal method is invoked +* automatically. +* +* @see sendSIOfferAcceptance: +*/ +- (void)acceptSIOffer:(XMPPIQ *)offer +{ + XMPPLogTrace(); + + if (!_autoAcceptFileTransfers) { + [self sendSIOfferAcceptance:offer]; + } +} + + +#pragma mark - Private Methods + +/** +* This method will send the device's identity in response to a `disco#info` +* query. In our case, we will send something close the following: +* +* +* +* +* +* +* +* +* +* +* +* This tells the requester who they're dealing with and which transfer types +* we support. If there's a better way than hard-coding these values, I'm open +* to suggestions. +*/ +- (void)sendIdentity:(XMPPIQ *)request +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + XMPPIQ *iq = [XMPPIQ iqWithType:@"result" + to:request.from + elementID:request.elementID]; + [iq addAttributeWithName:@"from" stringValue:xmppStream.myJID.full]; + + NSXMLElement + *query = [NSXMLElement elementWithName:@"query" xmlns:XMPPDiscoInfoNamespace]; + + NSXMLElement *identity = [NSXMLElement elementWithName:@"identity"]; + [identity addAttributeWithName:@"category" stringValue:@"client"]; + [identity addAttributeWithName:@"type" stringValue:@"ios-osx"]; + [query addChild:identity]; + + NSXMLElement *feature = [NSXMLElement elementWithName:@"feature"]; + [feature addAttributeWithName:@"var" stringValue:XMPPSINamespace]; + [query addChild:feature]; + + NSXMLElement *feature1 = [NSXMLElement elementWithName:@"feature"]; + [feature1 addAttributeWithName:@"var" stringValue:XMPPSIProfileFileTransferNamespace]; + [query addChild:feature1]; + + if (!self.disableSOCKS5) { + NSXMLElement *feature2 = [NSXMLElement elementWithName:@"feature"]; + [feature2 addAttributeWithName:@"var" stringValue:XMPPBytestreamsNamespace]; + [query addChild:feature2]; + } + + if (!self.disableIBB) { + NSXMLElement *feature3 = [NSXMLElement elementWithName:@"feature"]; + [feature3 addAttributeWithName:@"var" stringValue:XMPPIBBNamespace]; + [query addChild:feature3]; + } + + [iq addChild:query]; + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method will send an IQ stanza accepting the SI offer. We need to choose +* which 'stream-method' we prefer to use. For now, we will be using IBB as the +* 'stream-method', but SOCKS5 is preferable. +* +* Take a look at XEP-0096 Examples 2 and 4 for more details. +*/ +- (void)sendSIOfferAcceptance:(XMPPIQ *)offer +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // Store the sender's JID + _senderJID = offer.from; + + // Store the sid for later use + NSXMLElement *inSi = offer.childElement; + self.sid = [inSi attributeStringValueForName:@"id"]; + + // Store the size of the incoming data for later use + NSXMLElement *inFile = [inSi elementForName:@"file"]; + _totalDataSize = [inFile attributeUnsignedIntegerValueForName:@"size"]; + + // Store the name of the file for later use + _receivedFileName = [inFile attributeStringValueForName:@"name"]; + + // Outgoing + XMPPIQ *iq = [XMPPIQ iqWithType:@"result" + to:offer.from + elementID:offer.elementID]; + + + NSXMLElement *si = [NSXMLElement elementWithName:@"si" xmlns:XMPPSINamespace]; + + NSXMLElement *feature = [NSXMLElement elementWithName:@"feature" + xmlns:XMPPFeatureNegNamespace]; + + NSXMLElement *x = [NSXMLElement elementWithName:@"x" xmlns:@"jabber:x:data"]; + [x addAttributeWithName:@"type" stringValue:@"submit"]; + + NSXMLElement *field = [NSXMLElement elementWithName:@"field"]; + [field addAttributeWithName:@"var" stringValue:@"stream-method"]; + + NSXMLElement *value = [NSXMLElement elementWithName:@"value"]; + + // Prefer SOCKS5 if it's not disabled. + if (!self.disableSOCKS5) { + [value setStringValue:XMPPBytestreamsNamespace]; + _transferState = XMPPIFTStateWaitingForStreamhosts; + } else { + [value setStringValue:XMPPIBBNamespace]; + _transferState = XMPPIFTStateWaitingForIBBOpen; + } + + [field addChild:value]; + [x addChild:field]; + [feature addChild:x]; + [si addChild:feature]; + [iq addChild:si]; + + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + + +#pragma mark - IBB Methods + +/** +* This method will send an IQ stanza accepting the IBB request. See XEP-0047 +* Example 2 for more details. +*/ +- (void)sendIBBAcceptance:(XMPPIQ *)request +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + XMPPIQ *iq = [XMPPIQ iqWithType:@"result" + to:request.from + elementID:request.elementID]; + [xmppStream sendElement:iq]; + + // Prepare to receive data + _receivedData = [NSMutableData new]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method is responsible for reading the incoming data from the IQ stanza +* and writing it to the member variable '_receivedData'. After successfully +* reading the data, a response (XEP-0047 Example 7) will be sent back to the +* sender. +*/ +- (void)processReceivedIBBDataIQ:(XMPPIQ *)received +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // Handle the scenario that the transfer is cancelled. + [self resetIBBTimer:20]; + + // Handle incoming data + NSXMLElement *dataElem = received.childElement; + NSData + *temp = [[NSData alloc] initWithBase64EncodedString:dataElem.stringValue options:0]; + [_receivedData appendData:temp]; + + // According the base64 encoding, it takes up 4/3 n bytes of space, so + // we need to find the size of the data before base64. + _receivedDataSize += (3 * dataElem.stringValue.length) / 4; + + XMPPLogVerbose(@"Downloaded %lu/%lu bytes in IBB transfer.", + (unsigned long) _receivedDataSize, (unsigned long) _totalDataSize); + + if (_receivedDataSize < _totalDataSize) { + // Send ack response + XMPPIQ *iq = [XMPPIQ iqWithType:@"result" + to:received.from + elementID:received.elementID]; + [xmppStream sendElement:iq]; + } else { + // We're finished! + XMPPLogInfo(@"Finished downloading IBB data."); + [self transferSuccess]; + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + + +#pragma mark - Util Methods + +/** +* This method determines whether or not the IQ stanza is a `disco#info` +* request. Should be in the following form: +* +* +* +* +*/ +- (BOOL)isDiscoInfoIQ:(XMPPIQ *)iq +{ + if (!iq) return NO; + NSXMLElement *query = iq.childElement; + return query != nil && [query.xmlns isEqualToString:XMPPDiscoInfoNamespace]; +} + +/** +* This method determines whether or not the the IQ stanza is a Stream +* Initiation Offer (XEP-0096 Examples 1 and 3). +*/ +- (BOOL)isSIOfferIQ:(XMPPIQ *)iq +{ + if (!iq) return NO; + if (![iq.type isEqualToString:@"set"]) return NO; + + NSXMLElement *si = iq.childElement; + if (!si || ![si.xmlns isEqualToString:XMPPSINamespace]) return NO; + + NSXMLElement *file = (DDXMLElement *) [si childAtIndex:0]; + if (!file || ![file.xmlns isEqualToString:XMPPSIProfileFileTransferNamespace]) return NO; + + NSXMLElement *feature = (DDXMLElement *) [si childAtIndex:1]; + return !(!feature || ![feature.xmlns isEqualToString:XMPPFeatureNegNamespace]); + + // Maybe there should be further verification, but I think this should be + // plenty... +} + +/** +* This method determines whether or not the IQ stanza is an IBB session request +* (XEP-0047 Example 1). +*/ +- (BOOL)isIBBOpenRequestIQ:(XMPPIQ *)iq +{ + if (!iq) return NO; + if (![iq.type isEqualToString:@"set"]) return NO; + + NSXMLElement *open = iq.childElement; + return !(!open || ![open.xmlns isEqualToString:XMPPIBBNamespace]); +} + +/** +* This method determines whether or not the IQ stanza is an IBB data stanza +* (XEP-0047 Example 6). +*/ +- (BOOL)isIBBDataIQ:(XMPPIQ *)iq +{ + if (!iq) return NO; + if (![iq.type isEqualToString:@"set"]) return NO; + + NSXMLElement *data = iq.childElement; + return !(!data || ![data.xmlns isEqualToString:XMPPIBBNamespace]); +} + +/** +* This method determines whether or not the IQ stanza contains a list of +* streamhosts as shown in XEP-0065 Example 12. +*/ +- (BOOL)isStreamhostsListIQ:(XMPPIQ *)iq +{ + if (!iq) return NO; + if (![iq.type isEqualToString:@"set"]) return NO; + + NSXMLElement *query = iq.childElement; + if (!query || ![[query attributeStringValueForName:@"sid"] isEqualToString:self.sid]) return NO; + + return [query elementsForName:@"streamhost"].count > 0; +} + +/** +* This method returns the SHA1 hash as per XEP-0065. +* +* The [address] MUST be SHA1(SID + Initiator JID + Target JID) and the output +* is hexadecimal encoded (not binary). +* +* Because this is an incoming file transfer, we are always the target. +*/ +- (NSData *)sha1Hash +{ + NSString *hashMe = + [NSString stringWithFormat:@"%@%@%@", self.sid, _senderJID.full, xmppStream.myJID.full]; + NSData *hashRaw = [[hashMe dataUsingEncoding:NSUTF8StringEncoding] xmpp_sha1Digest]; + NSData *hash = [[hashRaw xmpp_hexStringValue] dataUsingEncoding:NSUTF8StringEncoding]; + + XMPPLogVerbose(@"%@: hashMe : %@", THIS_FILE, hashMe); + XMPPLogVerbose(@"%@: hashRaw: %@", THIS_FILE, hashRaw); + XMPPLogVerbose(@"%@: hash : %@", THIS_FILE, hash); + + return hash; +} + +/** +* This method is called to clean up everything when the transfer fails. +*/ +- (void)failWithReason:(NSString *)causeOfFailure + error: + (NSError *)error +{ + XMPPLogTrace(); + XMPPLogInfo(@"Incoming file transfer failed because: %@", causeOfFailure); + + if (!error && causeOfFailure) { + NSDictionary *errInfo = @{NSLocalizedDescriptionKey : causeOfFailure}; + error = [NSError errorWithDomain:XMPPIncomingFileTransferErrorDomain + code:-1 + userInfo:errInfo]; + } + + _transferState = XMPPIFTStateNone; + [multicastDelegate xmppIncomingFileTransfer:self didFailWithError:error]; +} + +/** +* This method is called when the transfer is successfully completed. It +* handles resetting variables for another transfer and alerts the delegate of +* the transfer completion. +*/ +- (void)transferSuccess +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + [self cancelIBBTimer]; + + [multicastDelegate xmppIncomingFileTransfer:self + didSucceedWithData:_receivedData + named:_receivedFileName]; + [self cleanUp]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method is used to reset the system for receiving new files. +*/ +- (void)cleanUp +{ + XMPPLogTrace(); + + if (_asyncSocket) { + [_asyncSocket setDelegate:nil]; + [_asyncSocket disconnect]; + _asyncSocket = nil; + } + + _transferState = XMPPIFTStateNone; + _senderJID = nil; + _streamhostsQueryId = nil; + _streamhostUsed = nil; + _receivedData = nil; + _receivedFileName = nil; + _totalDataSize = 0; + _receivedDataSize = 0; +} + + +#pragma mark - Timeouts + +/** +* Resets the IBB timer that will cause the transfer to formally fail if an IBB +* data IQ stanza isn't received within the timeout. +*/ +- (void)resetIBBTimer:(NSTimeInterval)timeout +{ + NSAssert(dispatch_get_specific(moduleQueueTag), @"Invoked on incorrect queue."); + + if (_ibbTimer == NULL) { + _ibbTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, moduleQueue); + + dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC); + + dispatch_source_set_timer(_ibbTimer, tt, DISPATCH_TIME_FOREVER, 1); + dispatch_resume(_ibbTimer); + } else { + dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC); + dispatch_source_set_timer(_ibbTimer, tt, DISPATCH_TIME_FOREVER, 1); + } + + dispatch_source_set_event_handler(_ibbTimer, ^{ + @autoreleasepool { + NSString *errMsg = @"The IBB transfer timed out. It's likely that the sender canceled the" + @" transfer or has gone offline."; + [self failWithReason:errMsg error:nil]; + } + }); +} + +- (void)cancelIBBTimer +{ + NSAssert(dispatch_get_specific(moduleQueueTag), @"Invoked on incorrect queue."); + + if (_ibbTimer) { + dispatch_source_cancel(_ibbTimer); +#if !OS_OBJECT_USE_OBJC + dispatch_release(_ibbTimer); + #endif + _ibbTimer = NULL; + } +} + + +#pragma mark - XMPPStreamDelegate + +- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq +{ + if (_transferState == XMPPIFTStateNone && [self isDiscoInfoIQ:iq]) { + [self sendIdentity:iq]; + _transferState = XMPPIFTStateWaitingForSIOffer; + return YES; + } + + if ((_transferState == XMPPIFTStateNone || _transferState == XMPPIFTStateWaitingForSIOffer) + && [self isSIOfferIQ:iq]) { + // Alert the delegate that we've received a stream initiation offer + [multicastDelegate xmppIncomingFileTransfer:self didReceiveSIOffer:iq]; + + if (_autoAcceptFileTransfers) { + [self sendSIOfferAcceptance:iq]; + } + + return YES; + } + + if (_transferState == XMPPIFTStateWaitingForStreamhosts && [self isStreamhostsListIQ:iq]) { + [self attemptStreamhostsConnection:iq]; + return YES; + } + + if (_transferState == XMPPIFTStateWaitingForIBBOpen && [self isIBBOpenRequestIQ:iq]) { + [self sendIBBAcceptance:iq]; + _transferState = XMPPIFTStateWaitingForIBBData; + + // Handle the scenario that the transfer is cancelled. + [self resetIBBTimer:20]; + return YES; + } + + if (_transferState == XMPPIFTStateWaitingForIBBData && [self isIBBDataIQ:iq]) { + [self processReceivedIBBDataIQ:iq]; + } + + return iq != nil; +} + + +#pragma mark - GCDAsyncSocketDelegate + +- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port +{ + XMPPLogVerbose(@"%@: didConnectToHost:%@ port:%d", THIS_FILE, host, port); + + [self socks5WriteMethod]; + _transferState = XMPPIFTStateConnected; +} + +- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag +{ + XMPPLogVerbose(@"%@: didReadData:%@ withTag:%ld", THIS_FILE, data, tag); + + switch (tag) { + case SOCKS_TAG_READ_METHOD: + [self socks5ReadMethod:data]; + break; + case SOCKS_TAG_READ_REPLY: + [self socks5ReadReply:data]; + case SOCKS_TAG_READ_ADDRESS: + [_asyncSocket readDataToLength:_totalDataSize + withTimeout:TIMEOUT_READ + tag:SOCKS_TAG_READ_DATA]; + break; + case SOCKS_TAG_READ_DATA: + // Success! + _receivedData = [data mutableCopy]; + [self transferSuccess]; + default: + break; + } +} + +- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag +{ + XMPPLogVerbose(@"%@: didWriteDataWithTag:%ld", THIS_FILE, tag); + + switch (tag) { + case SOCKS_TAG_WRITE_METHOD: + [_asyncSocket readDataToLength:2 withTimeout:TIMEOUT_READ tag:SOCKS_TAG_READ_METHOD]; + break; + case SOCKS_TAG_WRITE_CONNECT: + [_asyncSocket readDataToLength:5 withTimeout:TIMEOUT_READ + tag:SOCKS_TAG_READ_REPLY]; + default: + break; + } +} + +- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err +{ + XMPPLogTrace(); + + if (_transferState == XMPPIFTStateConnected) { + [self failWithReason:@"Socket disconnected before transfer complete." error:nil]; + } +} + + +#pragma mark - SOCKS5 + +/** +* This method attempts a connection to each of the streamhosts provided until +* either a connection is established or there are no more streamhosts. In the +* latter case, an error stanza is sent to the sender. +* +* @see socket:didConnectToHost:port: +*/ +- (void)attemptStreamhostsConnection:(XMPPIQ *)iq +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + _streamhostsQueryId = iq.elementID; + _transferState = XMPPIFTStateConnectingToStreamhosts; + _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:moduleQueue]; + + // Since we've already validated our IQ stanza, we can just pull the data + NSArray *streamhosts = [iq.childElement elementsForName:@"streamhost"]; + + for (NSXMLElement *streamhost in streamhosts) { + NSString *host = [streamhost attributeStringValueForName:@"host"]; + uint16_t port = (gl_uint16_t) [streamhost attributeUInt32ValueForName:@"port"]; + + NSError *err; + if (![_asyncSocket connectToHost:host onPort:port error:&err]) { + XMPPLogVerbose(@"%@: Unable to host:%@ port:%d error:%@", THIS_FILE, host, port, err); + continue; + } + + // If we make it this far, we've successfully connected to one of the hosts. + _streamhostUsed = [streamhost attributeStringValueForName:@"jid"]; + + return; + } + + // If we reach this, we weren't able to connect to any of the streamhosts. + // We'll send an error to the sender to let them know, and then we'll alert + // the delegate of the failure. + // + // XEP-0065 Example 13. + // + // + // + // + // + // + + XMPPIQ *errorIq = [XMPPIQ iqWithType:@"error" to:iq.from elementID:iq.elementID]; + + NSXMLElement *errorElem = [NSXMLElement elementWithName:@"error"]; + [errorElem addAttributeWithName:@"type" stringValue:@"modify"]; + + NSXMLElement *notAcceptable = [NSXMLElement elementWithName:@"not-acceptable" + xmlns:@"urn:ietf:params:xml:ns:xmpp-stanzas"]; + [errorElem addChild:notAcceptable]; + [errorIq addChild:errorElem]; + + [xmppStream sendElement:errorIq]; + + NSString *errMsg = @"Unable to connect to any of the provided streamhosts."; + [self failWithReason:errMsg error:nil]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +- (void)socks5WriteMethod +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // We will attempt anonymous authentication with the proxy. The request is + // the same that we would read if this were a direct connection. The only + // difference is this time we initiate the request as a client rather than + // being a the 'server.' + // + // +----+----------+----------+ + // |VER | NMETHODS | METHODS | + // +----+----------+----------+ + // | 1 | 1 | 1 to 255 | + // +----+----------+----------+ + // + // We're sending: + // + // VER = 5 (SOCKS5) + // NMETHODS = 1 (number of methods) + // METHODS = 0 (no authentication) + + void *byteBuf = malloc(3); + + UInt8 ver = 5; + memcpy(byteBuf, &ver, sizeof(ver)); + + UInt8 nmethods = 1; + memcpy(byteBuf + 1, &nmethods, sizeof(nmethods)); + + UInt8 methods = 0; + memcpy(byteBuf + 2, &methods, sizeof(methods)); + + NSData *data = [NSData dataWithBytesNoCopy:byteBuf length:3 freeWhenDone:YES]; + [_asyncSocket writeData:data withTimeout:TIMEOUT_WRITE tag:SOCKS_TAG_WRITE_METHOD]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +- (void)socks5ReadMethod:(NSData *)incomingData +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // We've sent a request to connect with no authentication. This is the + // response: + // + // +----+--------+ + // |VER | METHOD | + // +----+--------+ + // | 1 | 1 | + // +----+--------+ + // + // We're expecting: + // + // VER = 5 (SOCKS5) + // METHOD = 0 (no authentication) + + UInt8 version = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:0]; + UInt8 method = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:1]; + + if (version != 5 || method) { + [self failWithReason:@"Proxy doesn't allow anonymous authentication." error:nil]; + return; + } + + NSData *hash = [self sha1Hash]; + + // The SOCKS request is formed as follows: + // + // +----+-----+-------+------+----------+----------+ + // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | + // +----+-----+-------+------+----------+----------+ + // | 1 | 1 | X'00' | 1 | Variable | 2 | + // +----+-----+-------+------+----------+----------+ + // + // We're sending: + // + // VER = 5 + // CMD = 1 (connect) + // RSV = 0 (reserved; this will always be 0) + // ATYP = 3 (domain name) + // DST.ADDR (varies based on ATYP) + // DST.PORT = 0 (according to XEP-0065) + // + // Immediately after ATYP, we need to send the length of our address. Because + // SHA1 is always 40 bytes, we simply send this value. After it, we append + // the actual hash and then the port. + + void *byteBuf = malloc(5 + 40 + 2); + + UInt8 ver = 5; + memcpy(byteBuf, &ver, sizeof(ver)); + + UInt8 cmd = 1; + memcpy(byteBuf + 1, &cmd, sizeof(cmd)); + + UInt8 rsv = 0; + memcpy(byteBuf + 2, &rsv, sizeof(rsv)); + + UInt8 atyp = 3; + memcpy(byteBuf + 3, &atyp, sizeof(atyp)); + + UInt8 hashlen = (UInt8) hash.length; + memcpy(byteBuf + 4, &hashlen, sizeof(hashlen)); + + memcpy(byteBuf + 5, hash.bytes, hashlen); + + UInt8 port = 0; + memcpy(byteBuf + 5 + hashlen, &port, sizeof(port)); + memcpy(byteBuf + 6 + hashlen, &port, sizeof(port)); + + NSData *data = [NSData dataWithBytesNoCopy:byteBuf length:47 freeWhenDone:YES]; + [_asyncSocket writeData:data withTimeout:TIMEOUT_WRITE tag:SOCKS_TAG_WRITE_CONNECT]; + + XMPPLogVerbose(@"%@: writing connect request: %@", THIS_FILE, data); + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +- (void)socks5ReadReply:(NSData *)incomingData +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // The server/sender will reply to our connect command with the following: + // + // +----+-----+-------+------+----------+----------+ + // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + // +----+-----+-------+------+----------+----------+ + // | 1 | 1 | X'00' | 1 | Variable | 2 | + // +----+-----+-------+------+----------+----------+ + // + // VER = 5 (SOCKS5) + // REP = 0 (Success) + // RSV = 0 + // ATYP = 3 (Domain) - NOTE: Since we're using ATYP = 3, we must check the + // length of the server's host in the next byte. + + UInt8 ver = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:0]; + UInt8 rep = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:1]; + UInt8 atyp = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:3]; + UInt8 hostlen = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:4]; + + if (ver != 5 || rep || atyp != 3) { + [self failWithReason:@"Invalid VER, REP, or ATYP." error:nil]; + return; + } + + // According to XEP-0065 Example 23, we don't need to validate the + // address we were sent (at least that is how I interpret it), so we + // just read the next 42 bytes (hostlen + portlen) so there's no + // conflict when reading the data and then send to + // the file transfer initiator. Note that the sid must be included. + // + // XEP-0065 Example 17: + // + // + // + // + // + // + + XMPPIQ *iq = [XMPPIQ iqWithType:@"result" to:_senderJID elementID:_streamhostsQueryId]; + + NSXMLElement *query = [NSXMLElement elementWithName:@"query" + xmlns:XMPPBytestreamsNamespace]; + [query addAttributeWithName:@"sid" stringValue:self.sid]; + + NSXMLElement *streamhostUsed = [NSXMLElement elementWithName:@"streamhost-used"]; + [streamhostUsed addAttributeWithName:@"jid" + stringValue:_streamhostUsed]; + + [query addChild:streamhostUsed]; + [iq addChild:query]; + + [xmppStream sendElement:iq]; + + // We're basically piping these to dev/null because we don't care. + // However, we need to tag this read so we can start to read the actual + // data once this read is finished. + [_asyncSocket readDataToLength:hostlen + 2 + withTimeout:TIMEOUT_READ + tag:SOCKS_TAG_READ_ADDRESS]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +@end diff --git a/Extensions/FileTransfer/XMPPOutgoingFileTransfer.h b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.h new file mode 100644 index 0000000000..affddffdd8 --- /dev/null +++ b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.h @@ -0,0 +1,140 @@ +// +// Created by Jonathon Staff on 10/21/14. +// Copyright (c) 2014 nplexity, LLC. All rights reserved. +// + +#import +#import "XMPPFileTransfer.h" + +@interface XMPPOutgoingFileTransfer : XMPPFileTransfer + +/** +* (Required) +* +* The data being sent to the recipient. +* +* If you're using startFileTransfer:, you *MUST* set this prior to calling +* startFileTransfer:. +*/ +@property (nonatomic, strong) NSData *outgoingData; + +/** +* (Required) +* +* The recipient of your file transfer. +* +* If you're using startFileTransfer:, you *MUST* set this prior to calling +* startFileTransfer:. +*/ +@property (nonatomic, strong) XMPPJID *recipientJID; + +/** +* (Optional) +* +* The name of the file you're sending. +* +* If you don't provide a filename, one will be generated for you. +*/ +@property (nonatomic, copy) NSString *outgoingFileName; + +/** +* (Optional) +* +* The description of the file you're sending. +*/ +@property (nonatomic, copy) NSString *outgoingFileDescription; + +/** +* (Optional) +* +* Specifies whether or not a random name should be generated instead of the +* filename provided. The randomly generated name will retain the same file +* extension as the original name if one was provided +* +* The default is NO; set to YES to generate a random name. +*/ +@property (nonatomic, assign) BOOL shouldGenerateRandomName; + +/** +* (Optional) +* +* Specifies the default block-size when using IBB file transfers. The default +* value is 4096 (Bytes). If the file recipient requests a smaller block-size, +* it will be halved. +*/ +@property (nonatomic, assign) int32_t blockSize; + + +#pragma mark - Public Methods + +/** +* Starts the file transfer. This assumes that at a minimum a recipientJID and +* outgoingData have already been provided. +* +* @param errPtr The address of an error which will be contain a description of +* the problem if there is one (optional). +* +* @return Returns NO if there is something blatantly wrong (not authorized, no +* recipientJID, no outgoingData); YES otherwise. +*/ +- (BOOL)startFileTransfer:(NSError **)errPtr; + +/** +* Sends the provided data to the provided recipient. Use of this method is not +* recommended, as there is no error handling, but you're free to make your own +* choices. +*/ +- (BOOL)sendData:(NSData *)data toRecipient:(XMPPJID *)recipient; + +/** +* Sends the provided data to the provided recipient. Pass nil for params you +* don't care about. +* +* @param data The data you wish to send (required). +* @param name The filename of the file you're sending (optional). +* @param recipient The recipient of your file transfer (required). Note that a +* resource must also be included in the JID. +* @param description The description of the file you're sending (optional). +* @param errPtr The address of an error which will contain a description of the +* problem if there is one (optional). +*/ +- (BOOL)sendData:(NSData *)data + named:(NSString *)name + toRecipient:(XMPPJID *)recipient + description:(NSString *)description + error:(NSError **)errPtr; + +@end + + +#pragma mark - XMPPOutgoingFileTransferDelegate + +@protocol XMPPOutgoingFileTransferDelegate +@optional + +/** +* Implement this method when calling startFileTransfer: or sendData:(variants). +* It will be invoked if the file transfer fails to execute properly. More +* information will be given in the error. +* +* @param sender XMPPOutgoingFileTransfer object invoking this delegate method. +* @param error NSError containing more details of the failure. +*/ +- (void)xmppOutgoingFileTransfer:(XMPPOutgoingFileTransfer *)sender + didFailWithError:(NSError *)error; + +/** +* Implement this method when calling startFileTransfer: or sendData:(variants). +* It will be invoked if the outgoing file transfer was completed successfully. +* +* @param sender XMPPOutgoingFileTransfer object invoking this delegate method. +*/ +- (void)xmppOutgoingFileTransferDidSucceed:(XMPPOutgoingFileTransfer *)sender; + +/** +* Not really sure why you would want this information, but hey, when I get +* information, I'm happy to share. +*/ +- (void)xmppOutgoingFileTransferIBBClosed:(XMPPOutgoingFileTransfer *)sender; + +@end diff --git a/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m new file mode 100644 index 0000000000..2a56467c1f --- /dev/null +++ b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m @@ -0,0 +1,2103 @@ +// +// Created by Jonathon Staff on 10/21/14. +// Copyright (c) 2014 nplexity, LLC. All rights reserved. +// + +#if !__has_feature(objc_arc) +#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). +#endif + +#import +#import +#import +#import +#import +#import "XMPPLogging.h" +#import "XMPPOutgoingFileTransfer.h" +#import "XMPPIDTracker.h" +#import "idn-int.h" +#import "XMPPNamespaces.h" +#import "NSNumber+XMPP.h" +#import "NSData+XMPP.h" + +#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 IOS_CELLULAR @"pdp_ip0" +#define IOS_WIFI @"en0" +#define IP_ADDR_IPv4 @"ipv4" +#define IP_ADDR_IPv6 @"ipv6" + +/** +* Seeing a return statements within an inner block +* can sometimes be mistaken for a return point of the enclosing method. +* This makes inline blocks a bit easier to read. +**/ +#define return_from_block return + +/** +* Tags for _asyncSocket handling. +*/ +#define SOCKS_TAG_READ_METHOD 101 +#define SOCKS_TAG_WRITE_METHOD 102 +#define SOCKS_TAG_READ_REQUEST 103 +#define SOCKS_TAG_READ_DOMAIN 104 +#define SOCKS_TAG_WRITE_REPLY 105 +#define SOCKS_TAG_WRITE_DATA 106 +#define SOCKS_TAG_WRITE_PROXY_METHOD 107 +#define SOCKS_TAG_READ_PROXY_METHOD 108 +#define SOCKS_TAG_WRITE_PROXY_CONNECT 109 +#define SOCKS_TAG_READ_PROXY_REPLY 110 + +#define TIMEOUT_WRITE -1 +#define TIMEOUT_READ 5.0 + +/** +* Set the default timeout for requests to be 60 seconds. +*/ +#define OUTGOING_DEFAULT_TIMEOUT 60 + +// XMPP Outgoing File Transfer State +typedef NS_ENUM(int, XMPPOFTState) { + XMPPOFTStateNone, + XMPPOFTStateSOCKSLive, + XMPPOFTStateConnectingToProxy, + XMPPOFTStateFinished +}; + +NSString *const XMPPOutgoingFileTransferErrorDomain = @"XMPPOutgoingFileTransferErrorDomain"; + +@interface XMPPOutgoingFileTransfer () { + dispatch_queue_t _outgoingQueue; + void *_outgoingQueueTag; + + NSString *_localIPAddress; + uint16_t _localPort; + + GCDAsyncSocket *_outgoingSocket; + + int32_t _outgoingDataBlockSeq; + NSUInteger _sentDataSize; + NSUInteger _totalDataSize; + NSString *_outgoingDataBase64; + + XMPPOFTState _transferState; + + XMPPJID *_proxyJID; +} + +@end + +@implementation XMPPOutgoingFileTransfer + + +- (instancetype)initWithDispatchQueue:(dispatch_queue_t)queue +{ + self = [super initWithDispatchQueue:queue]; + if (self) { + // Create separate dispatch queue. + _outgoingQueue = dispatch_queue_create("XMPPOutgoingFileTransfer", NULL); + _outgoingQueueTag = &_outgoingQueueTag; + dispatch_queue_set_specific(_outgoingQueue, _outgoingQueueTag, _outgoingQueueTag, NULL); + + // define the default block-size in case we use IBB + _blockSize = 4096; + + _transferState = XMPPOFTStateNone; + } + return self; +} + + +#pragma mark - XMPPModule Methods + +- (void)didActivate +{ + XMPPLogTrace(); + + _idTracker = [[XMPPIDTracker alloc] initWithStream:xmppStream dispatchQueue:moduleQueue]; +} + +- (void)willDeactivate +{ + XMPPLogTrace(); + + [_idTracker removeAllIDs]; + _idTracker = nil; +} + +#pragma mark - Public Methods + +- (BOOL)startFileTransfer:(NSError **)errPtr +{ + XMPPLogTrace(); + + if (!xmppStream.isConnected) { + if (errPtr) { + NSString *errMsg = @"You must be connected to send a file"; + *errPtr = [self localErrorWithMessage:errMsg code:-1]; + } + + return NO; + } + + if (!_outgoingData) { + if (errPtr) { + NSString *errMsg = @"You must provide data to be sent."; + *errPtr = [self localErrorWithMessage:errMsg code:-1]; + } + + return NO; + } + + if (!_recipientJID || ![_recipientJID isFull]) { + if (errPtr) { + NSString *errMsg = @"You must provide a recipient (including a resource)."; + *errPtr = [self localErrorWithMessage:errMsg code:-1]; + } + + return NO; + } + + if (self.disableSOCKS5 && self.disableIBB) { + if (errPtr) { + NSString *errMsg = @"Both SOCKS5 and IBB transfers are disabled."; + *errPtr = [self localErrorWithMessage:errMsg code:-1]; + } + + return NO; + } + + dispatch_block_t block = ^{ + @autoreleasepool { + [self queryRecipientDiscoInfo]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); + + return YES; +} + +- (BOOL)sendData:(NSData *)data toRecipient:(XMPPJID *)recipient +{ + return [self sendData:data named:nil toRecipient:recipient description:nil error:nil]; +} + +- (BOOL)sendData:(NSData *)data + named:(NSString *)name + toRecipient:(XMPPJID *)recipient + description:(NSString *)description + error:(NSError **)errPtr +{ + self.outgoingData = data; + self.outgoingFileName = name; + self.recipientJID = recipient; + self.outgoingFileDescription = description; + + return [self startFileTransfer:errPtr]; +} + + +#pragma mark - Private Methods + +/** +* This method sends a `disco#info` query to the recipient. This is done to +* ensure they support file transfer, SOCKS5, and IBB. +* +* The request will look like the following: +* +* +* +* +* +* @see handleRecipientDiscoInfoQueryIQ:withInfo: +*/ +- (void)queryRecipientDiscoInfo +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + XMPPIQ *iq = [XMPPIQ iqWithType:@"get" + to:_recipientJID + elementID:[xmppStream generateUUID]]; + NSXMLElement *query = [NSXMLElement elementWithName:@"query" + xmlns:XMPPDiscoInfoNamespace]; + [iq addChild:query]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleRecipientDiscoInfoQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method is responsible for sending the Stream Initiation Offer as +* described in Examples 1 and 3 of XEP-0096. Both SOCKS5 bytestreams (XEP-0065) +* and IBB (XEP-0047) are sent as options. The default, per XEP-0096 3.1, is +* SOCKS5, with IBB as the fallback. +* +* The outgoing IQ will be similar to the one below: +* +* +* +* +* We should destroy this, right? +* +* +* +* +* +* +* +* +* +* +* +* +* @see handleSIOfferQueryIQ:withInfo: +*/ +- (void)querySIOffer +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + XMPPIQ *iq = [XMPPIQ iqWithType:@"set" + to:_recipientJID + elementID:[xmppStream generateUUID]]; + [iq addAttributeWithName:@"from" stringValue:xmppStream.myJID.full]; + + // Store the sid; we'll need this later + self.sid = [xmppStream generateUUID]; + + NSXMLElement *si = [NSXMLElement elementWithName:@"si" xmlns:XMPPSINamespace]; + [si addAttributeWithName:@"id" stringValue:self.sid]; + [si addAttributeWithName:@"profile" stringValue:XMPPSIProfileFileTransferNamespace]; + [iq addChild:si]; + + // Generate a random filename if one isn't provided + NSString *fileName; + if (_outgoingFileName) { + + // If there is a name provided, but a random one should be created, we'll keep the file ext. + if (_shouldGenerateRandomName) { + NSString *ext = [[_outgoingFileName componentsSeparatedByString:@"."] lastObject]; + fileName = [NSString stringWithFormat:@"%@.%@", [xmppStream generateUUID], ext]; + } else { + fileName = _outgoingFileName; + } + } else { + fileName = [xmppStream generateUUID]; + } + + NSXMLElement *file = [NSXMLElement elementWithName:@"file" + xmlns:XMPPSIProfileFileTransferNamespace]; + [file addAttributeWithName:@"name" stringValue:fileName]; + [file addAttributeWithName:@"size" + stringValue:[[NSString alloc] initWithFormat:@"%lu", + (unsigned long) [_outgoingData length]]];//TODO + [si addChild:file]; + + // Only include description if it's provided + if (_outgoingFileDescription) { + NSXMLElement *desc = [NSXMLElement elementWithName:@"desc" + stringValue:_outgoingFileDescription]; + [file addChild:desc]; + } + + NSXMLElement *feature = [NSXMLElement elementWithName:@"feature" + xmlns:XMPPFeatureNegNamespace]; + [si addChild:feature]; + + NSXMLElement *x = [NSXMLElement elementWithName:@"x" xmlns:@"jabber:x:data"]; + [x addAttributeWithName:@"type" stringValue:@"form"]; + [feature addChild:x]; + + NSXMLElement *field = [NSXMLElement elementWithName:@"field"]; + [field addAttributeWithName:@"var" stringValue:@"stream-method"]; + [field addAttributeWithName:@"type" stringValue:@"list-single"]; + [x addChild:field]; + + // We support SOCKS5 + if (!self.disableSOCKS5) { + NSXMLElement *option = [NSXMLElement elementWithName:@"option"]; + [field addChild:option]; + NSXMLElement *value = [NSXMLElement elementWithName:@"value" + stringValue:XMPPBytestreamsNamespace]; + [option addChild:value]; + } + + // We support IBB + if (!self.disableIBB) { + NSXMLElement *option2 = [NSXMLElement elementWithName:@"option"]; + [field addChild:option2]; + NSXMLElement *value2 = [NSXMLElement elementWithName:@"value" + stringValue:XMPPIBBNamespace]; + [option2 addChild:value2]; + } + + [_idTracker addElement:iq + target:self + selector:@selector(handleSIOfferQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method begins the process of collecting streamhosts to send to the +* recipient. The first (and preferred) streamhost is the sender's local +* IP Address and a random local port. If the recipient is able to connect +* using this streamhost, the bytestream should be directly between clients and +* not require the use of a proxy. +*/ +- (void)collectStreamHosts +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + _localIPAddress = [self getIPAddress:YES]; + _localPort = [XMPPOutgoingFileTransfer getRandomPort]; + + _streamhosts = [NSMutableArray new]; + + // Don't send direct streamhost details if disabled. + if (!self.disableDirectTransfers) { + NSXMLElement *streamHost = [NSXMLElement elementWithName:@"streamhost"]; + [streamHost addAttributeWithName:@"jid" stringValue:xmppStream.myJID.full]; + [streamHost addAttributeWithName:@"host" stringValue:_localIPAddress]; + [streamHost addAttributeWithName:@"port" intValue:_localPort]; + [_streamhosts addObject:streamHost]; + } + + [self queryProxyDiscoItems]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method queries the server to determine what its services are, hopefully +* finding that one of them is a proxy. A `disco#items` query is sent to the +* domain of the file transfer initiator. +* +* @see handleProxyDiscoItemsQueryIQ:withInfo: +*/ +- (void)queryProxyDiscoItems +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + NSString *toStr = xmppStream.myJID.domain; + NSXMLElement *query = [NSXMLElement elementWithName:@"query" + xmlns:XMPPDiscoItemsNamespace]; + XMPPIQ *iq = [XMPPIQ iqWithType:@"get" + to:[XMPPJID jidWithString:toStr] + elementID:[xmppStream generateUUID] + child:query]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleProxyDiscoItemsQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method queries a JID directly to determine whether or not it is a proxy +* service. The provided JID will be in the form `subdomain.domain.com`, likely +* `proxy.domain.com`. This method will be called for each service found at the +* initiator's server until a proxy service is found or all services have been +* exhausted. +* +* @see handleProxyDiscoInfoQueryIQ:withInfo: +*/ +- (void)queryProxyDiscoInfoWithJID:(XMPPJID *)jid +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + XMPPIQ *iq = [XMPPIQ iqWithType:@"get" + to:jid + elementID:[xmppStream generateUUID]]; + NSXMLElement *query = [NSXMLElement elementWithName:@"query" + xmlns:XMPPDiscoInfoNamespace]; + [iq addChild:query]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleProxyDiscoInfoQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method queries a JID directly to determine its address and port. It has +* already been established that the provided JID is indeed a proxy. We merely +* need to know how to connect. +* +* @see handleProxyAddressQueryIQ:withInfo: +*/ +- (void)queryProxyAddressWithJID:(XMPPJID *)jid +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + XMPPIQ *iq = [XMPPIQ iqWithType:@"get" + to:jid + elementID:[xmppStream generateUUID]]; + NSXMLElement *query = [NSXMLElement elementWithName:@"query" + xmlns:XMPPBytestreamsNamespace]; + [iq addChild:query]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleProxyAddressQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method sends the list of streamhosts to the recipient and waits for a +* connection on one of them. +* +* One of these streamhosts will be a local IP address of the sender. If either +* or both of the parties are behind a Network Address Translation (NAT) device, +* this will not work (provided that they aren't on the same Local Area Network +* (LAN). In theory, this means that if both devices are on cellular data, they +* should be able to establish a direct connection. If one (or both) are on wifi, +* either a proxy streamhost will have to be used or IBB will have to be used. +*/ +- (void)sendStreamHostsAndWaitForConnection +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (_streamhosts.count < 1) { + NSString *errMsg = + [NSString stringWithFormat:@"Unable to send streamhosts to %@", _recipientJID.full]; + [self failWithReason:errMsg error:nil]; + return; + } + + XMPPIQ *iq = [XMPPIQ iqWithType:@"set" + to:_recipientJID + elementID:[xmppStream generateUUID]]; + [iq addAttributeWithName:@"xmlns" stringValue:@"jabber:client"]; + [iq addAttributeWithName:@"from" stringValue:xmppStream.myJID.full]; + + NSXMLElement *query = [NSXMLElement elementWithName:@"query" + xmlns:XMPPBytestreamsNamespace]; + [query addAttributeWithName:@"sid" stringValue:self.sid]; + + for (NSXMLElement *streamhost in _streamhosts) { + [query addChild:streamhost]; + } + + [iq addChild:query]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleSentStreamhostsQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + // Send the list of streamhosts to the recipient + [xmppStream sendElement:iq]; + + + NSAssert(_asyncSocket == nil, @"_asyncSocket should be nil at this point."); + + // Create a socket to listen for a direct connection + _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self + delegateQueue:moduleQueue]; + NSError *error; + + if (![_asyncSocket acceptOnPort:_localPort error:&error]) { + NSString *errMsg = [NSString stringWithFormat:@"Failed to open port %d", _localPort]; + [self failWithReason:errMsg error:error]; + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + + +#pragma mark - IBB Transfer + +/** +* This method is responsible for opening a new In-Band Bytestream, as shown in +* XEP-0047 Example 1. We *MUST* send the same sid inside the stanza +* that was used in the SI offer. +* +* The outgoing IQ will be similar to the following: +* +* +* +* +* +* @see handleInitialIBBQueryIQ:withInfo: +*/ +- (void)beginIBBTransfer +{ + + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + XMPPIQ *iq = [XMPPIQ iqWithType:@"set" + to:_recipientJID + elementID:[xmppStream generateUUID]]; + + NSXMLElement *open = [NSXMLElement elementWithName:@"open" xmlns:XMPPIBBNamespace]; + [open addAttributeWithName:@"block-size" intValue:_blockSize]; + [open addAttributeWithName:@"sid" stringValue:self.sid]; + [open addAttributeWithName:@"stanza" stringValue:@"iq"]; + [iq addChild:open]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleInitialIBBQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + + // Convert our data to base64 for the IBB transmission + _outgoingDataBase64 = [_outgoingData base64EncodedStringWithOptions:0]; + _totalDataSize = _outgoingDataBase64.length; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method handles the response to a query matching Example 1. Initiator +* requests session (XEP-0047). +* +* @see beginIBBTransfer +* +* The possible responses are described in Examples 2-5 of XEP-0047. +*/ +- (void)handleInitialIBBQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for response to IBB intiation."; + [self failWithReason:errMsg error:nil]; + } + + NSXMLElement *errorElem = [iq elementForName:@"error"]; + + if (errorElem) { + NSString *errType = [errorElem attributeStringValueForName:@"type"]; + + // Handle Example 3 and 5 + if ([errType isEqualToString:@"cancel"]) { + NSString *errMsg = [NSString stringWithFormat:@"Error initiating IBB: %@", + [errorElem childAtIndex:0].name]; + [self failWithReason:errMsg error:nil]; + return_from_block; + } + + // Handle Example 4. We'll divide the block-size by 4 and try again. + if ([errType isEqualToString:@"modify"] + && [[errorElem childAtIndex:0].name isEqualToString:@"resource-constraint"]) { + XMPPLogInfo(@"Responder prefers smaller IBB chunks. Shrinking block-size and retrying"); + _blockSize /= 2; + [self beginIBBTransfer]; + return_from_block; + } + } + + // Handle Example 2. Responder accepts session + if (iq.childCount == 0) { + XMPPLogVerbose(@"Responder has accepted IBB session. Begin sending data"); + [self sendIBBData]; + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* Sends the data to the recipient via IBB. This method will continue until it +* has verified that all the data has been sent, it fails, or receives an error +* from the recipient. It will close the IBB stream upon completion. +* +* Example 6. Sending data in an IQ stanza (XEP-0047) +* +* +* +* qANQR1DBwU4DX7jmYZnncmUQB/9KuKBddzQH+tZ1ZywKK0yHKnq57kWq+RFtQdCJ +* WpdWpR0uQsuJe7+vh3NWn59/gTc5MDlX8dS9p0ovStmNcyLhxVgmqS8ZKhsblVeu +* IpQ0JgavABqibJolc3BKrVtVV1igKiX/N7Pi8RtY1K18toaMDhdEfhBRzO/XB0+P +* AQhYlRjNacGcslkhXqNjK5Va4tuOAPy2n1Q8UUrHbUd0g+xJ9Bm0G0LZXyvCWyKH +* kuNEHFQiLuCY6Iv0myq6iX6tjuHehZlFSh80b5BVV9tNLwNR5Eqz1klxMhoghJOA +* +* +* +* @see handleIBBTransferQueryIQ:withInfo: +*/ +- (void)sendIBBData +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (_sentDataSize < _totalDataSize) { + XMPPIQ *iq = [XMPPIQ iqWithType:@"set" + to:_recipientJID + elementID:[xmppStream generateUUID]]; + NSXMLElement *data = [NSXMLElement elementWithName:@"data" xmlns:XMPPIBBNamespace]; + [data addAttributeWithName:@"sid" stringValue:self.sid]; + [data addAttributeWithName:@"seq" intValue:_outgoingDataBlockSeq++]; + + // Get the base64 data for our block + NSUInteger length = _sentDataSize + _blockSize > _totalDataSize ? + _totalDataSize - _sentDataSize : _blockSize; + NSRange range = NSMakeRange(_sentDataSize, length); + + NSString *dataString = [_outgoingDataBase64 substringWithRange:range]; + XMPPLogVerbose(@"Uploading %lu/%lu bytes in IBB transfer.", (unsigned long) _sentDataSize, + (unsigned long) _totalDataSize); + + [data setStringValue:dataString]; + [iq addChild:data]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleIBBTransferQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + } else { + XMPPLogInfo(@"IBB file transfer complete. Closing stream..."); + + // All the data has been sent. Alert the delegate that the transfer + // was successful and close the stream. + [multicastDelegate xmppOutgoingFileTransferDidSucceed:self]; + [self closeIBB]; + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* Handles the response from the data recipient during an IBB file transfer. The +* recipient should be sending back a childless result IQ confirming that they +* received the data we sent. We will wait until receiving this IQ before +* sending the next block of data. +* +* Example 7. Acknowledging data received via IQ (XEP-0047) +* +* +* +* @see sendIBBData +*/ +- (void)handleIBBTransferQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for response to IBB sent data."; + [self failWithReason:errMsg error:nil]; + } + + NSXMLElement *errorElem = [iq elementForName:@"error"]; + + // Handle dropped connection or recipient offline. + if (errorElem) { + NSString *errMsg = [NSString stringWithFormat:@"Error transferring with IBB: %@", + [errorElem childAtIndex:0]]; + NSError *err = [self localErrorWithMessage:errMsg code:-1]; + + NSString *reason = + @"The recipient might be offline, the connection was interrupted, or the transfer was canceled."; + [self failWithReason:reason error:err]; + return; + } + + // Handle the scenario when the recipient closes the bytestream. + NSXMLElement *close = [iq elementForName:@"close"]; + if (close) { + if (_sentDataSize >= _totalDataSize) { + // We can assume the transfer was successful. + [multicastDelegate xmppOutgoingFileTransferDidSucceed:self]; + [multicastDelegate xmppOutgoingFileTransferIBBClosed:self]; + + // As per Examples 8-9 (XEP-0047), we SHOULD send the following + // response to let the other party know it's alright to close the + // bytestream. There's no reason to track it, however. + // + // + + XMPPIQ *resultIq = [XMPPIQ iqWithType:@"result" + to:_recipientJID + elementID:iq.elementID]; + [xmppStream sendElement:resultIq]; + } else { + // There must have been a reason to close, but we don't know it. + // Therefore, the transfer might not have been successful. + [self failWithReason:@"Recipient closed IBB stream." error:nil]; + [multicastDelegate xmppOutgoingFileTransferIBBClosed:self]; + } + } + + // At this point, we're assuming that we've received the stanza shown + // above and the recipient has successfully received the data we sent, + // so we should now send them the next block of data. + _sentDataSize += _blockSize; + [self sendIBBData]; + + XMPPLogVerbose( + @"Received response signifying successful IBB stanza. Sending the next block"); + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* XEP-0047 Example 8. Closing the bytestream +* +* Sends an IQ to the recipient stating that the bytestream will be closed. As +* per the protocol, we SHOULD wait for an IQ response before we can consider +* the bytestream to be closed. +* +* Note that the 'sid' must be included. +* +* @see handleCloseIBBQueryIQ:withInfo: +*/ +- (void)closeIBB +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + XMPPIQ *iq = [XMPPIQ iqWithType:@"set" + to:_recipientJID + elementID:[xmppStream generateUUID]]; + NSXMLElement *close = [NSXMLElement elementWithName:@"close" xmlns:XMPPIBBNamespace]; + [close addAttributeWithName:@"sid" stringValue:self.sid]; + [iq addChild:close]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleCloseIBBQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* Handles the response of our query to close the IBB. When it gets a response, +* it merely changes the state and logs that the stream is closed. a successful +* response will look like XEP-0047 Example 9. +*/ +- (void)handleCloseIBBQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for close IBB response."; + [self failWithReason:errMsg error:nil]; + } + + // The protocol states that we might receive an + // response, so we'll just ignore that here + NSXMLElement *errorElem = [iq elementForName:@"error"]; + if (errorElem && ![errorElem.name isEqualToString:@"item-not-found"]) { + NSString *errMsg = [errorElem.children componentsJoinedByString:@", "]; + NSError *err = [self localErrorWithMessage:errMsg + code:[errorElem attributeIntValueForName:@"code"]]; + [self failWithReason:errMsg error:err]; + return_from_block; + } + + // We're assuming that if it makes it this far, it's the response we want + [multicastDelegate xmppOutgoingFileTransferIBBClosed:self]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + + +#pragma mark - Response Handling + +/** +* This method handles the response of our `disco#info` query sent to the file +* recipient. We ensure that the recipient has the capabilities for our transfer +* before sending an SI offer. +* +* +* +* +* +* +* +* +* +* +*/ +- (void)handleRecipientDiscoInfoQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + XMPPLogInfo(@"iq: %@, info: %@", iq, info); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for recipient `disco#info` response."; + [self failWithReason:errMsg error:nil]; + } + + NSXMLElement *errorElem = [iq elementForName:@"error"]; + + if (errorElem) { + NSString *errMsg = [errorElem.children componentsJoinedByString:@", "]; + NSError *err = [self localErrorWithMessage:errMsg + code:[errorElem attributeIntValueForName:@"code"]]; + [self failWithReason:errMsg error:err]; + return_from_block; + } + + NSXMLElement *query = [iq elementForName:@"query"]; + + // We're checking to see if the recipient has the features we need + BOOL hasSI = NO; + BOOL hasFT = NO; + BOOL hasSOCKS5 = NO; + BOOL hasIBB = NO; + + NSArray *features = [query elementsForName:@"feature"]; + for (NSXMLElement *feature in features) { + NSString *var = [feature attributeStringValueForName:@"var"]; + if ([var isEqualToString:XMPPSINamespace]) hasSI = YES; + if ([var isEqualToString:XMPPSIProfileFileTransferNamespace]) hasFT = YES; + if ([var isEqualToString:XMPPBytestreamsNamespace]) hasSOCKS5 = YES; + if ([var isEqualToString:XMPPIBBNamespace]) hasIBB = YES; + } + + hasSOCKS5 = hasSI && hasFT && hasSOCKS5; + hasIBB = hasSI && hasFT && hasIBB; + + if (!hasSOCKS5 || !hasIBB) { + NSString *errMsg = + @"Unable to send SI offer; the recipient doesn't have the required features."; + XMPPLogInfo(@"%@: %@", THIS_FILE, errMsg); + + NSError *err = [self localErrorWithMessage:errMsg code:-1]; + [multicastDelegate xmppOutgoingFileTransfer:self didFailWithError:err]; + + return_from_block; + } + + [self querySIOffer]; + + // TODO: + // The following lines are currently useless. Maybe at some point I'll + // add the ability to restart the transfer using IBB if bytestreams + // fail, but only if the stream-method is available. + if (hasSOCKS5) { + _streamMethods |= XMPPFileTransferStreamMethodBytestreams; + } + + if (hasIBB) { + _streamMethods |= XMPPFileTransferStreamMethodIBB; + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method is responsible for handling the response to the Stream Initiation +* Offer that will be in the form described in Examples 2 and 4 of XEP-0096. +* Depending on the response, this method will trigger an error or begin the +* transfer process using either SOCKS5 or IBB (whichever is sent back first). +* +* The response should be in a similar format to that which is shown below: +* +* +* +* +* +* +* http://jabber.org/protocol/bytestreams +* +* +* +* +* +*/ +- (void)handleSIOfferQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^void { + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for SI offer response."; + [self failWithReason:errMsg error:nil]; + } + + NSXMLElement *errorElem = [iq elementForName:@"error"]; + + if (errorElem) { + NSString *errMsg = [errorElem.children componentsJoinedByString:@", "]; + NSError *err = [self localErrorWithMessage:errMsg + code:[errorElem attributeIntValueForName:@"code"]]; + [self failWithReason:@"There was an issue with the SI offer." error:err]; + return_from_block; + } + + NSXMLElement *si = iq.childElement; + NSXMLElement *feature = (DDXMLElement *) [si childAtIndex:0]; + NSXMLElement *x = (DDXMLElement *) [feature childAtIndex:0]; + NSXMLElement *field = (DDXMLElement *) [x childAtIndex:0]; + NSXMLElement *value = (DDXMLElement *) [field childAtIndex:0]; + + if ([[value stringValue] isEqualToString:XMPPBytestreamsNamespace]) { + XMPPLogVerbose(@"The recipient has confirmed the use of SOCKS5. Starting transfer..."); + [self collectStreamHosts]; + } else if ([[value stringValue] isEqualToString:XMPPIBBNamespace]) { + XMPPLogVerbose(@"The recipient has confirmed the use of IBB. Beginning IBB transfer"); + [self beginIBBTransfer]; + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method handles the server's response to the `disco#items` query sent +* before. It iterates through the results and queries each JID to determine +* whether or not it is a proxy service. +* +* @see queryProxyDiscoInfoWithJID: +*/ +- (void)handleProxyDiscoItemsQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for proxy `disco#items` response."; + [self failWithReason:errMsg error:nil]; + } + + NSXMLElement *errorElem = [iq elementForName:@"error"]; + + if (errorElem) { + NSString *errMsg = [errorElem.children componentsJoinedByString:@", "]; + NSError *err = [self localErrorWithMessage:errMsg + code:[errorElem attributeIntValueForName:@"code"]]; + [self failWithReason:@"There was an error with the disco#items request." error:err]; + return_from_block; + } + + NSXMLElement *query = [iq elementForName:@"query" xmlns:XMPPDiscoItemsNamespace]; + if (!query) return; + + NSArray *items = [query elementsForName:@"item"]; + + for (NSXMLElement *item in items) { + XMPPJID *itemJid = [XMPPJID jidWithString:[item attributeStringValueForName:@"jid"]]; + + if (itemJid) { + XMPPLogVerbose(@"Found service %@. Querying to see if it's a proxy.", itemJid.full); + [self queryProxyDiscoInfoWithJID:itemJid]; + } + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method handles the server's response to the `disco#info` query sent +* before. It determines whether or not the service is indeed a proxy. If it is, +* the service is queried for its address and port. +* +* @see queryProxyAddressWithJID +*/ +- (void)handleProxyDiscoInfoQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for proxy `disco#info` response."; + [self failWithReason:errMsg error:nil]; + } + + NSXMLElement *errorElem = [iq elementForName:@"error"]; + + if (errorElem) { + NSString *errMsg = [errorElem.children componentsJoinedByString:@", "]; + NSError *err = [self localErrorWithMessage:errMsg + code:[errorElem attributeIntValueForName:@"code"]]; + [self failWithReason:@"There was an error with the disco#info request." error:err]; + return_from_block; + } + + NSXMLElement *query = [iq elementForName:@"query" xmlns:XMPPDiscoInfoNamespace]; + NSArray *identities = [query elementsForName:@"identity"]; + + for (NSXMLElement *identity in identities) { + NSString *category = [identity attributeStringValueForName:@"category"]; + NSString *type = [identity attributeStringValueForName:@"type"]; + + if ([category isEqualToString:@"proxy"] && [type isEqualToString:@"bytestreams"]) { + [self queryProxyAddressWithJID:iq.from]; + } + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method handles the server's response to the address query sent before. +* If there is no error, we assume that we were sent an address and a port in +* the form of a streamhost and send the streamhosts to the recipient to begin +* the actual connection process. +* +* @see sendStreamHostsAndWaitForConnection +*/ +- (void)handleProxyAddressQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for proxy address discovery response."; + [self failWithReason:errMsg error:nil]; + } + + NSXMLElement *errorElem = [iq elementForName:@"error"]; + + if (errorElem) { + NSString *errMsg = [errorElem.children componentsJoinedByString:@", "]; + NSError *err = [self localErrorWithMessage:errMsg + code:[errorElem attributeIntValueForName:@"code"]]; + [self failWithReason:@"There was an issue with the proxy address query." error:err]; + return_from_block; + } + + NSXMLElement *query = [iq elementForName:@"query" xmlns:XMPPBytestreamsNamespace]; + NSXMLElement *streamHost = [query elementForName:@"streamhost"]; + + if (!streamHost) { + [self failWithReason:@"There must be at least one streamhost." error:nil]; + return_from_block; + } + + // Detach the streamHost object so it can later be added to a query + [streamHost detach]; + [_streamhosts addObject:streamHost]; + + [self sendStreamHostsAndWaitForConnection]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method handles the server's response after sending the query of +* streamhosts. If there is an error, it alerts the delegate and causes the +* transfer to fail. Otherwise, the connection will proceed and the data will be +* written to the bytestream. +*/ +- (void)handleSentStreamhostsQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + NSXMLElement *errorElem = [iq elementForName:@"error"]; + + if (errorElem) { + NSString *errMsg = [errorElem.children componentsJoinedByString:@", "]; + NSError *err = [self localErrorWithMessage:errMsg + code:[errorElem attributeIntValueForName:@"code"]]; + [self failWithReason:@"There was an issue with sending the streamhosts." error:err]; + return_from_block; + } + + // Check for + // + // We're expecting something like: + // + // + // + // + // + // + + NSXMLElement *query = iq.childElement; + NSXMLElement *streamhostUsed = [query elementForName:@"streamhost-used"]; + + NSString *jid = [streamhostUsed attributeStringValueForName:@"jid"]; + XMPPLogVerbose(@"%@: streamhost-used received with jid: %@", THIS_FILE, jid); + + if ([jid isEqualToString:xmppStream.myJID.full]) { + XMPPLogVerbose(@"%@: writing data via direct connection.", THIS_FILE); + [_outgoingSocket writeData:_outgoingData + withTimeout:TIMEOUT_WRITE + tag:SOCKS_TAG_WRITE_DATA]; + return; + } + + XMPPLogVerbose(@"%@: unable use a direct connection; trying the provided streamhost.", + THIS_FILE); + + if (_outgoingSocket) { + if (_outgoingSocket.isConnected) { + [_outgoingSocket disconnect]; + } + _outgoingSocket = nil; + } + + // We need to get the streamhost which we discovered earlier as a proxy. + NSXMLElement *proxy; + for (NSXMLElement *streamhost in _streamhosts) { + if ([jid isEqualToString:[streamhost attributeStringValueForName:@"jid"]]) { + proxy = streamhost; + _proxyJID = [XMPPJID jidWithString:jid]; + break; + } + } + + if (_asyncSocket) { + [_asyncSocket setDelegate:nil]; + [_asyncSocket disconnect]; + } + + if (!_asyncSocket) { + _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self + delegateQueue:_outgoingQueue]; + } else { + [_asyncSocket setDelegate:self]; + } + + NSError *err; + NSString *proxyHost = [proxy attributeStringValueForName:@"host"]; + uint16_t proxyPort = (gl_uint16_t) [proxy attributeUnsignedIntegerValueForName:@"port"]; + + if (![_asyncSocket connectToHost:proxyHost onPort:proxyPort error:&err]) { + [self failWithReason:@"Unable to connect to proxy." error:err]; + return_from_block; + } + + _transferState = XMPPOFTStateConnectingToProxy; + // See the GCDAsyncSocket Delegate for the next steps. + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method handles the server's response after sending the IQ +* query as described in XEP-0065 Example 24. +* +* If the response is valid (Example 25), the actual transfer of data begins. +*/ +- (void)handleSentActivateQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *)info +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + if (!iq) { + // If we're inside this block, it means that the timeout has been + // fired and we need to force a failure + NSString *errMsg = @"Timeout waiting for sent activate response."; + [self failWithReason:errMsg error:nil]; + } + + XMPPLogVerbose(@"Receive response to activate. Starting the actual data transfer now..."); + [_asyncSocket writeData:_outgoingData withTimeout:TIMEOUT_WRITE tag:SOCKS_TAG_WRITE_DATA]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + + +#pragma mark - Util Methods + +- (NSError *)localErrorWithMessage:(NSString *)msg code:(NSInteger)code +{ + NSDictionary *errInfo = @{NSLocalizedDescriptionKey : [msg copy]}; + return [NSError errorWithDomain:XMPPOutgoingFileTransferErrorDomain + code:code + userInfo:errInfo]; +} + +- (NSString *)getIPAddress:(BOOL)preferIPv4 +{ + NSArray *searchArray; + + if (preferIPv4) { + searchArray = @[IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, + IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6]; + } else { + searchArray = @[IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, + IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4]; + } + + NSDictionary *addresses = [self getIPAddresses]; + + __block NSString *address; + [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) { + address = addresses[key]; + if (address) *stop = YES; + }]; + + return address; +} + +- (NSDictionary *)getIPAddresses +{ + NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8]; + + // Retrieve the current interfaces — returns 0 on success + struct ifaddrs *interfaces; + if (!getifaddrs(&interfaces)) { + // Loop through linked list of interfaces + struct ifaddrs *curr; + + for (curr = interfaces; curr; curr = curr->ifa_next) { + if (!curr->ifa_flags & IFF_UP) { + continue; + } + + const struct sockaddr_in *addr = (const struct sockaddr_in *) curr->ifa_addr; + char addr_buf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; + + if (addr && (addr->sin_family == AF_INET || addr->sin_family == AF_INET6)) { + NSString *name = [NSString stringWithUTF8String:curr->ifa_name]; + NSString *type; + + if (addr->sin_family == AF_INET) { + if (inet_ntop(AF_INET, &addr->sin_addr, addr_buf, INET_ADDRSTRLEN)) { + type = IP_ADDR_IPv4; + } + } else { + const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) curr->ifa_addr; + + if (inet_ntop(AF_INET6, &addr6->sin6_addr, addr_buf, INET6_ADDRSTRLEN)) { + type = IP_ADDR_IPv6; + } + } + + if (type) { + NSString *key = [NSString stringWithFormat:@"%@/%@", name, type]; + addresses[key] = [NSString stringWithUTF8String:addr_buf]; + } + } + } + + freeifaddrs(interfaces); + } + + return addresses.count ? addresses : nil; +} + +/** +* Returns a random port number between 1024 and 49151, since these are the +* values available to use as ports. +*/ ++ (uint16_t)getRandomPort +{ + int port = arc4random_uniform(49151); + return (uint16_t) (port < 1024 ? port + 1024 : port); +} + +/** +* This method returns the SHA1 hash as per XEP-0065. +* +* The [address] MUST be SHA1(SID + Initiator JID + Target JID) and the output +* is hexadecimal encoded (not binary). +* +* Because this is an outgoing file transfer, we are always the initiator. +*/ +- (NSData *)sha1Hash +{ + NSString *hashMe = + [NSString stringWithFormat:@"%@%@%@", self.sid, xmppStream.myJID.full, _recipientJID.full]; + NSData *hashRaw = [[hashMe dataUsingEncoding:NSUTF8StringEncoding] xmpp_sha1Digest]; + NSData *hash = [[hashRaw xmpp_hexStringValue] dataUsingEncoding:NSUTF8StringEncoding]; + + XMPPLogVerbose(@"%@: hashMe : %@", THIS_FILE, hashMe); + XMPPLogVerbose(@"%@: hashRaw: %@", THIS_FILE, hashRaw); + XMPPLogVerbose(@"%@: hash : %@", THIS_FILE, hash); + + return hash; +} + +/** +* This method is called to clean up everything if the transfer fails. +*/ +- (void)failWithReason:(NSString *)causeOfFailure error:(NSError *)error +{ + XMPPLogTrace(); + XMPPLogInfo(@"Outgoing file transfer failed because: %@", causeOfFailure); + + if (!error && causeOfFailure) { + NSDictionary *errInfo = @{NSLocalizedDescriptionKey : causeOfFailure}; + error = [NSError errorWithDomain:XMPPOutgoingFileTransferErrorDomain + code:-1 + userInfo:errInfo]; + } + + if (_outgoingSocket) { + if (_outgoingSocket.isConnected) { + [_outgoingSocket disconnect]; + } + _outgoingSocket = nil; + } + + if (_asyncSocket) { + if (_asyncSocket.isConnected) { + [_asyncSocket disconnect]; + } + _asyncSocket = nil; + } + + [multicastDelegate xmppOutgoingFileTransfer:self didFailWithError:error]; +} + + +#pragma mark - XMPPStreamDelegate + +/** +* Default XMPPStreamDelegate method. We need this to handle the IQ responses. +*/ +- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq +{ + NSString *type = iq.type; + + if ([type isEqualToString:@"result"] || [type isEqualToString:@"error"]) { + return [_idTracker invokeForElement:iq withObject:iq]; + } + + return NO; +} + + +#pragma mark - GCDAsyncSocketDelegate + +- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket +{ + XMPPLogVerbose(@"Did accept new socket"); + XMPPLogVerbose(@"connected host: %@", newSocket.connectedHost); + XMPPLogVerbose(@"connected port: %hu", newSocket.connectedPort); + + _outgoingSocket = newSocket; + [_outgoingSocket readDataToLength:3 withTimeout:20 tag:SOCKS_TAG_READ_METHOD]; +} + +- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port +{ + XMPPLogVerbose(@"%@: didConnectToHost:%@ port:%d", THIS_FILE, host, port); + + [self socks5WriteProxyMethod]; +} + +- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag +{ + XMPPLogVerbose(@"%@: didReadData:%@ withTag:%ld", THIS_FILE, data, tag); + + switch (tag) { + case SOCKS_TAG_READ_METHOD: + [self socks5ReadMethod:data]; + break; + case SOCKS_TAG_READ_REQUEST: + [self socks5ReadRequest:data]; + break; + case SOCKS_TAG_READ_DOMAIN: + [self socks5ReadDomain:data]; + break; + case SOCKS_TAG_READ_PROXY_METHOD: + [self socks5ReadProxyMethod:data]; + break; + case SOCKS_TAG_READ_PROXY_REPLY: + [self socks5ReadProxyReply:data]; + break; + default: + break; + } +} + +- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag +{ + XMPPLogVerbose(@"%@: didWriteDataWithTag:%ld", THIS_FILE, tag); + + switch (tag) { + case SOCKS_TAG_WRITE_METHOD: + [_outgoingSocket readDataToLength:4 withTimeout:TIMEOUT_READ tag:SOCKS_TAG_READ_REQUEST]; + break; + case SOCKS_TAG_WRITE_PROXY_METHOD: + [_asyncSocket readDataToLength:2 withTimeout:TIMEOUT_READ tag:SOCKS_TAG_READ_PROXY_METHOD]; + break; + case SOCKS_TAG_WRITE_PROXY_CONNECT: + [_asyncSocket readDataToLength:5 withTimeout:TIMEOUT_READ tag:SOCKS_TAG_READ_PROXY_REPLY]; + break; + case SOCKS_TAG_WRITE_DATA: + _transferState = XMPPOFTStateFinished; + [multicastDelegate xmppOutgoingFileTransferDidSucceed:self]; + break; + default: + break; + } +} + +- (NSTimeInterval)socket:(GCDAsyncSocket *)sock +shouldTimeoutReadWithTag:(long)tag + elapsed:(NSTimeInterval)elapsed + bytesDone:(NSUInteger)length +{ + XMPPLogVerbose(@"%@: socket shouldTimeoutReadWithTag:%ld elapsed:%d bytesDone:%d", THIS_FILE, tag, + elapsed, length); + + NSString *reason = [NSString stringWithFormat:@"Read timeout. %d bytes read.", length]; + [self failWithReason:reason error:nil]; + + return 0; +} + +- (NSTimeInterval) socket:(GCDAsyncSocket *)sock +shouldTimeoutWriteWithTag:(long)tag + elapsed:(NSTimeInterval)elapsed + bytesDone:(NSUInteger)length +{ + XMPPLogVerbose(@"%@: socket shouldTimeoutWriteWithTag:%ld elapsed:%f bytesDone:%lu", THIS_FILE, + tag, elapsed, (unsigned long) length); + + NSString *reason = [NSString stringWithFormat:@"Write timeout. %lu bytes written.", + (unsigned long) length]; + [self failWithReason:reason error:nil]; + + return 0; +} + +- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err +{ + XMPPLogVerbose(@"socket did disconnect with error: %@", err); + if (_transferState != XMPPOFTStateFinished) { + [self failWithReason:@"Socket disconnected before transfer completion." error:err]; + } +} + + +#pragma mark - SOCKS5 + +- (void)socks5ReadMethod:(NSData *)incomingData +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // According to the SOCKS5 protocol (http://tools.ietf.org/html/rfc1928), + // we facilitate the role of the 'server' in this scenario, meaning that + // the 'client' has connected to us and written data in the following form: + // + // +----+----------+----------+ + // |VER | NMETHODS | METHODS | + // +----+----------+----------+ + // | 1 | 1 | 1 to 255 | + // +----+----------+----------+ + // + // The VER field should always be set to 5 (for SOCKS v5). + // NMETHODS will always be a single byte and since we really only want this + // to be 1, we're free to ignore it. + // METHODS can have various values, but if it's set to anything other than + // 0 (no authentication), we're going to abort the process. + // + // We're thus expecting: + // + // VER = 5 + // NMETHODS = 1 + // METHODS = 0 + + UInt8 version = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:0]; + UInt8 method = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:2]; + + if (version == 5 && method == 0) { + + // At this point, we've determined that no authentication is required and + // are able to proceed. In order to do so, we need to write data in the + // following form: + // + // +----+--------+ + // |VER | METHOD | + // +----+--------+ + // | 1 | 1 | + // +----+--------+ + // + // The VER will once again be set to 5, and METHOD will be set to 0. + // + // We're sending: + // + // VER = 5 + // METHOD = 0 + + void *byteBuf = malloc(2); + + UInt8 ver = 5; + memcpy(byteBuf, &ver, sizeof(ver)); + + UInt8 mtd = 0; + memcpy(byteBuf + 1, &mtd, sizeof(mtd)); + + NSData *responseData = [NSData dataWithBytesNoCopy:byteBuf length:2 freeWhenDone:YES]; + XMPPLogVerbose(@"%@: writing SOCKS5 auth response: %@", THIS_FILE, responseData); + + [_outgoingSocket writeData:responseData + withTimeout:TIMEOUT_WRITE + tag:SOCKS_TAG_WRITE_METHOD]; + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +- (void)socks5ReadRequest:(NSData *)incomingData +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // The SOCKS request is formed as follows: + // + // +----+-----+-------+------+----------+----------+ + // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | + // +----+-----+-------+------+----------+----------+ + // | 1 | 1 | X'00' | 1 | Variable | 2 | + // +----+-----+-------+------+----------+----------+ + // + // We're expecting: + // + // VER = 5 + // CMD = 1 (connect) + // RSV = 0 (reserved; this will always be 0) + // ATYP = 1 (IPv4), 3 (domain name), or 4 (IPv6) + // DST.ADDR (varies based on ATYP) + // DST.PORT = 0 (according to XEP-0065) + // + // At this stage, we've only actually read 4 bytes from the stream, those + // being VER, CMD, RSV, and ATYP. We need to read ATYP to determine how many + // more bytes we should read. Scenarios listed below: + // + // ATYP = 3 (domain name): Read the next byte which will contain the number + // bytes in the address. Then read that many bytes + + // 2 for the port. Since this is the only type of + // ATYP we want to support, any other fails. We'll go + // ahead and read the whole address and port. It + // should always be 40 bytes long (SHA1). + + UInt8 ver = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:0]; + UInt8 cmd = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:1]; + UInt8 atyp = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:3]; + + if (ver != 5 || cmd != 1) { + [self failWithReason:@"Incorrect SOCKS version or command is not 'CONNECT'." error:nil]; + return; + } + + // Read the length byte + the 40-byte SHA1 + 2-byte address + NSUInteger length = 43; + if (atyp == 3) { + [_outgoingSocket readDataToLength:length + withTimeout:TIMEOUT_READ + tag:SOCKS_TAG_READ_DOMAIN]; + } else { + [self failWithReason:@"ATYP value is invalid." error:nil]; + } + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +- (void)socks5ReadDomain:(NSData *)incomingData +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + NSData *hash = [self sha1Hash]; + + // We need to pull the address data out, which starts after the first byte + // and goes for 40 bytes. + NSRange addrRange = NSMakeRange(1, 40); + if (![hash isEqualToData:[incomingData subdataWithRange:addrRange]]) { + XMPPLogVerbose(@"Addresses don't match. Canceling the SOCKS5 transfer."); + [self failWithReason:@"Addresses don't match." error:nil]; + return; + } + + // We need to next pull the port out and verify that it's 0x00, 0x00. + UInt8 addrPort0 = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:41]; + UInt8 addrPort1 = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:41]; + + if (addrPort0 || addrPort1) { + XMPPLogVerbose(@"Port should always be 0x00. Canceling the SOCKS5 transfer."); + [self failWithReason:@"Port isn't 0x00." error:nil]; + return; + } + + // If the DST.ADDR and DST.PORT are valid, then we proceed with the process. + // We send our reply which is described below. + // + // +----+-----+-------+------+----------+----------+ + // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + // +----+-----+-------+------+----------+----------+ + // | 1 | 1 | X'00' | 1 | Variable | 2 | + // +----+-----+-------+------+----------+----------+ + // + // VER = 5 (SOCKS5) + // REP = 0 (Success) + // RSV = 0 + // ATYP = 3 (Domain) - NOTE: Since we're using ATYP = 3, we must send the + // length of our host in the very next byte. + // BND.ADDR = local IP address + // BND.PORT = 0x00 + // 0x00 + + const char *host = [_localIPAddress UTF8String]; + + NSUInteger numBytes = 5 + strlen(host) + 2; + + void *byteBuf = malloc(numBytes); + + UInt8 ver = 5; + memcpy(byteBuf, &ver, sizeof(ver)); + + UInt8 rep = 0; + memcpy(byteBuf + 1, &rep, sizeof(rep)); + + UInt8 rsv = 0; + memcpy(byteBuf + 2, &rsv, sizeof(rsv)); + + UInt8 atyp = 3; + memcpy(byteBuf + 3, &atyp, sizeof(atyp)); + + UInt8 hostlen = (UInt8) strlen(host); + memcpy(byteBuf + 4, &hostlen, sizeof(hostlen)); + + memcpy(byteBuf + 5, host, hostlen); + + UInt8 port = 0; + memcpy(byteBuf + 5 + hostlen, &port, sizeof(port)); + memcpy(byteBuf + 6 + hostlen, &port, sizeof(port)); + + NSData + *responseData = [NSData dataWithBytesNoCopy:byteBuf length:numBytes freeWhenDone:YES]; + XMPPLogVerbose(@"%@: writing SOCKS5 auth response: %@", THIS_FILE, responseData); + + [_outgoingSocket writeData:responseData + withTimeout:TIMEOUT_WRITE + tag:SOCKS_TAG_WRITE_REPLY]; + + _transferState = XMPPOFTStateSOCKSLive; + + // Now we wait for a IQ stanza before sending the data. + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +- (void)socks5WriteProxyMethod +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // We will attempt anonymous authentication with the proxy. The request is + // the same that we would read if this were a direct connection. The only + // difference is this time we initiate the request as a client rather than + // being a the 'server.' + // + // +----+----------+----------+ + // |VER | NMETHODS | METHODS | + // +----+----------+----------+ + // | 1 | 1 | 1 to 255 | + // +----+----------+----------+ + // + // We're sending: + // + // VER = 5 (SOCKS5) + // NMETHODS = 1 (number of methods) + // METHODS = 0 (no authentication) + + void *byteBuf = malloc(3); + + UInt8 ver = 5; + memcpy(byteBuf, &ver, sizeof(ver)); + + UInt8 nmethods = 1; + memcpy(byteBuf + 1, &nmethods, sizeof(nmethods)); + + UInt8 methods = 0; + memcpy(byteBuf + 2, &methods, sizeof(methods)); + + NSData *data = [NSData dataWithBytesNoCopy:byteBuf length:3 freeWhenDone:YES]; + [_asyncSocket writeData:data withTimeout:TIMEOUT_WRITE tag:SOCKS_TAG_WRITE_PROXY_METHOD]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +- (void)socks5ReadProxyMethod:(NSData *)incomingData +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // We've sent a request to connect with no authentication. This data contains + // the proxy server's response to our request. + // + // +----+--------+ + // |VER | METHOD | + // +----+--------+ + // | 1 | 1 | + // +----+--------+ + // + // We're expecting: + // + // VER = 5 (SOCKS5) + // METHOD = 0 (no authentication) + + UInt8 version = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:0]; + UInt8 method = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:1]; + + if (version != 5 || method) { + [self failWithReason:@"Proxy doesn't allow anonymous authentication." error:nil]; + return; + } + + NSData *hash = [self sha1Hash]; + + // The SOCKS request is formed as follows: + // + // +----+-----+-------+------+----------+----------+ + // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | + // +----+-----+-------+------+----------+----------+ + // | 1 | 1 | X'00' | 1 | Variable | 2 | + // +----+-----+-------+------+----------+----------+ + // + // We're sending: + // + // VER = 5 + // CMD = 1 (connect) + // RSV = 0 (reserved; this will always be 0) + // ATYP = 3 (domain name) + // DST.ADDR (varies based on ATYP) + // DST.PORT = 0 (according to XEP-0065) + // + // Immediately after ATYP, we need to send the length of our address. Because + // SHA1 is always 40 bytes, we simply send this value. After it, we append + // the actual hash and then the port. + + void *byteBuf = malloc(5 + 40 + 2); + + UInt8 ver = 5; + memcpy(byteBuf, &ver, sizeof(ver)); + + UInt8 cmd = 1; + memcpy(byteBuf + 1, &cmd, sizeof(cmd)); + + UInt8 rsv = 0; + memcpy(byteBuf + 2, &rsv, sizeof(rsv)); + + UInt8 atyp = 3; + memcpy(byteBuf + 3, &atyp, sizeof(atyp)); + + UInt8 hashlen = (UInt8) hash.length; + memcpy(byteBuf + 4, &hashlen, sizeof(hashlen)); + + memcpy(byteBuf + 5, hash.bytes, hashlen); + + UInt8 port = 0; + memcpy(byteBuf + 5 + hashlen, &port, sizeof(port)); + memcpy(byteBuf + 6 + hashlen, &port, sizeof(port)); + + NSData *data = [NSData dataWithBytesNoCopy:byteBuf length:47 freeWhenDone:YES]; + [_asyncSocket writeData:data withTimeout:TIMEOUT_WRITE tag:SOCKS_TAG_WRITE_PROXY_CONNECT]; + + XMPPLogVerbose(@"%@: writing connect request: %@", THIS_FILE, data); + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +- (void)socks5ReadProxyReply:(NSData *)incomingData +{ + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + // The server will reply to our connect command with the following: + // + // +----+-----+-------+------+----------+----------+ + // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + // +----+-----+-------+------+----------+----------+ + // | 1 | 1 | X'00' | 1 | Variable | 2 | + // +----+-----+-------+------+----------+----------+ + // + // VER = 5 (SOCKS5) + // REP = 0 (Success) + // RSV = 0 + // ATYP = 3 (Domain) - NOTE: Since we're using ATYP = 3, we must check the + // length of the server's host in the next byte. + + UInt8 ver = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:0]; + UInt8 rep = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:1]; + UInt8 atyp = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:3]; + UInt8 hostlen = [NSNumber xmpp_extractUInt8FromData:incomingData atOffset:4]; + + if (ver != 5 || rep || atyp != 3) { + [self failWithReason:@"Invalid VER, REP, or ATYP." error:nil]; + return; + } + + // Read those bytes off into oblivion... + [_asyncSocket readDataToLength:hostlen + 2 withTimeout:TIMEOUT_READ tag:-1]; + + // According to XEP-0065 Example 23, we don't need to validate the + // address we were sent (at least that is how I interpret it), so we + // can just go ahead and send the IQ query and start + // sending the data once we receive our response. + + NSXMLElement *activate = [NSXMLElement elementWithName:@"activate" + stringValue:_recipientJID.full]; + + NSXMLElement *query = [NSXMLElement elementWithName:@"query" + xmlns:@"http://jabber.org/protocol/bytestreams"]; + [query addAttributeWithName:@"sid" stringValue:self.sid]; + [query addChild:activate]; + + XMPPIQ *iq = [XMPPIQ iqWithType:@"set" + to:_proxyJID + elementID:[xmppStream generateUUID] + child:query]; + + [_idTracker addElement:iq + target:self + selector:@selector(handleSentActivateQueryIQ:withInfo:) + timeout:OUTGOING_DEFAULT_TIMEOUT]; + + [xmppStream sendElement:iq]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +@end From 4ed84843c3749b6ed7937b18b8d72084960939f9 Mon Sep 17 00:00:00 2001 From: Jonathon Staff Date: Sat, 1 Nov 2014 19:52:06 +0800 Subject: [PATCH 002/356] Added XMPPNamespaces --- Core/XMPPNamespaces.h | 24 ++++++++++++++++++++++++ Core/XMPPNamespaces.m | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 Core/XMPPNamespaces.h create mode 100644 Core/XMPPNamespaces.m diff --git a/Core/XMPPNamespaces.h b/Core/XMPPNamespaces.h new file mode 100644 index 0000000000..bd40014763 --- /dev/null +++ b/Core/XMPPNamespaces.h @@ -0,0 +1,24 @@ +// +// Created by Jonathon Staff on 10/22/14. +// Copyright (c) 2014 nplexity, LLC. All rights reserved. +// + +#import + +/** +* This class is provided to house various namespaces that are reused throughout +* the project. Feel free to add to the constants as you see necessary. If a +* particular namespace is only applicable to a particular extension, then it +* should be inside that extension rather than here. +*/ + +extern NSString *const XMPPSINamespace; +extern NSString *const XMPPSIProfileFileTransferNamespace; +extern NSString *const XMPPFeatureNegNamespace; +extern NSString *const XMPPBytestreamsNamespace; +extern NSString *const XMPPIBBNamespace; +extern NSString *const XMPPDiscoItemsNamespace; +extern NSString *const XMPPDiscoInfoNamespace; + +@interface XMPPNamespaces : NSObject +@end \ No newline at end of file diff --git a/Core/XMPPNamespaces.m b/Core/XMPPNamespaces.m new file mode 100644 index 0000000000..1f89a3b285 --- /dev/null +++ b/Core/XMPPNamespaces.m @@ -0,0 +1,19 @@ +// +// Created by Jonathon Staff on 10/22/14. +// Copyright (c) 2014 nplexity, LLC. All rights reserved. +// + +#import "XMPPNamespaces.h" + +NSString *const XMPPSINamespace = @"http://jabber.org/protocol/si"; +NSString *const XMPPSIProfileFileTransferNamespace = + @"http://jabber.org/protocol/si/profile/file-transfer"; +NSString *const XMPPFeatureNegNamespace = @"http://jabber.org/protocol/feature-neg"; +NSString *const XMPPBytestreamsNamespace = @"http://jabber.org/protocol/bytestreams"; +NSString *const XMPPIBBNamespace = @"http://jabber.org/protocol/ibb"; +NSString *const XMPPDiscoItemsNamespace = @"http://jabber.org/protocol/disco#items"; +NSString *const XMPPDiscoInfoNamespace = @"http://jabber.org/protocol/disco#info"; + +@implementation XMPPNamespaces + +@end \ No newline at end of file From 1d5798a099e2bfd423dc238b1ec76381f7b4bbba Mon Sep 17 00:00:00 2001 From: Jonathon Staff Date: Sun, 2 Nov 2014 18:21:10 +0800 Subject: [PATCH 003/356] Updated log levels --- Extensions/FileTransfer/XMPPIncomingFileTransfer.m | 2 +- Extensions/FileTransfer/XMPPOutgoingFileTransfer.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Extensions/FileTransfer/XMPPIncomingFileTransfer.m b/Extensions/FileTransfer/XMPPIncomingFileTransfer.m index 614236e359..2ae65d59b5 100644 --- a/Extensions/FileTransfer/XMPPIncomingFileTransfer.m +++ b/Extensions/FileTransfer/XMPPIncomingFileTransfer.m @@ -15,7 +15,7 @@ #import "NSData+XMPP.h" #if DEBUG -static const int xmppLogLevel = XMPP_LOG_LEVEL_VERBOSE | XMPP_LOG_FLAG_TRACE; +static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; // XMPP_LOG_LEVEL_VERBOSE | XMPP_LOG_FLAG_TRACE; #else static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; #endif diff --git a/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m index 2a56467c1f..57034ae545 100644 --- a/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m +++ b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m @@ -21,7 +21,7 @@ #import "NSData+XMPP.h" #if DEBUG -static const int xmppLogLevel = XMPP_LOG_LEVEL_VERBOSE | XMPP_LOG_FLAG_TRACE; +static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; // XMPP_LOG_LEVEL_VERBOSE | XMPP_LOG_FLAG_TRACE; #else static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; #endif From 2bb249c2e5a007585fdf93ae2a17e237bef9654b Mon Sep 17 00:00:00 2001 From: Jonathon Staff Date: Tue, 4 Nov 2014 22:09:26 +0800 Subject: [PATCH 004/356] Bulletproofing the file transfer extensions --- .../FileTransfer/XMPPIncomingFileTransfer.m | 1 + .../FileTransfer/XMPPOutgoingFileTransfer.m | 127 +++++++++++++++--- 2 files changed, 108 insertions(+), 20 deletions(-) diff --git a/Extensions/FileTransfer/XMPPIncomingFileTransfer.m b/Extensions/FileTransfer/XMPPIncomingFileTransfer.m index 2ae65d59b5..2aa45e27e7 100644 --- a/Extensions/FileTransfer/XMPPIncomingFileTransfer.m +++ b/Extensions/FileTransfer/XMPPIncomingFileTransfer.m @@ -510,6 +510,7 @@ - (void)cleanUp _asyncSocket = nil; } + _streamMethods &= 0; _transferState = XMPPIFTStateNone; _senderJID = nil; _streamhostsQueryId = nil; diff --git a/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m index 57034ae545..1a435d0662 100644 --- a/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m +++ b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m @@ -63,6 +63,7 @@ // XMPP Outgoing File Transfer State typedef NS_ENUM(int, XMPPOFTState) { XMPPOFTStateNone, + XMPPOFTStateStarted, XMPPOFTStateSOCKSLive, XMPPOFTStateConnectingToProxy, XMPPOFTStateFinished @@ -87,6 +88,8 @@ @interface XMPPOutgoingFileTransfer () { XMPPOFTState _transferState; XMPPJID *_proxyJID; + + NSMutableDictionary *_pastRecipients; } @end @@ -107,6 +110,7 @@ - (instancetype)initWithDispatchQueue:(dispatch_queue_t)queue _blockSize = 4096; _transferState = XMPPOFTStateNone; + _pastRecipients = [NSMutableDictionary new]; } return self; } @@ -171,8 +175,36 @@ - (BOOL)startFileTransfer:(NSError **)errPtr return NO; } + if (_transferState != XMPPOFTStateNone) { + if (errPtr) { + NSString *errMsg = @"Transfer already in progress."; + *errPtr = [self localErrorWithMessage:errMsg code:-1]; + } + + return NO; + } + dispatch_block_t block = ^{ @autoreleasepool { + _transferState = XMPPOFTStateStarted; + + if (_pastRecipients[_recipientJID.full]) { + uint8_t methods = (gl_uint8_t) [_pastRecipients[_recipientJID.full] unsignedIntValue]; + + if (methods & XMPPFileTransferStreamMethodBytestreams) { + _streamMethods |= XMPPFileTransferStreamMethodBytestreams; + } + + if (methods & XMPPFileTransferStreamMethodIBB) { + _streamMethods |= XMPPFileTransferStreamMethodIBB; + } + + if (_streamMethods) { + [self querySIOffer]; + return_from_block; + } + } + [self queryRecipientDiscoInfo]; } }; @@ -187,7 +219,12 @@ - (BOOL)startFileTransfer:(NSError **)errPtr - (BOOL)sendData:(NSData *)data toRecipient:(XMPPJID *)recipient { - return [self sendData:data named:nil toRecipient:recipient description:nil error:nil]; + return _transferState != XMPPOFTStateNone ? NO : [self sendData:data + named:nil + toRecipient:recipient + description:nil + error:nil]; + } - (BOOL)sendData:(NSData *)data @@ -196,6 +233,15 @@ - (BOOL)sendData:(NSData *)data description:(NSString *)description error:(NSError **)errPtr { + if (_transferState != XMPPOFTStateNone) { + if (errPtr) { + NSString *errMsg = @"Transfer already in progress."; + *errPtr = [self localErrorWithMessage:errMsg code:-1]; + } + + return NO; + } + self.outgoingData = data; self.outgoingFileName = name; self.recipientJID = recipient; @@ -398,7 +444,10 @@ - (void)collectStreamHosts dispatch_block_t block = ^{ @autoreleasepool { _localIPAddress = [self getIPAddress:YES]; - _localPort = [XMPPOutgoingFileTransfer getRandomPort]; + + if (!_localPort) { + _localPort = [XMPPOutgoingFileTransfer getRandomPort]; + } _streamhosts = [NSMutableArray new]; @@ -564,6 +613,7 @@ - (void)sendStreamHostsAndWaitForConnection [query addAttributeWithName:@"sid" stringValue:self.sid]; for (NSXMLElement *streamhost in _streamhosts) { + [streamhost detach]; [query addChild:streamhost]; } @@ -577,12 +627,12 @@ - (void)sendStreamHostsAndWaitForConnection // Send the list of streamhosts to the recipient [xmppStream sendElement:iq]; - - NSAssert(_asyncSocket == nil, @"_asyncSocket should be nil at this point."); - // Create a socket to listen for a direct connection - _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self - delegateQueue:moduleQueue]; + if (!_asyncSocket) { + _asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self + delegateQueue:moduleQueue]; + } + NSError *error; if (![_asyncSocket acceptOnPort:_localPort error:&error]) { @@ -1041,6 +1091,8 @@ - (void)handleRecipientDiscoInfoQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTracking if (hasIBB) { _streamMethods |= XMPPFileTransferStreamMethodIBB; } + + _pastRecipients[_recipientJID.full] = @(_streamMethods); } }; @@ -1533,21 +1585,57 @@ - (void)failWithReason:(NSString *)causeOfFailure error:(NSError *)error userInfo:errInfo]; } - if (_outgoingSocket) { - if (_outgoingSocket.isConnected) { - [_outgoingSocket disconnect]; - } - _outgoingSocket = nil; - } + [self cleanUp]; + [multicastDelegate xmppOutgoingFileTransfer:self didFailWithError:error]; +} + +/** +* This method is called to clean up everything if the transfer succeeds. +*/ +- (void)transferSuccess +{ + + XMPPLogTrace(); + + dispatch_block_t block = ^{ + @autoreleasepool { + _transferState = XMPPOFTStateFinished; + [multicastDelegate xmppOutgoingFileTransferDidSucceed:self]; + [self cleanUp]; + } + }; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} + +/** +* This method is used to reset the system for receiving new files. +*/ +- (void)cleanUp +{ + XMPPLogTrace(); if (_asyncSocket) { - if (_asyncSocket.isConnected) { - [_asyncSocket disconnect]; - } + [_asyncSocket setDelegate:nil]; + [_asyncSocket disconnect]; _asyncSocket = nil; } - [multicastDelegate xmppOutgoingFileTransfer:self didFailWithError:error]; + if (_outgoingSocket) { + [_outgoingSocket setDelegate:nil]; + [_outgoingSocket disconnect]; + _outgoingSocket = nil; + } + + _streamMethods &= 0; + _transferState = XMPPOFTStateNone; + _totalDataSize = 0; + _outgoingDataBlockSeq = 0; + _sentDataSize = 0; + _outgoingDataBase64 = nil; } @@ -1627,8 +1715,7 @@ - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag [_asyncSocket readDataToLength:5 withTimeout:TIMEOUT_READ tag:SOCKS_TAG_READ_PROXY_REPLY]; break; case SOCKS_TAG_WRITE_DATA: - _transferState = XMPPOFTStateFinished; - [multicastDelegate xmppOutgoingFileTransferDidSucceed:self]; + [self transferSuccess]; break; default: break; @@ -1667,7 +1754,7 @@ - (NSTimeInterval) socket:(GCDAsyncSocket *)sock - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err { XMPPLogVerbose(@"socket did disconnect with error: %@", err); - if (_transferState != XMPPOFTStateFinished) { + if (_transferState != XMPPOFTStateFinished && _transferState != XMPPOFTStateNone) { [self failWithReason:@"Socket disconnected before transfer completion." error:err]; } } From 9799b34652c672e3aff1685fbfe52442259235c6 Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Wed, 12 Nov 2014 10:03:14 +0000 Subject: [PATCH 005/356] Merges #461 Fixes Warnings in Xcode Version 6.1 (6A1052d) Rename XMPPNamespaces to XMPPConstants --- Core/{XMPPNamespaces.h => XMPPConstants.h} | 8 -------- Core/{XMPPNamespaces.m => XMPPConstants.m} | 11 +---------- Extensions/FileTransfer/XMPPIncomingFileTransfer.m | 2 +- Extensions/FileTransfer/XMPPOutgoingFileTransfer.m | 8 +++----- 4 files changed, 5 insertions(+), 24 deletions(-) rename Core/{XMPPNamespaces.h => XMPPConstants.h} (81%) rename Core/{XMPPNamespaces.m => XMPPConstants.m} (77%) diff --git a/Core/XMPPNamespaces.h b/Core/XMPPConstants.h similarity index 81% rename from Core/XMPPNamespaces.h rename to Core/XMPPConstants.h index bd40014763..63e94e0081 100644 --- a/Core/XMPPNamespaces.h +++ b/Core/XMPPConstants.h @@ -1,8 +1,3 @@ -// -// Created by Jonathon Staff on 10/22/14. -// Copyright (c) 2014 nplexity, LLC. All rights reserved. -// - #import /** @@ -19,6 +14,3 @@ extern NSString *const XMPPBytestreamsNamespace; extern NSString *const XMPPIBBNamespace; extern NSString *const XMPPDiscoItemsNamespace; extern NSString *const XMPPDiscoInfoNamespace; - -@interface XMPPNamespaces : NSObject -@end \ No newline at end of file diff --git a/Core/XMPPNamespaces.m b/Core/XMPPConstants.m similarity index 77% rename from Core/XMPPNamespaces.m rename to Core/XMPPConstants.m index 1f89a3b285..d341b56a2b 100644 --- a/Core/XMPPNamespaces.m +++ b/Core/XMPPConstants.m @@ -1,9 +1,4 @@ -// -// Created by Jonathon Staff on 10/22/14. -// Copyright (c) 2014 nplexity, LLC. All rights reserved. -// - -#import "XMPPNamespaces.h" +#import "XMPPConstants.h" NSString *const XMPPSINamespace = @"http://jabber.org/protocol/si"; NSString *const XMPPSIProfileFileTransferNamespace = @@ -13,7 +8,3 @@ NSString *const XMPPIBBNamespace = @"http://jabber.org/protocol/ibb"; NSString *const XMPPDiscoItemsNamespace = @"http://jabber.org/protocol/disco#items"; NSString *const XMPPDiscoInfoNamespace = @"http://jabber.org/protocol/disco#info"; - -@implementation XMPPNamespaces - -@end \ No newline at end of file diff --git a/Extensions/FileTransfer/XMPPIncomingFileTransfer.m b/Extensions/FileTransfer/XMPPIncomingFileTransfer.m index 2aa45e27e7..eabc9a4bfd 100644 --- a/Extensions/FileTransfer/XMPPIncomingFileTransfer.m +++ b/Extensions/FileTransfer/XMPPIncomingFileTransfer.m @@ -8,7 +8,7 @@ #endif #import "XMPPIncomingFileTransfer.h" -#import "XMPPNamespaces.h" +#import "XMPPConstants.h" #import "XMPPLogging.h" #import "idn-int.h" #import "NSNumber+XMPP.h" diff --git a/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m index 1a435d0662..b0e0c9a067 100644 --- a/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m +++ b/Extensions/FileTransfer/XMPPOutgoingFileTransfer.m @@ -9,14 +9,13 @@ #import #import -#import #import #import #import "XMPPLogging.h" #import "XMPPOutgoingFileTransfer.h" #import "XMPPIDTracker.h" #import "idn-int.h" -#import "XMPPNamespaces.h" +#import "XMPPConstants.h" #import "NSNumber+XMPP.h" #import "NSData+XMPP.h" @@ -1727,10 +1726,9 @@ - (NSTimeInterval)socket:(GCDAsyncSocket *)sock elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length { - XMPPLogVerbose(@"%@: socket shouldTimeoutReadWithTag:%ld elapsed:%d bytesDone:%d", THIS_FILE, tag, - elapsed, length); + XMPPLogVerbose(@"%@: socket shouldTimeoutReadWithTag:%ld elapsed:%f bytesDone:%lu", THIS_FILE, tag, elapsed, (unsigned long)length); - NSString *reason = [NSString stringWithFormat:@"Read timeout. %d bytes read.", length]; + NSString *reason = [NSString stringWithFormat:@"Read timeout. %lu bytes read.", (unsigned long)length]; [self failWithReason:reason error:nil]; return 0; From ee91d872ee6d972c31f7a9d8dec709392757da65 Mon Sep 17 00:00:00 2001 From: Chris Ballinger Date: Wed, 3 Dec 2014 23:25:53 -0800 Subject: [PATCH 006/356] Add support for NSSecureCoding --- Core/XMPPElement.h | 2 +- Core/XMPPElement.m | 15 ++++++- Core/XMPPJID.h | 2 +- Core/XMPPJID.m | 21 ++++++++-- .../XMPPResourceMemoryStorageObject.h | 2 +- .../XMPPResourceMemoryStorageObject.m | 21 ++++++++-- .../XMPPUserMemoryStorageObject.h | 2 +- .../XMPPUserMemoryStorageObject.m | 39 ++++++++++++++----- ...MPPRoomOccupantHybridMemoryStorageObject.h | 2 +- ...MPPRoomOccupantHybridMemoryStorageObject.m | 24 ++++++++++-- .../XMPPRoomMessageMemoryStorageObject.h | 2 +- .../XMPPRoomMessageMemoryStorageObject.m | 28 ++++++++++--- .../XMPPRoomOccupantMemoryStorageObject.h | 2 +- .../XMPPRoomOccupantMemoryStorageObject.m | 18 ++++++++- Extensions/XEP-0054/XMPPvCardTempBase.h | 2 +- Extensions/XEP-0054/XMPPvCardTempBase.m | 31 ++++++++++----- 16 files changed, 169 insertions(+), 44 deletions(-) diff --git a/Core/XMPPElement.h b/Core/XMPPElement.h index 3ca2c42c10..4c02e493ad 100644 --- a/Core/XMPPElement.h +++ b/Core/XMPPElement.h @@ -15,7 +15,7 @@ * On the iPhone, the KissXML library provides a drop-in replacement for Apple's NSXML classes. **/ -@interface XMPPElement : NSXMLElement +@interface XMPPElement : NSXMLElement #pragma mark Common Jabber Methods diff --git a/Core/XMPPElement.m b/Core/XMPPElement.m index a9fce77741..55a1113d0a 100644 --- a/Core/XMPPElement.m +++ b/Core/XMPPElement.m @@ -27,7 +27,15 @@ - (id)initWithCoder:(NSCoder *)coder NSString *xmlString; if([coder allowsKeyedCoding]) { - xmlString = [coder decodeObjectForKey:@"xmlString"]; + if([coder respondsToSelector:@selector(requiresSecureCoding)] && + [coder requiresSecureCoding]) + { + xmlString = [coder decodeObjectOfClass:[NSString class] forKey:@"xmlString"]; + } + else + { + xmlString = [coder decodeObjectForKey:@"xmlString"]; + } } else { @@ -63,6 +71,11 @@ - (void)encodeWithCoder:(NSCoder *)coder } } ++ (BOOL) supportsSecureCoding +{ + return YES; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Copying //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Core/XMPPJID.h b/Core/XMPPJID.h index 80ecdff30e..cfe51eb007 100644 --- a/Core/XMPPJID.h +++ b/Core/XMPPJID.h @@ -12,7 +12,7 @@ enum XMPPJIDCompareOptions typedef enum XMPPJIDCompareOptions XMPPJIDCompareOptions; -@interface XMPPJID : NSObject +@interface XMPPJID : NSObject { __strong NSString *user; __strong NSString *domain; diff --git a/Core/XMPPJID.m b/Core/XMPPJID.m index 8bfbfbd6f2..fac24e0df3 100644 --- a/Core/XMPPJID.m +++ b/Core/XMPPJID.m @@ -215,9 +215,19 @@ - (id)initWithCoder:(NSCoder *)coder { if ([coder allowsKeyedCoding]) { - user = [[coder decodeObjectForKey:@"user"] copy]; - domain = [[coder decodeObjectForKey:@"domain"] copy]; - resource = [[coder decodeObjectForKey:@"resource"] copy]; + if([coder respondsToSelector:@selector(requiresSecureCoding)] && + [coder requiresSecureCoding]) + { + user = [[coder decodeObjectOfClass:[NSString class] forKey:@"user"] copy]; + domain = [[coder decodeObjectOfClass:[NSString class] forKey:@"domain"] copy]; + resource = [[coder decodeObjectOfClass:[NSString class] forKey:@"resource"] copy]; + } + else + { + user = [[coder decodeObjectForKey:@"user"] copy]; + domain = [[coder decodeObjectForKey:@"domain"] copy]; + resource = [[coder decodeObjectForKey:@"resource"] copy]; + } } else { @@ -245,6 +255,11 @@ - (void)encodeWithCoder:(NSCoder *)coder } } ++ (BOOL) supportsSecureCoding +{ + return YES; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Copying: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Extensions/Roster/MemoryStorage/XMPPResourceMemoryStorageObject.h b/Extensions/Roster/MemoryStorage/XMPPResourceMemoryStorageObject.h index ffc7a745d1..9999102073 100644 --- a/Extensions/Roster/MemoryStorage/XMPPResourceMemoryStorageObject.h +++ b/Extensions/Roster/MemoryStorage/XMPPResourceMemoryStorageObject.h @@ -6,7 +6,7 @@ @class XMPPPresence; -@interface XMPPResourceMemoryStorageObject : NSObject +@interface XMPPResourceMemoryStorageObject : NSObject { XMPPJID *jid; XMPPPresence *presence; diff --git a/Extensions/Roster/MemoryStorage/XMPPResourceMemoryStorageObject.m b/Extensions/Roster/MemoryStorage/XMPPResourceMemoryStorageObject.m index a8ec4e0666..fa8e27d7f6 100644 --- a/Extensions/Roster/MemoryStorage/XMPPResourceMemoryStorageObject.m +++ b/Extensions/Roster/MemoryStorage/XMPPResourceMemoryStorageObject.m @@ -63,9 +63,19 @@ - (id)initWithCoder:(NSCoder *)coder { if([coder allowsKeyedCoding]) { - jid = [coder decodeObjectForKey:@"jid"]; - presence = [coder decodeObjectForKey:@"presence"]; - presenceDate = [coder decodeObjectForKey:@"presenceDate"]; + if([coder respondsToSelector:@selector(requiresSecureCoding)] && + [coder requiresSecureCoding]) + { + jid = [coder decodeObjectOfClass:[XMPPJID class] forKey:@"jid"]; + presence = [coder decodeObjectOfClass:[XMPPPresence class] forKey:@"presence"]; + presenceDate = [coder decodeObjectOfClass:[NSDate class] forKey:@"presenceDate"]; + } + else + { + jid = [coder decodeObjectForKey:@"jid"]; + presence = [coder decodeObjectForKey:@"presence"]; + presenceDate = [coder decodeObjectForKey:@"presenceDate"]; + } } else { @@ -93,6 +103,11 @@ - (void)encodeWithCoder:(NSCoder *)coder } } ++ (BOOL) supportsSecureCoding +{ + return YES; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Standard Methods //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h index 001734f4f8..05acf1b130 100644 --- a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h +++ b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h @@ -9,7 +9,7 @@ @class XMPPResourceMemoryStorageObject; -@interface XMPPUserMemoryStorageObject : NSObject +@interface XMPPUserMemoryStorageObject : NSObject { XMPPJID *jid; NSMutableDictionary *itemAttributes; diff --git a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m index 7ea68fec53..b70af4be55 100644 --- a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m +++ b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m @@ -101,15 +101,31 @@ - (id)initWithCoder:(NSCoder *)coder { if ([coder allowsKeyedCoding]) { - jid = [coder decodeObjectForKey:@"jid"]; - itemAttributes = [[coder decodeObjectForKey:@"itemAttributes"] mutableCopy]; - #if TARGET_OS_IPHONE - photo = [[UIImage alloc] initWithData:[coder decodeObjectForKey:@"photo"]]; - #else - photo = [[NSImage alloc] initWithData:[coder decodeObjectForKey:@"photo"]]; - #endif - resources = [[coder decodeObjectForKey:@"resources"] mutableCopy]; - primaryResource = [coder decodeObjectForKey:@"primaryResource"]; + if([coder respondsToSelector:@selector(requiresSecureCoding)] && + [coder requiresSecureCoding]) + { + jid = [coder decodeObjectOfClass:[XMPPJID class] forKey:@"jid"]; + itemAttributes = [[coder decodeObjectOfClass:[NSDictionary class] forKey:@"itemAttributes"] mutableCopy]; +#if TARGET_OS_IPHONE + photo = [[UIImage alloc] initWithData:[coder decodeObjectOfClass:[NSData class] forKey:@"photo"]]; +#else + photo = [[NSImage alloc] initWithData:[coder decodeObjectOfClass:[NSData class] forKey:@"photo"]]; +#endif + resources = [[coder decodeObjectOfClass:[NSDictionary class] forKey:@"resources"] mutableCopy]; + primaryResource = [coder decodeObjectOfClass:[XMPPResourceMemoryStorageObject class] forKey:@"primaryResource"]; + } + else + { + jid = [coder decodeObjectForKey:@"jid"]; + itemAttributes = [[coder decodeObjectForKey:@"itemAttributes"] mutableCopy]; +#if TARGET_OS_IPHONE + photo = [[UIImage alloc] initWithData:[coder decodeObjectForKey:@"photo"]]; +#else + photo = [[NSImage alloc] initWithData:[coder decodeObjectForKey:@"photo"]]; +#endif + resources = [[coder decodeObjectForKey:@"resources"] mutableCopy]; + primaryResource = [coder decodeObjectForKey:@"primaryResource"]; + } } else { @@ -155,6 +171,11 @@ - (void)encodeWithCoder:(NSCoder *)coder } } ++ (BOOL) supportsSecureCoding +{ + return YES; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Standard Methods //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Extensions/XEP-0045/HybridStorage/XMPPRoomOccupantHybridMemoryStorageObject.h b/Extensions/XEP-0045/HybridStorage/XMPPRoomOccupantHybridMemoryStorageObject.h index 01f64db747..65c37c615f 100644 --- a/Extensions/XEP-0045/HybridStorage/XMPPRoomOccupantHybridMemoryStorageObject.h +++ b/Extensions/XEP-0045/HybridStorage/XMPPRoomOccupantHybridMemoryStorageObject.h @@ -3,7 +3,7 @@ #import "XMPPRoomOccupant.h" -@interface XMPPRoomOccupantHybridMemoryStorageObject : NSObject +@interface XMPPRoomOccupantHybridMemoryStorageObject : NSObject - (id)initWithPresence:(XMPPPresence *)presence streamFullJid:(XMPPJID *)streamFullJid; - (void)updateWithPresence:(XMPPPresence *)presence; diff --git a/Extensions/XEP-0045/HybridStorage/XMPPRoomOccupantHybridMemoryStorageObject.m b/Extensions/XEP-0045/HybridStorage/XMPPRoomOccupantHybridMemoryStorageObject.m index 0f94753b9e..965b224a66 100644 --- a/Extensions/XEP-0045/HybridStorage/XMPPRoomOccupantHybridMemoryStorageObject.m +++ b/Extensions/XEP-0045/HybridStorage/XMPPRoomOccupantHybridMemoryStorageObject.m @@ -45,10 +45,21 @@ - (id)initWithCoder:(NSCoder *)coder { if ([coder allowsKeyedCoding]) { - presence = [coder decodeObjectForKey:@"presence"]; - jid = [coder decodeObjectForKey:@"jid"]; - createdAt = [coder decodeObjectForKey:@"createdAt"]; - streamFullJid = [coder decodeObjectForKey:@"streamFullJid"]; + if([coder respondsToSelector:@selector(requiresSecureCoding)] && + [coder requiresSecureCoding]) + { + presence = [coder decodeObjectOfClass:[XMPPPresence class] forKey:@"presence"]; + jid = [coder decodeObjectOfClass:[XMPPJID class] forKey:@"jid"]; + createdAt = [coder decodeObjectOfClass:[NSDate class] forKey:@"createdAt"]; + streamFullJid = [coder decodeObjectOfClass:[XMPPJID class] forKey:@"streamFullJid"]; + } + else + { + presence = [coder decodeObjectForKey:@"presence"]; + jid = [coder decodeObjectForKey:@"jid"]; + createdAt = [coder decodeObjectForKey:@"createdAt"]; + streamFullJid = [coder decodeObjectForKey:@"streamFullJid"]; + } } else { @@ -79,6 +90,11 @@ - (void)encodeWithCoder:(NSCoder *)coder } } ++ (BOOL) supportsSecureCoding +{ + return YES; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Copying //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.h b/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.h index 2b6e655ca6..fc83094813 100644 --- a/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.h +++ b/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.h @@ -2,7 +2,7 @@ #import "XMPPRoomMessage.h" -@interface XMPPRoomMessageMemoryStorageObject : NSObject +@interface XMPPRoomMessageMemoryStorageObject : NSObject - (id)initWithIncomingMessage:(XMPPMessage *)message; - (id)initWithOutgoingMessage:(XMPPMessage *)message jid:(XMPPJID *)myRoomJID; diff --git a/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.m b/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.m index 1450bf37c8..b57e6f5085 100644 --- a/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.m +++ b/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.m @@ -63,11 +63,24 @@ - (id)initWithCoder:(NSCoder *)coder { if ([coder allowsKeyedCoding]) { - message = [coder decodeObjectForKey:@"message"]; - jid = [coder decodeObjectForKey:@"jid"]; - localTimestamp = [coder decodeObjectForKey:@"localTimestamp"]; - remoteTimestamp = [coder decodeObjectForKey:@"remoteTimestamp"]; - isFromMe = [coder decodeBoolForKey:@"isFromMe"]; + if([coder respondsToSelector:@selector(requiresSecureCoding)] && + [coder requiresSecureCoding]) + { + message = [coder decodeObjectOfClass:[XMPPMessage class] forKey:@"message"]; + jid = [coder decodeObjectOfClass:[XMPPJID class] forKey:@"jid"]; + localTimestamp = [coder decodeObjectOfClass:[NSDate class] forKey:@"localTimestamp"]; + remoteTimestamp = [coder decodeObjectOfClass:[NSDate class] forKey:@"remoteTimestamp"]; + isFromMe = [coder decodeBoolForKey:@"isFromMe"]; + } + else + { + message = [coder decodeObjectForKey:@"message"]; + jid = [coder decodeObjectForKey:@"jid"]; + localTimestamp = [coder decodeObjectForKey:@"localTimestamp"]; + remoteTimestamp = [coder decodeObjectForKey:@"remoteTimestamp"]; + isFromMe = [coder decodeBoolForKey:@"isFromMe"]; + } + } else { @@ -101,6 +114,11 @@ - (void)encodeWithCoder:(NSCoder *)coder } } ++ (BOOL) supportsSecureCoding +{ + return YES; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Copying //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Extensions/XEP-0045/MemoryStorage/XMPPRoomOccupantMemoryStorageObject.h b/Extensions/XEP-0045/MemoryStorage/XMPPRoomOccupantMemoryStorageObject.h index 2a1b89da87..cb9c44a7e0 100644 --- a/Extensions/XEP-0045/MemoryStorage/XMPPRoomOccupantMemoryStorageObject.h +++ b/Extensions/XEP-0045/MemoryStorage/XMPPRoomOccupantMemoryStorageObject.h @@ -3,7 +3,7 @@ #import "XMPPRoomOccupant.h" -@interface XMPPRoomOccupantMemoryStorageObject : NSObject +@interface XMPPRoomOccupantMemoryStorageObject : NSObject - (id)initWithPresence:(XMPPPresence *)presence; - (void)updateWithPresence:(XMPPPresence *)presence; diff --git a/Extensions/XEP-0045/MemoryStorage/XMPPRoomOccupantMemoryStorageObject.m b/Extensions/XEP-0045/MemoryStorage/XMPPRoomOccupantMemoryStorageObject.m index 67613d1130..514852f106 100644 --- a/Extensions/XEP-0045/MemoryStorage/XMPPRoomOccupantMemoryStorageObject.m +++ b/Extensions/XEP-0045/MemoryStorage/XMPPRoomOccupantMemoryStorageObject.m @@ -38,8 +38,17 @@ - (id)initWithCoder:(NSCoder *)coder { if ([coder allowsKeyedCoding]) { - presence = [coder decodeObjectForKey:@"presence"]; - jid = [coder decodeObjectForKey:@"jid"]; + if([coder respondsToSelector:@selector(requiresSecureCoding)] && + [coder requiresSecureCoding]) + { + presence = [coder decodeObjectOfClass:[XMPPPresence class] forKey:@"presence"]; + jid = [coder decodeObjectOfClass:[XMPPJID class] forKey:@"jid"]; + } + else + { + presence = [coder decodeObjectForKey:@"presence"]; + jid = [coder decodeObjectForKey:@"jid"]; + } } else { @@ -64,6 +73,11 @@ - (void)encodeWithCoder:(NSCoder *)coder } } ++ (BOOL) supportsSecureCoding +{ + return YES; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark Copying //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Extensions/XEP-0054/XMPPvCardTempBase.h b/Extensions/XEP-0054/XMPPvCardTempBase.h index c48ffa37d5..588dc880ad 100644 --- a/Extensions/XEP-0054/XMPPvCardTempBase.h +++ b/Extensions/XEP-0054/XMPPvCardTempBase.h @@ -62,7 +62,7 @@ } -@interface XMPPvCardTempBase : NSXMLElement { +@interface XMPPvCardTempBase : NSXMLElement { } diff --git a/Extensions/XEP-0054/XMPPvCardTempBase.m b/Extensions/XEP-0054/XMPPvCardTempBase.m index 6578205694..777328cede 100644 --- a/Extensions/XEP-0054/XMPPvCardTempBase.m +++ b/Extensions/XEP-0054/XMPPvCardTempBase.m @@ -38,15 +38,23 @@ - (id)replacementObjectForPortCoder:(NSPortCoder *)encoder - (id)initWithCoder:(NSCoder *)coder { - NSString *xmlString; - if([coder allowsKeyedCoding]) - { - xmlString = [coder decodeObjectForKey:@"xmlString"]; - } - else - { - xmlString = [coder decodeObject]; - } + NSString *xmlString; + if([coder allowsKeyedCoding]) + { + if([coder respondsToSelector:@selector(requiresSecureCoding)] && + [coder requiresSecureCoding]) + { + xmlString = [coder decodeObjectOfClass:[NSString class] forKey:@"xmlString"]; + } + else + { + xmlString = [coder decodeObjectForKey:@"xmlString"]; + } + } + else + { + xmlString = [coder decodeObject]; + } // The method [super initWithXMLString:error:] may return a different self. // In other words, it may [self release], and alloc/init/return a new self. @@ -78,6 +86,11 @@ - (void)encodeWithCoder:(NSCoder *)coder } } ++ (BOOL) supportsSecureCoding +{ + return YES; +} + - (id)copyWithZone:(NSZone *)zone { NSXMLElement *elementCopy = [super copyWithZone:zone]; From a902d2e9e84fff24636e0ec23ed1734967ae5837 Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Sat, 20 Dec 2014 17:47:01 +0000 Subject: [PATCH 007/356] Universal Roster Item API A Universal API for both Memory and Core Data Roster Storage for getting information about a Roster Item: - Subscription - Ask - Nickname - Groups --- .../XMPPRosterCoreDataStorage.m | 47 ++++++++++++++++++ .../MemoryStorage/XMPPRosterMemoryStorage.m | 38 ++++++++++++++ .../XMPPUserMemoryStorageObject.h | 10 ++++ .../XMPPUserMemoryStorageObject.m | 49 +++++++++++++++++++ Extensions/Roster/XMPPRoster.h | 7 +++ 5 files changed, 151 insertions(+) diff --git a/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m b/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m index c8b286c5a5..d93da369f8 100644 --- a/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m +++ b/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m @@ -522,5 +522,52 @@ - (NSArray *)jidsForXMPPStream:(XMPPStream *)stream{ return results; } +- (void)getSubscription:(NSString **)subscription + ask:(NSString **)ask + nickname:(NSString **)nickname + groups:(NSArray **)groups + forJID:(XMPPJID *)jid + xmppStream:(XMPPStream *)stream +{ + XMPPLogTrace(); + + [self executeBlock:^{ + + NSManagedObjectContext *moc = [self managedObjectContext]; + XMPPUserCoreDataStorageObject *user = [self userForJID:jid xmppStream:stream managedObjectContext:moc]; + + if(user) + { + if(subscription) + { + *subscription = user.subscription; + } + + if(ask) + { + *ask = user.ask; + } + + if(nickname) + { + *nickname = user.nickname; + } + + if(groups) + { + if([user.groups count]) + { + NSMutableArray *groupNames = [NSMutableArray array]; + + for(XMPPGroupCoreDataStorageObject *group in user.groups){ + [groupNames addObject:group.name]; + } + + *groups = groupNames; + } + } + } + }]; +} @end diff --git a/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m b/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m index 71437d9f2e..5639d4cb38 100644 --- a/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m +++ b/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m @@ -819,4 +819,42 @@ - (NSArray *)jidsForXMPPStream:(XMPPStream *)stream return results; } +- (void)getSubscription:(NSString **)subscription + ask:(NSString **)ask + nickname:(NSString **)nickname + groups:(NSArray **)groups + forJID:(XMPPJID *)jid + xmppStream:(XMPPStream *)stream +{ + + XMPPLogTrace(); + AssertParentQueue(); + + XMPPJID *jidKey = [jid bareJID]; + XMPPUserMemoryStorageObject *rosterUser = [roster objectForKey:jidKey]; + + if(rosterUser) + { + if(subscription) + { + *subscription = rosterUser.subscription; + } + + if(ask) + { + *ask = rosterUser.ask; + } + + if(nickname) + { + *nickname = rosterUser.nickname; + } + + if(groups) + { + *groups = rosterUser.groups; + } + } +} + @end diff --git a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h index 05acf1b130..a0c9dc88a6 100644 --- a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h +++ b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h @@ -13,6 +13,7 @@ { XMPPJID *jid; NSMutableDictionary *itemAttributes; + NSMutableArray *groups; NSMutableDictionary *resources; XMPPResourceMemoryStorageObject *primaryResource; @@ -39,6 +40,10 @@ */ +- (NSString *)subscription; + +- (NSString *)ask; + /** * Simple convenience method. * If a nickname exists for the user, the nickname is returned. @@ -46,6 +51,11 @@ **/ - (NSString *)displayName; +/** + * An array of Group Names. +**/ +- (NSArray *)groups; + /** * If XMPPvCardAvatarModule is included in the framework, the XMPPRoster will automatically integrate with it, * and we'll save the the user photos after they've been downloaded. diff --git a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m index b70af4be55..95cffe1be5 100644 --- a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m +++ b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m @@ -33,6 +33,8 @@ - (id)initWithJID:(XMPPJID *)aJid itemAttributes = [[NSMutableDictionary alloc] initWithCapacity:0]; + groups = [[NSMutableArray alloc] initWithCapacity:0]; + [self commonInit]; } return self; @@ -47,6 +49,19 @@ - (id)initWithItem:(NSXMLElement *)item itemAttributes = [item attributesAsDictionary]; + groups = [[NSMutableArray alloc] initWithCapacity:0]; + + NSArray *groupElements = [item elementsForName:@"group"]; + + for (NSXMLElement *groupElement in groupElements) { + NSString *groupName = [groupElement stringValue]; + + if ([groupName length]) + { + [groups addObject:groupName]; + } + } + [self commonInit]; } return self; @@ -65,6 +80,7 @@ - (id)copyWithZone:(NSZone *)zone deepCopy->jid = [jid copy]; deepCopy->itemAttributes = [itemAttributes mutableCopy]; + deepCopy->groups = [groups mutableCopy]; deepCopy->resources = [[NSMutableDictionary alloc] initWithCapacity:[resources count]]; @@ -106,6 +122,7 @@ - (id)initWithCoder:(NSCoder *)coder { jid = [coder decodeObjectOfClass:[XMPPJID class] forKey:@"jid"]; itemAttributes = [[coder decodeObjectOfClass:[NSDictionary class] forKey:@"itemAttributes"] mutableCopy]; + groups = [[coder decodeObjectOfClass:[NSArray class] forKey:@"groups"] mutableCopy]; #if TARGET_OS_IPHONE photo = [[UIImage alloc] initWithData:[coder decodeObjectOfClass:[NSData class] forKey:@"photo"]]; #else @@ -118,6 +135,7 @@ - (id)initWithCoder:(NSCoder *)coder { jid = [coder decodeObjectForKey:@"jid"]; itemAttributes = [[coder decodeObjectForKey:@"itemAttributes"] mutableCopy]; + groups = [[coder decodeObjectForKey:@"groups"] mutableCopy]; #if TARGET_OS_IPHONE photo = [[UIImage alloc] initWithData:[coder decodeObjectForKey:@"photo"]]; #else @@ -131,6 +149,7 @@ - (id)initWithCoder:(NSCoder *)coder { jid = [coder decodeObject]; itemAttributes = [[coder decodeObject] mutableCopy]; + groups = [[coder decodeObject] mutableCopy]; #if TARGET_OS_IPHONE photo = [[UIImage alloc] initWithData:[coder decodeObject]]; #else @@ -149,6 +168,7 @@ - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:jid forKey:@"jid"]; [coder encodeObject:itemAttributes forKey:@"itemAttributes"]; + [coder encodeObject:groups forKey:@"groups"]; #if TARGET_OS_IPHONE [coder encodeObject:UIImagePNGRepresentation(photo) forKey:@"photo"]; #else @@ -161,6 +181,7 @@ - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:jid]; [coder encodeObject:itemAttributes]; + [coder encodeObject:groups]; #if TARGET_OS_IPHONE [coder encodeObject:UIImagePNGRepresentation(photo)]; #else @@ -192,6 +213,16 @@ - (NSString *)nickname return (NSString *)[itemAttributes objectForKey:@"name"]; } +- (NSString *)subscription +{ + return (NSString *)[itemAttributes objectForKey:@"subscription"]; +} + +- (NSString *)ask +{ + return (NSString *)[itemAttributes objectForKey:@"ask"]; +} + - (NSString *)displayName { NSString *nickname = [self nickname]; @@ -201,6 +232,11 @@ - (NSString *)displayName return [jid bare]; } +- (NSArray *)groups +{ + return [groups copy]; +} + - (BOOL)isOnline { return (primaryResource != nil); @@ -309,6 +345,19 @@ - (void)updateWithItem:(NSXMLElement *)item [itemAttributes setObject:value forKey:key]; } + + [groups removeAllObjects]; + + NSArray *groupElements = [item elementsForName:@"group"]; + + for (NSXMLElement *groupElement in groupElements) { + NSString *groupName = [groupElement stringValue]; + + if ([groupName length]) + { + [groups addObject:groupName]; + } + } } - (int)updateWithPresence:(XMPPPresence *)presence diff --git a/Extensions/Roster/XMPPRoster.h b/Extensions/Roster/XMPPRoster.h index 5a89eebc35..f855ddf519 100644 --- a/Extensions/Roster/XMPPRoster.h +++ b/Extensions/Roster/XMPPRoster.h @@ -333,6 +333,13 @@ - (NSArray *)jidsForXMPPStream:(XMPPStream *)stream; +- (void)getSubscription:(NSString **)subscription + ask:(NSString **)ask + nickname:(NSString **)nickname + groups:(NSArray **)groups + forJID:(XMPPJID *)jid + xmppStream:(XMPPStream *)stream; + @optional /** From 7d1bb596b477ed6811de2a6003cac538b91b6527 Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Sat, 10 Jan 2015 18:19:56 +0000 Subject: [PATCH 008/356] Fixes allowRosterlessOperation Deadlock Move allowRosterlessOperation outside of scheduleBlock Fixes #471 Fixes #422 --- Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m b/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m index d93da369f8..c413b524e8 100644 --- a/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m +++ b/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m @@ -369,6 +369,8 @@ - (void)handleRosterItem:(NSXMLElement *)itemSubElement xmppStream:(XMPPStream * - (void)handlePresence:(XMPPPresence *)presence xmppStream:(XMPPStream *)stream { XMPPLogTrace(); + + BOOL allowRosterlessOperation = [parent allowRosterlessOperation]; [self scheduleBlock:^{ @@ -379,7 +381,7 @@ - (void)handlePresence:(XMPPPresence *)presence xmppStream:(XMPPStream *)stream XMPPUserCoreDataStorageObject *user = [self userForJID:jid xmppStream:stream managedObjectContext:moc]; - if (user == nil && [parent allowRosterlessOperation]) + if (user == nil && allowRosterlessOperation) { // This may happen if the roster is in rosterlessOperation mode. From a44385fd21ee79a97f202e4df65f12cac3143321 Mon Sep 17 00:00:00 2001 From: Jonathon Staff Date: Fri, 23 Jan 2015 11:05:11 -0500 Subject: [PATCH 009/356] Updated XEP-0077 based on conversations at the original PR. No longer using childCount == 0 as validation. --- Extensions/XEP-0077/XMPPRegistration.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Extensions/XEP-0077/XMPPRegistration.m b/Extensions/XEP-0077/XMPPRegistration.m index 4d65f1d733..b1d3bce12d 100644 --- a/Extensions/XEP-0077/XMPPRegistration.m +++ b/Extensions/XEP-0077/XMPPRegistration.m @@ -162,7 +162,7 @@ - (void)handlePasswordChangeQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo NSString *type = [iq type]; - if ([type isEqualToString:@"result"] && iq.childCount == 0) { + if ([type isEqualToString:@"result"]) { [multicastDelegate passwordChangeSuccessful:self]; } else { // this should be impossible to reach, but just for safety's sake... @@ -203,7 +203,7 @@ - (void)handleRegistrationCancelQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTracking NSString *type = [iq type]; - if ([type isEqualToString:@"result"] && iq.childCount == 0) { + if ([type isEqualToString:@"result"]) { [multicastDelegate cancelRegistrationSuccessful:self]; } else { // this should be impossible to reach, but just for safety's sake... @@ -228,11 +228,10 @@ - (BOOL)xmppStream:(XMPPStream *)stream didReceiveIQ:(XMPPIQ *)iq NSString *type = [iq type]; if ([type isEqualToString:@"result"] || [type isEqualToString:@"error"]) { - NSLog(@"invoking with iq: %@", iq); return [xmppIDTracker invokeForElement:iq withObject:iq]; } return NO; } -@end \ No newline at end of file +@end From eb8d374f8e1afecadf6687663d08f4c2525a7ebd Mon Sep 17 00:00:00 2001 From: Jonathon Staff Date: Wed, 4 Feb 2015 14:41:21 -0800 Subject: [PATCH 010/356] Updated gitignore to include .idea dir and began refactoring the codebase to use modern syntax --- .gitignore | 2 ++ .../XMPPGroupCoreDataStorageObject.m | 2 +- .../XMPPResourceCoreDataStorageObject.m | 4 +-- .../XMPPUserCoreDataStorageObject.m | 4 +-- .../MemoryStorage/XMPPRosterMemoryStorage.m | 20 +++++++------- .../XMPPUserMemoryStorageObject.m | 26 +++++++++---------- .../XMPPMessageArchivingCoreDataStorage.m | 7 ++--- ...PMessageArchiving_Message_CoreDataObject.m | 4 +-- Extensions/XEP-0198/XMPPStreamManagement.m | 6 ++--- 9 files changed, 39 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index fad27fa0b0..717f4b1953 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ xcuserdata .DS_Store project.xcworkspace +.idea + diff --git a/Extensions/Roster/CoreDataStorage/XMPPGroupCoreDataStorageObject.m b/Extensions/Roster/CoreDataStorage/XMPPGroupCoreDataStorageObject.m index 50373ea166..0dbf1421f3 100644 --- a/Extensions/Roster/CoreDataStorage/XMPPGroupCoreDataStorageObject.m +++ b/Extensions/Roster/CoreDataStorage/XMPPGroupCoreDataStorageObject.m @@ -73,7 +73,7 @@ + (id)fetchOrInsertGroupName:(NSString *)groupName inManagedObjectContext:(NSMan if ([results count] > 0) { - return [results objectAtIndex:0]; + return results[0]; } return [self insertGroupName:groupName inManagedObjectContext:moc]; diff --git a/Extensions/Roster/CoreDataStorage/XMPPResourceCoreDataStorageObject.m b/Extensions/Roster/CoreDataStorage/XMPPResourceCoreDataStorageObject.m index c00060cfba..626455a195 100644 --- a/Extensions/Roster/CoreDataStorage/XMPPResourceCoreDataStorageObject.m +++ b/Extensions/Roster/CoreDataStorage/XMPPResourceCoreDataStorageObject.m @@ -94,7 +94,7 @@ - (int)priority - (void)setPriority:(int)priority { - self.priorityNum = [NSNumber numberWithInt:priority]; + self.priorityNum = @(priority); } - (int)intShow @@ -104,7 +104,7 @@ - (int)intShow - (void)setIntShow:(int)intShow { - self.showNum = [NSNumber numberWithInt:intShow]; + self.showNum = @(intShow); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Extensions/Roster/CoreDataStorage/XMPPUserCoreDataStorageObject.m b/Extensions/Roster/CoreDataStorage/XMPPUserCoreDataStorageObject.m index 370754f343..f7f9b82610 100644 --- a/Extensions/Roster/CoreDataStorage/XMPPUserCoreDataStorageObject.m +++ b/Extensions/Roster/CoreDataStorage/XMPPUserCoreDataStorageObject.m @@ -108,7 +108,7 @@ - (NSInteger)section - (void)setSection:(NSInteger)value { - self.sectionNum = [NSNumber numberWithInteger:value]; + self.sectionNum = @(value); } - (NSInteger)primitiveSection @@ -291,7 +291,7 @@ - (void)recalculatePrimaryResource NSArray *sortedResources = [[self allResources] sortedArrayUsingSelector:@selector(compare:)]; if ([sortedResources count] > 0) { - XMPPResourceCoreDataStorageObject *resource = [sortedResources objectAtIndex:0]; + XMPPResourceCoreDataStorageObject *resource = sortedResources[0]; // Primary resource must have a non-negative priority if ([resource priority] >= 0) diff --git a/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m b/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m index 5639d4cb38..b007aff9cb 100644 --- a/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m +++ b/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m @@ -122,7 +122,7 @@ - (XMPPUserMemoryStorageObject *)_userForJID:(XMPPJID *)jid { AssertPrivateQueue(); - XMPPUserMemoryStorageObject *result = [roster objectForKey:[jid bareJID]]; + XMPPUserMemoryStorageObject *result = roster[[jid bareJID]]; if (result) { @@ -646,7 +646,7 @@ - (void)handleRosterItem:(NSXMLElement *)item xmppStream:(XMPPStream *)stream XMPPUserMemoryStorageObject *newUser = (XMPPUserMemoryStorageObject *)[[self.userClass alloc] initWithItem:item]; - [roster setObject:newUser forKey:jid]; + roster[jid] = newUser; XMPPLogVerbose(@"roster(%lu): %@", (unsigned long)[roster count], roster); } @@ -656,7 +656,7 @@ - (void)handleRosterItem:(NSXMLElement *)item xmppStream:(XMPPStream *)stream if ([subscription isEqualToString:@"remove"]) { - XMPPUserMemoryStorageObject *user = [roster objectForKey:jid]; + XMPPUserMemoryStorageObject *user = roster[jid]; if (user) { [roster removeObjectForKey:jid]; @@ -669,7 +669,7 @@ - (void)handleRosterItem:(NSXMLElement *)item xmppStream:(XMPPStream *)stream } else { - XMPPUserMemoryStorageObject *user = [roster objectForKey:jid]; + XMPPUserMemoryStorageObject *user = roster[jid]; if (user) { [user updateWithItem:item]; @@ -684,7 +684,7 @@ - (void)handleRosterItem:(NSXMLElement *)item xmppStream:(XMPPStream *)stream XMPPUserMemoryStorageObject *newUser = (XMPPUserMemoryStorageObject *)[[self.userClass alloc] initWithItem:item]; - [roster setObject:newUser forKey:jid]; + roster[jid] = newUser; XMPPLogVerbose(@"roster(%lu): %@", (unsigned long)[roster count], roster); @@ -708,7 +708,7 @@ - (void)handlePresence:(XMPPPresence *)presence xmppStream:(XMPPStream *)stream XMPPJID *jidKey = [[presence from] bareJID]; - user = [roster objectForKey:jidKey]; + user = roster[jidKey]; if (user == nil) { // Not a presence element from anyone in our roster (that we know of). @@ -726,7 +726,7 @@ - (void)handlePresence:(XMPPPresence *)presence xmppStream:(XMPPStream *)stream user = (XMPPUserMemoryStorageObject *)[[self.userClass alloc] initWithJID:jidKey]; - [roster setObject:user forKey:jidKey]; + roster[jidKey] = user; [[self multicastDelegate] xmppRoster:self didAddUser:user]; [[self multicastDelegate] xmppRosterDidChange:self]; @@ -756,7 +756,7 @@ - (BOOL)userExistsWithJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream AssertParentQueue(); XMPPJID *jidKey = [jid bareJID]; - XMPPUserMemoryStorageObject *rosterUser = [roster objectForKey:jidKey]; + XMPPUserMemoryStorageObject *rosterUser = roster[jidKey]; return (rosterUser != nil); } @@ -771,7 +771,7 @@ - (void)setPhoto:(NSImage *)photo forUserWithJID:(XMPPJID *)jid xmppStream:(XMPP AssertParentQueue(); XMPPJID *jidKey = [jid bareJID]; - XMPPUserMemoryStorageObject *rosterUser = [roster objectForKey:jidKey]; + XMPPUserMemoryStorageObject *rosterUser = roster[jidKey]; if (rosterUser) { @@ -831,7 +831,7 @@ - (void)getSubscription:(NSString **)subscription AssertParentQueue(); XMPPJID *jidKey = [jid bareJID]; - XMPPUserMemoryStorageObject *rosterUser = [roster objectForKey:jidKey]; + XMPPUserMemoryStorageObject *rosterUser = roster[jidKey]; if(rosterUser) { diff --git a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m index 95cffe1be5..14633d136b 100644 --- a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m +++ b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.m @@ -86,9 +86,9 @@ - (id)copyWithZone:(NSZone *)zone for (XMPPJID *key in resources) { - XMPPResourceMemoryStorageObject *resourceCopy = [[resources objectForKey:key] copy]; + XMPPResourceMemoryStorageObject *resourceCopy = [resources[key] copy]; - [deepCopy->resources setObject:resourceCopy forKey:key]; + deepCopy->resources[key] = resourceCopy; } [deepCopy recalculatePrimaryResource]; @@ -210,17 +210,17 @@ - (XMPPJID *)jid - (NSString *)nickname { - return (NSString *)[itemAttributes objectForKey:@"name"]; + return (NSString *) itemAttributes[@"name"]; } - (NSString *)subscription { - return (NSString *)[itemAttributes objectForKey:@"subscription"]; + return (NSString *) itemAttributes[@"subscription"]; } - (NSString *)ask { - return (NSString *)[itemAttributes objectForKey:@"ask"]; + return (NSString *) itemAttributes[@"ask"]; } - (NSString *)displayName @@ -248,8 +248,8 @@ - (BOOL)isPendingApproval // // - NSString *subscription = [itemAttributes objectForKey:@"subscription"]; - NSString *ask = [itemAttributes objectForKey:@"ask"]; + NSString *subscription = itemAttributes[@"subscription"]; + NSString *ask = itemAttributes[@"ask"]; if ([subscription isEqualToString:@"none"] || [subscription isEqualToString:@"from"]) { @@ -269,7 +269,7 @@ - (BOOL)isPendingApproval - (id )resourceForJID:(XMPPJID *)aJid { - return [resources objectForKey:aJid]; + return resources[aJid]; } - (NSArray *)allResources @@ -313,7 +313,7 @@ - (void)recalculatePrimaryResource NSArray *sortedResources = [[self allResources] sortedArrayUsingSelector:@selector(compare:)]; if ([sortedResources count] > 0) { - XMPPResourceMemoryStorageObject *possiblePrimary = [sortedResources objectAtIndex:0]; + XMPPResourceMemoryStorageObject *possiblePrimary = sortedResources[0]; // Primary resource must have a non-negative priority if ([[possiblePrimary presence] priority] >= 0) @@ -343,7 +343,7 @@ - (void)updateWithItem:(NSXMLElement *)item NSString *key = [node name]; NSString *value = [node stringValue]; - [itemAttributes setObject:value forKey:key]; + itemAttributes[key] = value; } [groups removeAllObjects]; @@ -372,7 +372,7 @@ - (int)updateWithPresence:(XMPPPresence *)presence if ([presenceType isEqualToString:@"unavailable"] || [presenceType isEqualToString:@"error"]) { - resource = [resources objectForKey:key]; + resource = resources[key]; if (resource) { [resources removeObjectForKey:key]; @@ -383,7 +383,7 @@ - (int)updateWithPresence:(XMPPPresence *)presence } else { - resource = [resources objectForKey:key]; + resource = resources[key]; if (resource) { [self willUpdateResource:resource withPresence:presence]; @@ -396,7 +396,7 @@ - (int)updateWithPresence:(XMPPPresence *)presence { resource = (XMPPResourceMemoryStorageObject *)[[resourceClass alloc] initWithPresence:presence]; - [resources setObject:resource forKey:key]; + resources[key] = resource; [self didAddResource:resource withPresence:presence]; result = XMPP_USER_ADDED_RESOURCE; diff --git a/Extensions/XEP-0136/CoreDataStorage/XMPPMessageArchivingCoreDataStorage.m b/Extensions/XEP-0136/CoreDataStorage/XMPPMessageArchivingCoreDataStorage.m index 6b0d2e9211..fa5c36e8d4 100644 --- a/Extensions/XEP-0136/CoreDataStorage/XMPPMessageArchivingCoreDataStorage.m +++ b/Extensions/XEP-0136/CoreDataStorage/XMPPMessageArchivingCoreDataStorage.m @@ -166,14 +166,15 @@ - (XMPPMessageArchiving_Message_CoreDataObject *)composingMessageWithJid:(XMPPJI NSString *predicateFrmt = @"composing == YES AND bareJidStr == %@ AND outgoing == %@ AND streamBareJidStr == %@"; NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFrmt, - [messageJid bare], [NSNumber numberWithBool:isOutgoing], [streamJid bare]]; + [messageJid bare], @(isOutgoing), + [streamJid bare]]; NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"timestamp" ascending:NO]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; fetchRequest.entity = messageEntity; fetchRequest.predicate = predicate; - fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; + fetchRequest.sortDescriptors = @[sortDescriptor]; fetchRequest.fetchLimit = 1; NSError *error = nil; @@ -460,7 +461,7 @@ - (void)archiveMessage:(XMPPMessage *)message outgoing:(BOOL)isOutgoing xmppStre contact.mostRecentMessageTimestamp = archivedMessage.timestamp; contact.mostRecentMessageBody = archivedMessage.body; - contact.mostRecentMessageOutgoing = [NSNumber numberWithBool:isOutgoing]; + contact.mostRecentMessageOutgoing = @(isOutgoing); XMPPLogVerbose(@"New contact: %@", contact); diff --git a/Extensions/XEP-0136/CoreDataStorage/XMPPMessageArchiving_Message_CoreDataObject.m b/Extensions/XEP-0136/CoreDataStorage/XMPPMessageArchiving_Message_CoreDataObject.m index e19a567471..60de9c3e1e 100644 --- a/Extensions/XEP-0136/CoreDataStorage/XMPPMessageArchiving_Message_CoreDataObject.m +++ b/Extensions/XEP-0136/CoreDataStorage/XMPPMessageArchiving_Message_CoreDataObject.m @@ -141,7 +141,7 @@ - (BOOL)isOutgoing - (void)setIsOutgoing:(BOOL)flag { - self.outgoing = [NSNumber numberWithBool:flag]; + self.outgoing = @(flag); } - (BOOL)isComposing @@ -151,7 +151,7 @@ - (BOOL)isComposing - (void)setIsComposing:(BOOL)flag { - self.composing = [NSNumber numberWithBool:flag]; + self.composing = @(flag); } #pragma mark Hooks diff --git a/Extensions/XEP-0198/XMPPStreamManagement.m b/Extensions/XEP-0198/XMPPStreamManagement.m index 4197df04a0..a4ef0b382c 100644 --- a/Extensions/XEP-0198/XMPPStreamManagement.m +++ b/Extensions/XEP-0198/XMPPStreamManagement.m @@ -563,7 +563,7 @@ - (void)processResumed:(NSXMLElement *)resumed for (uint32_t i = 0; i < diff; i++) { - XMPPStreamManagementOutgoingStanza *outgoingStanza = [prev_unackedByServer objectAtIndex:(NSUInteger)i]; + XMPPStreamManagementOutgoingStanza *outgoingStanza = prev_unackedByServer[(NSUInteger) i]; if (outgoingStanza.stanzaId) { [stanzaIds addObject:outgoingStanza.stanzaId]; @@ -947,7 +947,7 @@ - (void)processSentElement:(XMPPElement *)element while ([unprocessedReceivedAcks count] > 0) { - NSXMLElement *ack = [unprocessedReceivedAcks objectAtIndex:0]; + NSXMLElement *ack = unprocessedReceivedAcks[0]; if ([self processReceivedAck:ack]) { @@ -1029,7 +1029,7 @@ - (BOOL)processReceivedAck:(NSXMLElement *)ack for (uint32_t i = 0; i < diff; i++) { - XMPPStreamManagementOutgoingStanza *outgoingStanza = [unackedByServer objectAtIndex:(NSUInteger)i]; + XMPPStreamManagementOutgoingStanza *outgoingStanza = unackedByServer[(NSUInteger) i]; if ([outgoingStanza awaitingStanzaId]) { From 41186fbe040736a9317751b7de929ee5312cbbff Mon Sep 17 00:00:00 2001 From: Jonathon Staff Date: Wed, 4 Feb 2015 14:43:01 -0800 Subject: [PATCH 011/356] More updates to modern syntax --- .../Digest-MD5/XMPPDigestMD5Authentication.m | 10 ++--- .../X-OAuth2-Google/XMPPXOAuth2Google.m | 4 +- Core/XMPPMessage.m | 2 +- .../CoreDataStorage/XMPPCoreDataStorage.m | 12 +++--- Extensions/XEP-0009/XMPPIQ+JabberRPC.m | 2 +- Extensions/XEP-0009/XMPPIQ+JabberRPCResonse.m | 10 ++--- Extensions/XEP-0009/XMPPJabberRPCModule.m | 24 +++++------ .../CoreDataStorage/XMPPRoomCoreDataStorage.m | 2 +- .../XMPPRoomMessageCoreDataStorageObject.m | 2 +- .../HybridStorage/XMPPRoomHybridStorage.m | 38 ++++++++--------- ...PPRoomMessageHybridCoreDataStorageObject.m | 2 +- .../MemoryStorage/XMPPRoomMemoryStorage.m | 22 +++++----- .../XMPPRoomMessageMemoryStorageObject.m | 2 +- Extensions/XEP-0059/XMPPResultSet.m | 4 +- Extensions/XEP-0060/XMPPPubSub.m | 34 +++++++-------- .../XMPPCapsResourceCoreDataStorageObject.m | 2 +- Extensions/XEP-0115/XMPPCapabilities.m | 42 +++++++++---------- Extensions/XEP-0191/XMPPBlocking.m | 32 +++++++------- Utilities/GCDMulticastDelegate.m | 8 ++-- 19 files changed, 126 insertions(+), 128 deletions(-) diff --git a/Authentication/Digest-MD5/XMPPDigestMD5Authentication.m b/Authentication/Digest-MD5/XMPPDigestMD5Authentication.m index 5e3fd636a2..1b98b852bb 100644 --- a/Authentication/Digest-MD5/XMPPDigestMD5Authentication.m +++ b/Authentication/Digest-MD5/XMPPDigestMD5Authentication.m @@ -110,9 +110,9 @@ - (XMPPHandleAuthResponse)handleAuth1:(NSXMLElement *)authResponse NSDictionary *auth = [self dictionaryFromChallenge:authResponse]; - realm = [auth objectForKey:@"realm"]; - nonce = [auth objectForKey:@"nonce"]; - qop = [auth objectForKey:@"qop"]; + realm = auth[@"realm"]; + nonce = auth[@"nonce"]; + qop = auth[@"qop"]; // Fill out all the other variables // @@ -160,7 +160,7 @@ - (XMPPHandleAuthResponse)handleAuth2:(NSXMLElement *)authResponse if ([[authResponse name] isEqualToString:@"challenge"]) { NSDictionary *auth = [self dictionaryFromChallenge:authResponse]; - NSString *rspauth = [auth objectForKey:@"rspauth"]; + NSString *rspauth = auth[@"rspauth"]; if (rspauth == nil) { @@ -244,7 +244,7 @@ - (NSDictionary *)dictionaryFromChallenge:(NSXMLElement *)challenge if(key && value) { - [auth setObject:value forKey:key]; + auth[key] = value; } } } diff --git a/Authentication/X-OAuth2-Google/XMPPXOAuth2Google.m b/Authentication/X-OAuth2-Google/XMPPXOAuth2Google.m index 4a10228df9..e07c361326 100644 --- a/Authentication/X-OAuth2-Google/XMPPXOAuth2Google.m +++ b/Authentication/X-OAuth2-Google/XMPPXOAuth2Google.m @@ -78,7 +78,7 @@ - (BOOL)start:(NSError **)errPtr if (!accessToken) { NSString *errMsg = @"Missing facebook accessToken."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; NSError *err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -158,7 +158,7 @@ - (BOOL)authenticateWithGoogleAccessToken:(NSString *)accessToken error:(NSError else { NSString *errMsg = @"The server does not support X-OATH2-GOOGLE authentication."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; diff --git a/Core/XMPPMessage.m b/Core/XMPPMessage.m index 99ab6a751e..2a44aea747 100644 --- a/Core/XMPPMessage.m +++ b/Core/XMPPMessage.m @@ -255,7 +255,7 @@ - (NSError *)errorMessage NSXMLElement *error = [self elementForName:@"error"]; return [NSError errorWithDomain:@"urn:ietf:params:xml:ns:xmpp-stanzas" code:[error attributeIntValueForName:@"code"] - userInfo:[NSDictionary dictionaryWithObject:[error compactXMLString] forKey:NSLocalizedDescriptionKey]]; + userInfo:@{NSLocalizedDescriptionKey : [error compactXMLString]}]; } diff --git a/Extensions/CoreDataStorage/XMPPCoreDataStorage.m b/Extensions/CoreDataStorage/XMPPCoreDataStorage.m index 567ac44bff..de887075ed 100644 --- a/Extensions/CoreDataStorage/XMPPCoreDataStorage.m +++ b/Extensions/CoreDataStorage/XMPPCoreDataStorage.m @@ -375,13 +375,13 @@ - (XMPPJID *)myJIDForXMPPStream:(XMPPStream *)stream NSNumber *key = [NSNumber xmpp_numberWithPtr:(__bridge void *)stream]; - result = (XMPPJID *)[myJidCache objectForKey:key]; + result = (XMPPJID *) myJidCache[key]; if (!result) { result = [stream myJID]; if (result) { - [myJidCache setObject:result forKey:key]; + myJidCache[key] = result; } } }}; @@ -411,7 +411,7 @@ - (void)updateJidCache:(NSNotification *)notification dispatch_block_t block = ^{ @autoreleasepool { NSNumber *key = [NSNumber xmpp_numberWithPtr:(__bridge void *)stream]; - XMPPJID *cachedJID = [myJidCache objectForKey:key]; + XMPPJID *cachedJID = myJidCache[key]; if (cachedJID) { @@ -421,7 +421,7 @@ - (void)updateJidCache:(NSNotification *)notification { if (![cachedJID isEqualToJID:newJID]) { - [myJidCache setObject:newJID forKey:key]; + myJidCache[key] = newJID; [self didChangeCachedMyJID:newJID forXMPPStream:stream]; } } @@ -446,7 +446,7 @@ - (void)updateJidCache:(NSNotification *)notification - (NSString *)persistentStoreDirectory { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); - NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory(); + NSString *basePath = ([paths count] > 0) ? paths[0] : NSTemporaryDirectory(); // Attempt to find a name for this application NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; @@ -749,7 +749,7 @@ - (void)managedObjectContextDidSave:(NSNotification *)notification dispatch_async(dispatch_get_main_queue(), ^{ // http://stackoverflow.com/questions/3923826/nsfetchedresultscontroller-with-predicate-ignores-changes-merged-from-different - for (NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) { + for (NSManagedObject *object in [notification userInfo][NSUpdatedObjectsKey]) { [[mainThreadManagedObjectContext objectWithID:[object objectID]] willAccessValueForKey:nil]; } diff --git a/Extensions/XEP-0009/XMPPIQ+JabberRPC.m b/Extensions/XEP-0009/XMPPIQ+JabberRPC.m index e711f30bcb..c170d7e044 100644 --- a/Extensions/XEP-0009/XMPPIQ+JabberRPC.m +++ b/Extensions/XEP-0009/XMPPIQ+JabberRPC.m @@ -143,7 +143,7 @@ +(NSXMLElement *)valueElementFromDictionary:(NSDictionary *)dictionary { member = [NSXMLElement elementWithName:@"member"]; name = [NSXMLElement elementWithName:@"name" stringValue:key]; [member addChild:name]; - [member addChild:[self valueElementFromObject:[dictionary objectForKey:key]]]; + [member addChild:[self valueElementFromObject:dictionary[key]]]; } return [self wrapValueElementAroundElement:structElement]; diff --git a/Extensions/XEP-0009/XMPPIQ+JabberRPCResonse.m b/Extensions/XEP-0009/XMPPIQ+JabberRPCResonse.m index c9f081bdf7..3048170f8b 100644 --- a/Extensions/XEP-0009/XMPPIQ+JabberRPCResonse.m +++ b/Extensions/XEP-0009/XMPPIQ+JabberRPCResonse.m @@ -229,7 +229,7 @@ -(NSDictionary *)parseMember:(NSXMLElement *)memberElement { NSString *key = [self objectFromElement:[memberElement elementForName:@"name"]]; id value = [self objectFromElement:[memberElement elementForName:@"value"]]; - return [NSDictionary dictionaryWithObject:value forKey:key]; + return @{key : value}; } #pragma mark - @@ -247,19 +247,19 @@ - (NSDate *)parseDateString: (NSString *)dateString withFormat: (NSString *)form #pragma mark - - (NSNumber *)parseInteger: (NSString *)value { - return [NSNumber numberWithInteger: [value integerValue]]; + return @([value integerValue]); } - (NSNumber *)parseDouble: (NSString *)value { - return [NSNumber numberWithDouble: [value doubleValue]]; + return @([value doubleValue]); } - (NSNumber *)parseBoolean: (NSString *)value { if ([value isEqualToString: @"1"]) { - return [NSNumber numberWithBool: YES]; + return @YES; } - return [NSNumber numberWithBool: NO]; + return @NO; } - (NSString *)parseString: (NSString *)value { diff --git a/Extensions/XEP-0009/XMPPJabberRPCModule.m b/Extensions/XEP-0009/XMPPJabberRPCModule.m index 54c03dd74c..1177ebc08f 100644 --- a/Extensions/XEP-0009/XMPPJabberRPCModule.m +++ b/Extensions/XEP-0009/XMPPJabberRPCModule.m @@ -214,7 +214,7 @@ - (NSString *)sendRpcIQ:(XMPPIQ *)iq withTimeout:(NSTimeInterval)timeout RPCID *rpcID = [[RPCID alloc] initWithRpcID:elementID timer:timer]; - [rpcIDs setObject:rpcID forKey:elementID]; + rpcIDs[elementID] = rpcID; [xmppStream sendElement:iq]; @@ -225,16 +225,15 @@ - (void)timeoutRemoveRpcID:(NSString *)elementID { XMPPLogTrace(); - RPCID *rpcID = [rpcIDs objectForKey:elementID]; + RPCID *rpcID = rpcIDs[elementID]; if (rpcID) { [rpcID cancelTimer]; [rpcIDs removeObjectForKey:elementID]; NSError *error = [NSError errorWithDomain:XMPPJabberRPCErrorDomain - code:1400 - userInfo:[NSDictionary dictionaryWithObjectsAndKeys: - @"Request timed out", @"error",nil]]; + code:1400 + userInfo:@{@"error" : @"Request timed out"}]; [multicastDelegate jabberRPC:self elementID:elementID didReceiveError:error]; } @@ -262,7 +261,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq // we could check the query element, but we should be able to do a lookup based on the unique elementID // because we send an ID, we should get one back - RPCID *rpcID = [rpcIDs objectForKey:elementID]; + RPCID *rpcID = rpcIDs[elementID]; if (rpcID == nil) { return NO; @@ -290,13 +289,12 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq // TODO: implement error parsing // not much specified in XEP, only 403 forbidden error NSXMLElement *errorElement = [iq childErrorElement]; - NSError *error = [NSError errorWithDomain:XMPPJabberRPCErrorDomain - code:[errorElement attributeIntValueForName:@"code"] - userInfo:[NSDictionary dictionaryWithObjectsAndKeys: - [errorElement attributesAsDictionary],@"error", - [[errorElement childAtIndex:0] name], @"condition", - iq,@"iq", - nil]]; + NSError *error = [NSError errorWithDomain:XMPPJabberRPCErrorDomain + code:[errorElement attributeIntValueForName:@"code"] + userInfo:@{ + @"error" : [errorElement attributesAsDictionary], + @"condition" : [[errorElement childAtIndex:0] name], + @"iq" : iq}]; [multicastDelegate jabberRPC:self elementID:elementID didReceiveError:error]; } diff --git a/Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m b/Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m index 6f3a6956ea..f835b3cbcd 100644 --- a/Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m +++ b/Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m @@ -826,7 +826,7 @@ - (NSDate *)mostRecentMessageTimestampForRoom:(XMPPJID *)roomJID } NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"localTimestamp" ascending:NO]; - NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; + NSArray *sortDescriptors = @[sortDescriptor]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:entity]; diff --git a/Extensions/XEP-0045/CoreDataStorage/XMPPRoomMessageCoreDataStorageObject.m b/Extensions/XEP-0045/CoreDataStorage/XMPPRoomMessageCoreDataStorageObject.m index 983ca4adcc..2d43565d20 100644 --- a/Extensions/XEP-0045/CoreDataStorage/XMPPRoomMessageCoreDataStorageObject.m +++ b/Extensions/XEP-0045/CoreDataStorage/XMPPRoomMessageCoreDataStorageObject.m @@ -150,7 +150,7 @@ - (BOOL)isFromMe - (void)setIsFromMe:(BOOL)value { - self.fromMe = [NSNumber numberWithBool:value]; + self.fromMe = @(value); } #pragma mark - Message diff --git a/Extensions/XEP-0045/HybridStorage/XMPPRoomHybridStorage.m b/Extensions/XEP-0045/HybridStorage/XMPPRoomHybridStorage.m index e68d7b7e5f..19c07f2714 100644 --- a/Extensions/XEP-0045/HybridStorage/XMPPRoomHybridStorage.m +++ b/Extensions/XEP-0045/HybridStorage/XMPPRoomHybridStorage.m @@ -607,24 +607,24 @@ - (XMPPRoomOccupantHybridMemoryStorageObject *)insertOccupantWithPresence:(XMPPP XMPPJID *streamFullJid = [self myJIDForXMPPStream:xmppStream]; XMPPJID *roomJid = room.roomJID; - NSMutableDictionary *occupantsRoomsDict = [occupantsGlobalDict objectForKey:streamFullJid]; + NSMutableDictionary *occupantsRoomsDict = occupantsGlobalDict[streamFullJid]; if (occupantsRoomsDict == nil) { occupantsRoomsDict = [[NSMutableDictionary alloc] init]; - [occupantsGlobalDict setObject:occupantsRoomsDict forKey:streamFullJid]; + occupantsGlobalDict[streamFullJid] = occupantsRoomsDict; } - NSMutableDictionary *occupantsRoomDict = [occupantsRoomsDict objectForKey:roomJid]; + NSMutableDictionary *occupantsRoomDict = occupantsRoomsDict[roomJid]; if (occupantsRoomDict == nil) { occupantsRoomDict = [[NSMutableDictionary alloc] init]; - [occupantsRoomsDict setObject:occupantsRoomDict forKey:roomJid]; + occupantsRoomsDict[roomJid] = occupantsRoomDict; } XMPPRoomOccupantHybridMemoryStorageObject *occupant = (XMPPRoomOccupantHybridMemoryStorageObject *) [[self.occupantClass alloc] initWithPresence:presence streamFullJid:streamFullJid]; - [occupantsRoomDict setObject:occupant forKey:occupant.jid]; + occupantsRoomDict[occupant.jid] = occupant; return occupant; } @@ -656,8 +656,8 @@ - (void)removeOccupant:(XMPPRoomOccupantHybridMemoryStorageObject *)occupant XMPPJID *streamFullJid = [self myJIDForXMPPStream:stream]; XMPPJID *roomJid = occupant.roomJID; - NSMutableDictionary *occupantsRoomsDict = [occupantsGlobalDict objectForKey:streamFullJid]; - NSMutableDictionary *occupantsRoomDict = [occupantsRoomsDict objectForKey:roomJid]; + NSMutableDictionary *occupantsRoomsDict = occupantsGlobalDict[streamFullJid]; + NSMutableDictionary *occupantsRoomDict = occupantsRoomsDict[roomJid]; [occupantsRoomDict removeObjectForKey:occupant.jid]; // Remove occupant if ([occupantsRoomDict count] == 0) @@ -715,7 +715,7 @@ - (NSDate *)mostRecentMessageTimestampForRoom:(XMPPJID *)roomJID } NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"localTimestamp" ascending:NO]; - NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; + NSArray *sortDescriptors = @[sortDescriptor]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:entity]; @@ -759,19 +759,19 @@ - (XMPPRoomOccupantHybridMemoryStorageObject *)occupantForJID:(XMPPJID *)occupan { XMPPJID *streamFullJid = [self myJIDForXMPPStream:xmppStream]; - NSDictionary *occupantsRoomsDict = [occupantsGlobalDict objectForKey:streamFullJid]; - NSDictionary *occupantsRoomDict = [occupantsRoomsDict objectForKey:roomJid]; + NSDictionary *occupantsRoomsDict = occupantsGlobalDict[streamFullJid]; + NSDictionary *occupantsRoomDict = occupantsRoomsDict[roomJid]; - occupant = [occupantsRoomDict objectForKey:occupantJid]; + occupant = occupantsRoomDict[occupantJid]; } else { for (XMPPJID *streamFullJid in occupantsGlobalDict) { - NSDictionary *occupantsRoomsDict = [occupantsGlobalDict objectForKey:streamFullJid]; - NSDictionary *occupantsRoomDict = [occupantsRoomsDict objectForKey:roomJid]; + NSDictionary *occupantsRoomsDict = occupantsGlobalDict[streamFullJid]; + NSDictionary *occupantsRoomDict = occupantsRoomsDict[roomJid]; - occupant = [occupantsRoomDict objectForKey:occupantJid]; + occupant = occupantsRoomDict[occupantJid]; if (occupant) break; } } @@ -802,8 +802,8 @@ - (NSArray *)occupantsForRoom:(XMPPJID *)roomJid stream:(XMPPStream *)xmppStream { XMPPJID *streamFullJid = [self myJIDForXMPPStream:xmppStream]; - NSDictionary *occupantsRoomsDict = [occupantsGlobalDict objectForKey:streamFullJid]; - NSDictionary *occupantsRoomDict = [occupantsRoomsDict objectForKey:roomJid]; + NSDictionary *occupantsRoomsDict = occupantsGlobalDict[streamFullJid]; + NSDictionary *occupantsRoomDict = occupantsRoomsDict[roomJid]; results = [occupantsRoomDict allValues]; } @@ -811,8 +811,8 @@ - (NSArray *)occupantsForRoom:(XMPPJID *)roomJid stream:(XMPPStream *)xmppStream { for (XMPPJID *streamFullJid in occupantsGlobalDict) { - NSDictionary *occupantsRoomsDict = [occupantsGlobalDict objectForKey:streamFullJid]; - NSDictionary *occupantsRoomDict = [occupantsRoomsDict objectForKey:roomJid]; + NSDictionary *occupantsRoomsDict = occupantsGlobalDict[streamFullJid]; + NSDictionary *occupantsRoomDict = occupantsRoomsDict[roomJid]; if (occupantsRoomDict) { @@ -981,7 +981,7 @@ - (void)handleDidLeaveRoom:(XMPPRoom *)room XMPPJID *streamFullJid = [self myJIDForXMPPStream:xmppStream]; - NSMutableDictionary *occupantsRoomsDict = [occupantsGlobalDict objectForKey:streamFullJid]; + NSMutableDictionary *occupantsRoomsDict = occupantsGlobalDict[streamFullJid]; [occupantsRoomsDict removeObjectForKey:roomJid]; // Remove room (and all associated occupants) }]; diff --git a/Extensions/XEP-0045/HybridStorage/XMPPRoomMessageHybridCoreDataStorageObject.m b/Extensions/XEP-0045/HybridStorage/XMPPRoomMessageHybridCoreDataStorageObject.m index c4eb758c81..b64d032093 100644 --- a/Extensions/XEP-0045/HybridStorage/XMPPRoomMessageHybridCoreDataStorageObject.m +++ b/Extensions/XEP-0045/HybridStorage/XMPPRoomMessageHybridCoreDataStorageObject.m @@ -150,7 +150,7 @@ - (BOOL)isFromMe - (void)setIsFromMe:(BOOL)value { - self.fromMe = [NSNumber numberWithBool:value]; + self.fromMe = @(value); } #pragma mark - Message diff --git a/Extensions/XEP-0045/MemoryStorage/XMPPRoomMemoryStorage.m b/Extensions/XEP-0045/MemoryStorage/XMPPRoomMemoryStorage.m index 8764c4ee1b..0714f25bfb 100644 --- a/Extensions/XEP-0045/MemoryStorage/XMPPRoomMemoryStorage.m +++ b/Extensions/XEP-0045/MemoryStorage/XMPPRoomMemoryStorage.m @@ -202,7 +202,7 @@ - (BOOL)existsMessage:(XMPPMessage *)message while (YES) { mid = (min + max) / 2; - XMPPRoomMessageMemoryStorageObject *currentMessage = [messages objectAtIndex:mid]; + XMPPRoomMessageMemoryStorageObject *currentMessage = messages[mid]; NSComparisonResult cmp = [minLocalTimestamp compare:[currentMessage localTimestamp]]; if (cmp == NSOrderedAscending) @@ -240,7 +240,7 @@ - (BOOL)existsMessage:(XMPPMessage *)message NSInteger index; for (index = mid; index < [messages count]; index++) { - XMPPRoomMessageMemoryStorageObject *currentMessage = [messages objectAtIndex:index]; + XMPPRoomMessageMemoryStorageObject *currentMessage = messages[index]; NSComparisonResult cmp = [maxLocalTimestamp compare:[currentMessage localTimestamp]]; if (cmp != NSOrderedAscending) @@ -296,7 +296,7 @@ - (NSUInteger)insertMessage:(XMPPRoomMessageMemoryStorageObject *)message // Shortcut - Most (if not all) messages are inserted at the end - XMPPRoomMessageMemoryStorageObject *lastMessage = [messages objectAtIndex:(count - 1)]; + XMPPRoomMessageMemoryStorageObject *lastMessage = messages[count - 1]; if ([message compare:lastMessage] != NSOrderedAscending) { [messages addObject:message]; @@ -313,7 +313,7 @@ - (NSUInteger)insertMessage:(XMPPRoomMessageMemoryStorageObject *)message while (YES) { mid = (min + max) / 2; - XMPPRoomMessageMemoryStorageObject *currentMessage = [messages objectAtIndex:mid]; + XMPPRoomMessageMemoryStorageObject *currentMessage = messages[mid]; NSComparisonResult cmp = [message compare:currentMessage]; if (cmp == NSOrderedAscending) @@ -369,7 +369,7 @@ - (void)addMessage:(XMPPRoomMessageMemoryStorageObject *)roomMsg { NSUInteger index = [self insertMessage:roomMsg]; - XMPPRoomOccupantMemoryStorageObject *occupant = [occupantsDict objectForKey:[roomMsg jid]]; + XMPPRoomOccupantMemoryStorageObject *occupant = occupantsDict[[roomMsg jid]]; XMPPRoomMessageMemoryStorageObject *roomMsgCopy = [roomMsg copy]; XMPPRoomOccupantMemoryStorageObject *occupantCopy = [occupant copy]; @@ -401,7 +401,7 @@ - (NSUInteger)insertOccupant:(XMPPRoomOccupantMemoryStorageObject *)occupant while (YES) { mid = (min + max) / 2; - XMPPRoomOccupantMemoryStorageObject *currentOccupant = [occupantsArray objectAtIndex:mid]; + XMPPRoomOccupantMemoryStorageObject *currentOccupant = occupantsArray[mid]; NSComparisonResult cmp = [occupant compare:currentOccupant]; if (cmp == NSOrderedAscending) @@ -447,7 +447,7 @@ - (XMPPRoomOccupantMemoryStorageObject *)occupantForJID:(XMPPJID *)jid if (dispatch_get_specific(parentQueueTag)) { - return [occupantsDict objectForKey:jid]; + return occupantsDict[jid]; } else { @@ -455,7 +455,7 @@ - (XMPPRoomOccupantMemoryStorageObject *)occupantForJID:(XMPPJID *)jid dispatch_sync(parentQueue, ^{ @autoreleasepool { - occupant = [[occupantsDict objectForKey:jid] copy]; + occupant = [occupantsDict[jid] copy]; }}); return occupant; @@ -587,7 +587,7 @@ - (void)handlePresence:(XMPPPresence *)presence room:(XMPPRoom *)room if ([[presence type] isEqualToString:@"unavailable"]) { - XMPPRoomOccupantMemoryStorageObject *occupant = [occupantsDict objectForKey:from]; + XMPPRoomOccupantMemoryStorageObject *occupant = occupantsDict[from]; if (occupant) { // Occupant did leave - remove @@ -610,7 +610,7 @@ - (void)handlePresence:(XMPPPresence *)presence room:(XMPPRoom *)room } else { - XMPPRoomOccupantMemoryStorageObject *occupant = [occupantsDict objectForKey:from]; + XMPPRoomOccupantMemoryStorageObject *occupant = occupantsDict[from]; if (occupant == nil) { // Occupant did join - add @@ -618,7 +618,7 @@ - (void)handlePresence:(XMPPPresence *)presence room:(XMPPRoom *)room occupant = [[self.occupantClass alloc] initWithPresence:presence]; NSUInteger index = [self insertOccupant:occupant]; - [occupantsDict setObject:occupant forKey:from]; + occupantsDict[from] = occupant; // Notify delegate(s) diff --git a/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.m b/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.m index b57e6f5085..02081fd74a 100644 --- a/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.m +++ b/Extensions/XEP-0045/MemoryStorage/XMPPRoomMessageMemoryStorageObject.m @@ -110,7 +110,7 @@ - (void)encodeWithCoder:(NSCoder *)coder [coder encodeObject:jid]; [coder encodeObject:localTimestamp]; [coder encodeObject:remoteTimestamp]; - [coder encodeObject:[NSNumber numberWithBool:isFromMe]]; + [coder encodeObject:@(isFromMe)]; } } diff --git a/Extensions/XEP-0059/XMPPResultSet.m b/Extensions/XEP-0059/XMPPResultSet.m index 7d9be02aed..87ceb0395c 100644 --- a/Extensions/XEP-0059/XMPPResultSet.m +++ b/Extensions/XEP-0059/XMPPResultSet.m @@ -117,13 +117,13 @@ - (id)initWithMax:(NSInteger)max { if(max != NSNotFound) { - NSXMLElement *maxElement = [NSXMLElement elementWithName:@"max" stringValue:[[NSNumber numberWithInteger:max] stringValue]]; + NSXMLElement *maxElement = [NSXMLElement elementWithName:@"max" stringValue:[@(max) stringValue]]; [self addChild:maxElement]; } if(firstIndex != NSNotFound) { - NSXMLElement *maxElement = [NSXMLElement elementWithName:@"index" stringValue:[[NSNumber numberWithInteger:firstIndex] stringValue]]; + NSXMLElement *maxElement = [NSXMLElement elementWithName:@"index" stringValue:[@(firstIndex) stringValue]]; [self addChild:maxElement]; } diff --git a/Extensions/XEP-0060/XMPPPubSub.m b/Extensions/XEP-0060/XMPPPubSub.m index 5520e1c489..28c329598d 100644 --- a/Extensions/XEP-0060/XMPPPubSub.m +++ b/Extensions/XEP-0060/XMPPPubSub.m @@ -156,7 +156,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq NSString *elementID = [iq elementID]; NSString *node = nil; - if ((node = [subscribeDict objectForKey:elementID])) + if ((node = subscribeDict[elementID])) { // Example subscription success response: // @@ -199,7 +199,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [subscribeDict removeObjectForKey:elementID]; return YES; } - else if ((node = [unsubscribeDict objectForKey:elementID])) + else if ((node = unsubscribeDict[elementID])) { // Example unsubscribe success response: // @@ -230,7 +230,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [unsubscribeDict removeObjectForKey:elementID]; return YES; } - else if ((node = [retrieveDict objectForKey:elementID])) + else if ((node = retrieveDict[elementID])) { // Example retrieve success response: // @@ -273,7 +273,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [retrieveDict removeObjectForKey:elementID]; return YES; } - else if ((node = [configSubDict objectForKey:elementID])) + else if ((node = configSubDict[elementID])) { // Example configure subscription success response: // @@ -296,7 +296,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [configSubDict removeObjectForKey:elementID]; return YES; } - else if ((node = [publishDict objectForKey:elementID])) + else if ((node = publishDict[elementID])) { // Example publish success response: // @@ -324,7 +324,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [publishDict removeObjectForKey:elementID]; return YES; } - else if ((node = [createDict objectForKey:elementID])) + else if ((node = createDict[elementID])) { // Example create success response: // @@ -347,7 +347,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [createDict removeObjectForKey:elementID]; return YES; } - else if ((node = [deleteDict objectForKey:elementID])) + else if ((node = deleteDict[elementID])) { // Example delete success response: // @@ -369,7 +369,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [deleteDict removeObjectForKey:elementID]; return YES; } - else if ((node = [configNodeDict objectForKey:elementID])) + else if ((node = configNodeDict[elementID])) { // Example configure node success response: // @@ -521,7 +521,7 @@ - (NSString *)subscribeToNode:(NSString *)aNode withJID:(XMPPJID *)myBareOrFullJ // Generate uuid and add to dict NSString *uuid = [xmppStream generateUUID]; dispatch_async(moduleQueue, ^{ - [subscribeDict setObject:node forKey:uuid]; + subscribeDict[uuid] = node; }); // Example from XEP-0060 section 6.1.1: @@ -597,7 +597,7 @@ - (NSString *)unsubscribeFromNode:(NSString *)aNode withJID:(XMPPJID *)myBareOrF // Generate uuid and add to dict NSString *uuid = [xmppStream generateUUID]; dispatch_async(moduleQueue, ^{ - [unsubscribeDict setObject:node forKey:uuid]; + unsubscribeDict[uuid] = node; }); // Example from XEP-0060 section 6.2.1: @@ -640,9 +640,9 @@ - (NSString *)retrieveSubscriptionsForNode:(NSString *)aNode NSString *uuid = [xmppStream generateUUID]; dispatch_async(moduleQueue, ^{ if (node) - [retrieveDict setObject:node forKey:uuid]; + retrieveDict[uuid] = node; else - [retrieveDict setObject:[NSNull null] forKey:uuid]; + retrieveDict[uuid] = [NSNull null]; }); // Get subscriptions for all nodes: @@ -693,7 +693,7 @@ - (NSString *)configureSubscriptionToNode:(NSString *)aNode // Generate uuid and add to dict NSString *uuid = [xmppStream generateUUID]; dispatch_async(moduleQueue, ^{ - [configSubDict setObject:node forKey:uuid]; + configSubDict[uuid] = node; }); // Example from XEP-0060 section 6.3.5: @@ -758,7 +758,7 @@ - (NSString *)createNode:(NSString *)aNode withOptions:(NSDictionary *)options // Generate uuid and add to dict NSString *uuid = [xmppStream generateUUID]; dispatch_async(moduleQueue, ^{ - [createDict setObject:node forKey:uuid]; + createDict[uuid] = node; }); // @@ -818,7 +818,7 @@ - (NSString *)deleteNode:(NSString *)aNode // Generate uuid and add to dict NSString *uuid = [xmppStream generateUUID]; dispatch_async(moduleQueue, ^{ - [deleteDict setObject:node forKey:uuid]; + deleteDict[uuid] = node; }); // Example XEP-0060 section 8.4.1: @@ -857,7 +857,7 @@ - (NSString *)configureNode:(NSString *)aNode withOptions:(NSDictionary *)option // Generate uuid and add to dict NSString *uuid = [xmppStream generateUUID]; dispatch_async(moduleQueue, ^{ - [configNodeDict setObject:node forKey:uuid]; + configNodeDict[uuid] = node; }); // @@ -962,7 +962,7 @@ - (NSString *)publishToNode:(NSString *)node [xmppStream sendElement:iq]; dispatch_async(moduleQueue, ^{ - [publishDict setObject:node forKey:uuid]; + publishDict[uuid] = node; }); return uuid; } diff --git a/Extensions/XEP-0115/CoreDataStorage/XMPPCapsResourceCoreDataStorageObject.m b/Extensions/XEP-0115/CoreDataStorage/XMPPCapsResourceCoreDataStorageObject.m index 28d1cc9bb3..183345d308 100644 --- a/Extensions/XEP-0115/CoreDataStorage/XMPPCapsResourceCoreDataStorageObject.m +++ b/Extensions/XEP-0115/CoreDataStorage/XMPPCapsResourceCoreDataStorageObject.m @@ -30,7 +30,7 @@ - (BOOL)haveFailed - (void)setHaveFailed:(BOOL)flag { - self.failed = [NSNumber numberWithBool:flag]; + self.failed = @(flag); } @end diff --git a/Extensions/XEP-0115/XMPPCapabilities.m b/Extensions/XEP-0115/XMPPCapabilities.m index d2dd25e6e3..97318826bb 100644 --- a/Extensions/XEP-0115/XMPPCapabilities.m +++ b/Extensions/XEP-0115/XMPPCapabilities.m @@ -409,12 +409,12 @@ static NSInteger sortFeatures(NSXMLElement *feature1, NSXMLElement *feature2, vo { if ([values count] > 1) { - NSString *baseValue = [[values objectAtIndex:0] stringValue]; + NSString *baseValue = [values[0] stringValue]; NSUInteger i; for (i = 1; i < [values count]; i++) { - NSString *value = [[values objectAtIndex:i] stringValue]; + NSString *value = [values[i] stringValue]; if (![value isEqualToString:baseValue]) { @@ -931,7 +931,7 @@ - (void)fetchCapabilitiesForJID:(XMPPJID *)jid // However, there is still a disco request that concerns the jid. key = [self keyFromHash:hash algorithm:hashAlg]; - NSMutableArray *jids = [discoRequestHashDict objectForKey:key]; + NSMutableArray *jids = discoRequestHashDict[key]; if (jids) { @@ -947,10 +947,10 @@ - (void)fetchCapabilitiesForJID:(XMPPJID *)jid // The first object in the jids array is the index of the last jid that we've sent a disco request to. // This is used in case the jid does not respond. - NSNumber *requestIndexNum = [NSNumber numberWithUnsignedInteger:1]; - jids = [NSMutableArray arrayWithObjects:requestIndexNum, jid, nil]; + NSNumber *requestIndexNum = @1; + jids = [@[requestIndexNum, jid] mutableCopy]; - [discoRequestHashDict setObject:jids forKey:key]; + discoRequestHashDict[key] = jids; [discoRequestJidSet addObject:jid]; } else @@ -1057,7 +1057,7 @@ - (void)handlePresenceCapabilities:(NSXMLElement *)c fromJID:(XMPPJID *)jid // Are we already fetching the capabilities? NSString *key = [self keyFromHash:ver algorithm:hash]; - NSMutableArray *jids = [discoRequestHashDict objectForKey:key]; + NSMutableArray *jids = discoRequestHashDict[key]; if (jids) { @@ -1098,10 +1098,10 @@ - (void)handlePresenceCapabilities:(NSXMLElement *)c fromJID:(XMPPJID *)jid // So how do we know what the next jid in the list is? // Via the requestIndexNum of course. - NSNumber *requestIndexNum = [NSNumber numberWithUnsignedInteger:1]; - jids = [NSMutableArray arrayWithObjects:requestIndexNum, jid, nil]; + NSNumber *requestIndexNum = @1; + jids = [@[requestIndexNum, jid] mutableCopy]; - [discoRequestHashDict setObject:jids forKey:key]; + discoRequestHashDict[key] = jids; [discoRequestJidSet addObject:jid]; // Send disco#info query @@ -1268,12 +1268,12 @@ - (void)handleDiscoResponse:(NSXMLElement *)querySubElement fromJID:(XMPPJID *)j [xmppCapabilitiesStorage setCapabilities:query forHash:hash algorithm:hashAlg]; // Remove the jid(s) from the discoRequest variables - NSArray *jids = [discoRequestHashDict objectForKey:key]; + NSArray *jids = discoRequestHashDict[key]; NSUInteger i; for (i = 1; i < [jids count]; i++) { - XMPPJID *currentJid = [jids objectAtIndex:i]; + XMPPJID *currentJid = jids[i]; [discoRequestJidSet removeObject:currentJid]; @@ -1366,7 +1366,7 @@ - (void)maybeQueryNextJidWithHashKey:(NSString *)key dueToHashMismatch:(BOOL)has // Get the list of jids that have the same capabilities hash - NSMutableArray *jids = [discoRequestHashDict objectForKey:key]; + NSMutableArray *jids = discoRequestHashDict[key]; if (jids == nil) { XMPPLogWarn(@"%@: %@ - Key doesn't exist in discoRequestHashDict", THIS_FILE, THIS_METHOD); @@ -1376,8 +1376,8 @@ - (void)maybeQueryNextJidWithHashKey:(NSString *)key dueToHashMismatch:(BOOL)has // Get the index and jid of the fetch that just failed - NSUInteger requestIndex = [[jids objectAtIndex:0] unsignedIntegerValue]; - XMPPJID *jid = [jids objectAtIndex:requestIndex]; + NSUInteger requestIndex = [jids[0] unsignedIntegerValue]; + XMPPJID *jid = jids[requestIndex]; // Release the associated timer [self cancelTimeoutForDiscoRequestFromJID:jid]; @@ -1395,7 +1395,7 @@ - (void)maybeQueryNextJidWithHashKey:(NSString *)key dueToHashMismatch:(BOOL)has // Increment request index (and update object in jids array), requestIndex++; - [jids replaceObjectAtIndex:0 withObject:[NSNumber numberWithUnsignedInteger:requestIndex]]; + jids[0] = @(requestIndex); } // Do we have another jid that we can query? @@ -1403,7 +1403,7 @@ - (void)maybeQueryNextJidWithHashKey:(NSString *)key dueToHashMismatch:(BOOL)has if (requestIndex < [jids count]) { - jid = [jids objectAtIndex:requestIndex]; + jid = jids[requestIndex]; NSString *node = nil; NSString *ver = nil; @@ -1440,7 +1440,7 @@ - (void)maybeQueryNextJidWithHashKey:(NSString *)key dueToHashMismatch:(BOOL)has NSUInteger i; for (i = 1; i < [jids count]; i++) { - jid = [jids objectAtIndex:i]; + jid = jids[i]; [discoRequestJidSet removeObject:jid]; [xmppCapabilitiesStorage setCapabilitiesFetchFailedForJID:jid xmppStream:xmppStream]; @@ -1656,7 +1656,7 @@ - (void)setupTimeoutForDiscoRequestFromJID:(XMPPJID *)jid GCDTimerWrapper *timerWrapper = [[GCDTimerWrapper alloc] initWithDispatchTimer:timer]; - [discoTimerJidDict setObject:timerWrapper forKey:jid]; + discoTimerJidDict[jid] = timerWrapper; } - (void)setupTimeoutForDiscoRequestFromJID:(XMPPJID *)jid withHashKey:(NSString *)key @@ -1692,7 +1692,7 @@ - (void)setupTimeoutForDiscoRequestFromJID:(XMPPJID *)jid withHashKey:(NSString GCDTimerWrapper *timerWrapper = [[GCDTimerWrapper alloc] initWithDispatchTimer:timer]; - [discoTimerJidDict setObject:timerWrapper forKey:jid]; + discoTimerJidDict[jid] = timerWrapper; } - (void)cancelTimeoutForDiscoRequestFromJID:(XMPPJID *)jid @@ -1702,7 +1702,7 @@ - (void)cancelTimeoutForDiscoRequestFromJID:(XMPPJID *)jid XMPPLogTrace(); - GCDTimerWrapper *timerWrapper = [discoTimerJidDict objectForKey:jid]; + GCDTimerWrapper *timerWrapper = discoTimerJidDict[jid]; if (timerWrapper) { [timerWrapper cancel]; diff --git a/Extensions/XEP-0191/XMPPBlocking.m b/Extensions/XEP-0191/XMPPBlocking.m index 520dfd5293..e36d0e105d 100644 --- a/Extensions/XEP-0191/XMPPBlocking.m +++ b/Extensions/XEP-0191/XMPPBlocking.m @@ -236,10 +236,10 @@ - (void)blockJID:(XMPPJID*)xmppJID { XMPPLogTrace(); - id value = [blockingDict objectForKey:[xmppJID full]]; + id value = blockingDict[[xmppJID full]]; if (value == nil) { - [blockingDict setObject:[NSNull null] forKey:[xmppJID full]]; + blockingDict[[xmppJID full]] = [NSNull null]; } // @@ -268,7 +268,7 @@ - (void)unblockJID:(XMPPJID*)xmppJID { XMPPLogTrace(); - id value = [blockingDict objectForKey:[xmppJID full]]; + id value = blockingDict[[xmppJID full]]; if (value != nil) { [blockingDict removeObjectForKey:[xmppJID full]]; @@ -297,7 +297,7 @@ - (void)unblockJID:(XMPPJID*)xmppJID - (BOOL)containsJID:(XMPPJID*)xmppJID { - if ([blockingDict objectForKey:[xmppJID full]]) + if (blockingDict[[xmppJID full]]) { return true; } @@ -349,7 +349,7 @@ - (void)addQueryInfo:(XMPPBlockingQueryInfo *)queryInfo withKey:(NSString *)uuid queryInfo.timer = timer; // Add to dictionary - [pendingQueries setObject:queryInfo forKey:uuid]; + pendingQueries[uuid] = queryInfo; } - (void)removeQueryInfo:(XMPPBlockingQueryInfo *)queryInfo withKey:(NSString *)uuid @@ -385,7 +385,7 @@ - (void)processQuery:(XMPPBlockingQueryInfo *)queryInfo withFailureCode:(XMPPBlo - (void)queryTimeout:(NSString *)uuid { - XMPPBlockingQueryInfo *queryInfo = [pendingQueries objectForKey:uuid]; + XMPPBlockingQueryInfo *queryInfo = pendingQueries[uuid]; if (queryInfo) { [self processQuery:queryInfo withFailureCode:XMPPBlockingQueryTimeout]; @@ -417,10 +417,10 @@ - (void)processQueryResponse:(XMPPIQ *)iq withInfo:(XMPPBlockingQueryInfo *)quer NSString *name = [listItem attributeStringValueForName:@"jid"]; if (name) { - id value = [blockingDict objectForKey:name]; + id value = blockingDict[name]; if (value == nil) { - [blockingDict setObject:[NSNull null] forKey:name]; + blockingDict[name] = [NSNull null]; } } } @@ -459,12 +459,12 @@ - (void)processQueryResponse:(XMPPIQ *)iq withInfo:(XMPPBlockingQueryInfo *)quer } else { - XMPPBlockingQueryInfo *queryInfo = [pendingQueries objectForKey:[iq elementID]]; + XMPPBlockingQueryInfo *queryInfo = pendingQueries[[iq elementID]]; - id value = [blockingDict objectForKey:[queryInfo.blockingXMPPJID full]]; + id value = blockingDict[[queryInfo.blockingXMPPJID full]]; if (value == nil) { - [blockingDict setObject:[NSNull null] forKey:[queryInfo.blockingXMPPJID full]]; + blockingDict[[queryInfo.blockingXMPPJID full]] = [NSNull null]; } [multicastDelegate xmppBlocking:self didNotBlockJID:queryInfo.blockingXMPPJID error:iq]; @@ -481,12 +481,12 @@ - (void)processQueryResponse:(XMPPIQ *)iq withInfo:(XMPPBlockingQueryInfo *)quer } else { - XMPPBlockingQueryInfo *queryInfo = [pendingQueries objectForKey:[iq elementID]]; + XMPPBlockingQueryInfo *queryInfo = pendingQueries[[iq elementID]]; - id value = [blockingDict objectForKey:[queryInfo.blockingXMPPJID full]]; + id value = blockingDict[[queryInfo.blockingXMPPJID full]]; if (value == nil) { - [blockingDict setObject:[NSNull null] forKey:queryInfo.blockingXMPPJID]; + blockingDict[queryInfo.blockingXMPPJID] = [NSNull null]; } [multicastDelegate xmppBlocking:self didNotUnblockAllDueToError:iq]; @@ -547,7 +547,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq { // This may be a response to a query we sent - XMPPBlockingQueryInfo *queryInfo = [pendingQueries objectForKey:[iq elementID]]; + XMPPBlockingQueryInfo *queryInfo = pendingQueries[[iq elementID]]; if (queryInfo) @@ -568,7 +568,7 @@ -(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error for (NSString *uuid in pendingQueries) { - XMPPBlockingQueryInfo *queryInfo = [pendingQueries objectForKey:uuid]; + XMPPBlockingQueryInfo *queryInfo = pendingQueries[uuid]; [self processQuery:queryInfo withFailureCode:XMPPBlockingDisconnect]; } diff --git a/Utilities/GCDMulticastDelegate.m b/Utilities/GCDMulticastDelegate.m index 1a3cb95c5c..1785c274d4 100644 --- a/Utilities/GCDMulticastDelegate.m +++ b/Utilities/GCDMulticastDelegate.m @@ -109,7 +109,7 @@ - (void)removeDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueu NSUInteger i; for (i = [delegateNodes count]; i > 0; i--) { - GCDMulticastDelegateNode *node = [delegateNodes objectAtIndex:(i-1)]; + GCDMulticastDelegateNode *node = delegateNodes[i - 1]; id nodeDelegate = node.delegate; #if __has_feature(objc_arc_weak) && !TARGET_OS_IPHONE @@ -580,7 +580,7 @@ - (BOOL)getNextDelegate:(id *)delPtr delegateQueue:(dispatch_queue_t *)dqPtr { while (currentNodeIndex < numNodes) { - GCDMulticastDelegateNode *node = [delegateNodes objectAtIndex:currentNodeIndex]; + GCDMulticastDelegateNode *node = delegateNodes[currentNodeIndex]; currentNodeIndex++; id nodeDelegate = node.delegate; // snapshot atomic property @@ -605,7 +605,7 @@ - (BOOL)getNextDelegate:(id *)delPtr delegateQueue:(dispatch_queue_t *)dqPtr ofC { while (currentNodeIndex < numNodes) { - GCDMulticastDelegateNode *node = [delegateNodes objectAtIndex:currentNodeIndex]; + GCDMulticastDelegateNode *node = delegateNodes[currentNodeIndex]; currentNodeIndex++; id nodeDelegate = node.delegate; // snapshot atomic property @@ -630,7 +630,7 @@ - (BOOL)getNextDelegate:(id *)delPtr delegateQueue:(dispatch_queue_t *)dqPtr for { while (currentNodeIndex < numNodes) { - GCDMulticastDelegateNode *node = [delegateNodes objectAtIndex:currentNodeIndex]; + GCDMulticastDelegateNode *node = delegateNodes[currentNodeIndex]; currentNodeIndex++; id nodeDelegate = node.delegate; // snapshot atomic property From 56c5ba0f1af427e7fab316159820eeacefa79eab Mon Sep 17 00:00:00 2001 From: Jonathon Staff Date: Wed, 4 Feb 2015 14:46:26 -0800 Subject: [PATCH 012/356] Most of the project (excluding the vendor dirs) should now be updated to modern syntax. Resolves issue #449. --- .../Anonymous/XMPPAnonymousAuthentication.m | 2 +- .../SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m | 10 ++-- .../XMPPXFacebookPlatformAuthentication.m | 10 ++-- Categories/NSXMLElement+XMPP.m | 44 +++++++------- Core/XMPPParser.m | 4 +- Core/XMPPStream.m | 58 +++++++++---------- .../XMPPGoogleSharedStatus.m | 41 +++++++------ Extensions/ProcessOne/XMPPProcessOne.m | 2 +- Extensions/XEP-0016/XMPPPrivacy.m | 20 +++---- .../XMPPvCardCoreDataStorage.m | 4 +- Extensions/XEP-0054/XMPPvCardTemp.m | 2 +- Extensions/XEP-0065/TURNSocket.m | 26 ++++----- Utilities/XMPPIDTracker.m | 10 ++-- Utilities/XMPPSRVResolver.m | 8 +-- Xcode/iPhoneXMPP/Classes/RootViewController.m | 6 +- .../Classes/iPhoneXMPPAppDelegate.m | 4 +- 16 files changed, 125 insertions(+), 126 deletions(-) diff --git a/Authentication/Anonymous/XMPPAnonymousAuthentication.m b/Authentication/Anonymous/XMPPAnonymousAuthentication.m index 3473139f83..aadc1a7e3c 100644 --- a/Authentication/Anonymous/XMPPAnonymousAuthentication.m +++ b/Authentication/Anonymous/XMPPAnonymousAuthentication.m @@ -109,7 +109,7 @@ - (BOOL)authenticateAnonymously:(NSError **)errPtr else { NSString *errMsg = @"The server does not support anonymous authentication."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; diff --git a/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m b/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m index e57d835233..5330db9f3c 100644 --- a/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m +++ b/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m @@ -111,9 +111,9 @@ - (XMPPHandleAuthResponse)handleAuth1:(NSXMLElement *)authResponse NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; - self.combinedNonce = [auth objectForKey:@"r"]; - self.salt = [auth objectForKey:@"s"]; - self.count = [numberFormatter numberFromString:[auth objectForKey:@"i"]]; + self.combinedNonce = auth[@"r"]; + self.salt = auth[@"s"]; + self.count = [numberFormatter numberFromString:auth[@"i"]]; //We have all the necessary information to calculate client proof and server signature if ([self calculateProofs]) { @@ -137,7 +137,7 @@ - (XMPPHandleAuthResponse)handleAuth2:(NSXMLElement *)authResponse NSDictionary *auth = [self dictionaryFromChallenge:authResponse]; if ([[authResponse name] isEqual:@"success"]) { - NSString *receivedServerSignature = [auth objectForKey:@"v"]; + NSString *receivedServerSignature = auth[@"v"]; if([self.serverSignatureData isEqualToData:[[receivedServerSignature dataUsingEncoding:NSUTF8StringEncoding] xmpp_base64Decoded]]){ return XMPP_AUTH_SUCCESS; @@ -307,7 +307,7 @@ - (NSDictionary *)dictionaryFromChallenge:(NSXMLElement *)challenge if(key && value) { - [auth setObject:value forKey:key]; + auth[key] = value; } } } diff --git a/Authentication/X-Facebook-Platform/XMPPXFacebookPlatformAuthentication.m b/Authentication/X-Facebook-Platform/XMPPXFacebookPlatformAuthentication.m index 1e473e67e1..dccc80d14d 100644 --- a/Authentication/X-Facebook-Platform/XMPPXFacebookPlatformAuthentication.m +++ b/Authentication/X-Facebook-Platform/XMPPXFacebookPlatformAuthentication.m @@ -78,7 +78,7 @@ - (BOOL)start:(NSError **)errPtr if (!appId || !accessToken) { NSString *errMsg = @"Missing facebook appId and/or accessToken."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; NSError *err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -113,8 +113,8 @@ - (XMPPHandleAuthResponse)handleAuth1:(NSXMLElement *)authResponse NSDictionary *auth = [self dictionaryFromChallenge:authResponse]; - nonce = [auth objectForKey:@"nonce"]; - method = [auth objectForKey:@"method"]; + nonce = auth[@"nonce"]; + method = auth[@"method"]; // Create and send challenge response element @@ -188,7 +188,7 @@ - (NSDictionary *)dictionaryFromChallenge:(NSXMLElement *)challenge value = [value substringWithRange:NSMakeRange(1,([value length]-2))]; } - [auth setObject:value forKey:key]; + auth[key] = value; } } @@ -305,7 +305,7 @@ - (BOOL)authenticateWithFacebookAccessToken:(NSString *)accessToken error:(NSErr else { NSString *errMsg = @"The server does not support X-FACEBOOK-PLATFORM authentication."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; diff --git a/Categories/NSXMLElement+XMPP.m b/Categories/NSXMLElement+XMPP.m index 9f516586f1..1daaf2e82f 100644 --- a/Categories/NSXMLElement+XMPP.m +++ b/Categories/NSXMLElement+XMPP.m @@ -129,7 +129,7 @@ - (NSXMLElement *)elementForName:(NSString *)name NSArray *elements = [self elementsForName:name]; if ([elements count] > 0) { - return [elements objectAtIndex:0]; + return elements[0]; } else { @@ -165,7 +165,7 @@ - (NSXMLElement *)elementForName:(NSString *)name xmlns:(NSString *)xmlns NSArray *elements = [self elementsForLocalName:name URI:xmlns]; if ([elements count] > 0) { - return [elements objectAtIndex:0]; + return elements[0]; } else { @@ -289,32 +289,32 @@ - (NSString *)compactXMLString - (void)addAttributeWithName:(NSString *)name intValue:(int)intValue { - [self addAttributeWithName:name numberValue:[NSNumber numberWithInt:intValue]]; + [self addAttributeWithName:name numberValue:@(intValue)]; } - (void)addAttributeWithName:(NSString *)name boolValue:(BOOL)boolValue { - [self addAttributeWithName:name numberValue:[NSNumber numberWithBool:boolValue]]; + [self addAttributeWithName:name numberValue:@(boolValue)]; } - (void)addAttributeWithName:(NSString *)name floatValue:(float)floatValue { - [self addAttributeWithName:name numberValue:[NSNumber numberWithFloat:floatValue]]; + [self addAttributeWithName:name numberValue:@(floatValue)]; } - (void)addAttributeWithName:(NSString *)name doubleValue:(double)doubleValue { - [self addAttributeWithName:name numberValue:[NSNumber numberWithDouble:doubleValue]]; + [self addAttributeWithName:name numberValue:@(doubleValue)]; } - (void)addAttributeWithName:(NSString *)name integerValue:(NSInteger)integerValue { - [self addAttributeWithName:name numberValue:[NSNumber numberWithInteger:integerValue]]; + [self addAttributeWithName:name numberValue:@(integerValue)]; } - (void)addAttributeWithName:(NSString *)name unsignedIntegerValue:(NSUInteger)unsignedIntegerValue { - [self addAttributeWithName:name numberValue:[NSNumber numberWithUnsignedInteger:unsignedIntegerValue]]; + [self addAttributeWithName:name numberValue:@(unsignedIntegerValue)]; } - (void)addAttributeWithName:(NSString *)name stringValue:(NSString *)string @@ -424,43 +424,43 @@ - (NSString *)attributeStringValueForName:(NSString *)name } - (NSNumber *)attributeNumberIntValueForName:(NSString *)name { - return [NSNumber numberWithInt:[self attributeIntValueForName:name]]; + return @([self attributeIntValueForName:name]); } - (NSNumber *)attributeNumberBoolValueForName:(NSString *)name { - return [NSNumber numberWithBool:[self attributeBoolValueForName:name]]; + return @([self attributeBoolValueForName:name]); } - (NSNumber *)attributeNumberFloatValueForName:(NSString *)name { - return [NSNumber numberWithFloat:[self attributeFloatValueForName:name]]; + return @([self attributeFloatValueForName:name]); } - (NSNumber *)attributeNumberDoubleValueForName:(NSString *)name { - return [NSNumber numberWithDouble:[self attributeDoubleValueForName:name]]; + return @([self attributeDoubleValueForName:name]); } - (NSNumber *)attributeNumberInt32ValueForName:(NSString *)name { - return [NSNumber numberWithInt:[self attributeInt32ValueForName:name]]; + return @([self attributeInt32ValueForName:name]); } - (NSNumber *)attributeNumberUInt32ValueForName:(NSString *)name { - return [NSNumber numberWithUnsignedInt:[self attributeUInt32ValueForName:name]]; + return @([self attributeUInt32ValueForName:name]); } - (NSNumber *)attributeNumberInt64ValueForName:(NSString *)name { - return [NSNumber numberWithLongLong:[self attributeInt64ValueForName:name]]; + return @([self attributeInt64ValueForName:name]); } - (NSNumber *)attributeNumberUInt64ValueForName:(NSString *)name { - return [NSNumber numberWithUnsignedLongLong:[self attributeUInt64ValueForName:name]]; + return @([self attributeUInt64ValueForName:name]); } - (NSNumber *)attributeNumberIntegerValueForName:(NSString *)name { - return [NSNumber numberWithInteger:[self attributeIntegerValueForName:name]]; + return @([self attributeIntegerValueForName:name]); } - (NSNumber *)attributeNumberUnsignedIntegerValueForName:(NSString *)name { - return [NSNumber numberWithUnsignedInteger:[self attributeUnsignedIntegerValueForName:name]]; + return @([self attributeUnsignedIntegerValueForName:name]); } /** @@ -543,11 +543,11 @@ - (NSString *)attributeStringValueForName:(NSString *)name withDefaultValue:(NSS } - (NSNumber *)attributeNumberIntValueForName:(NSString *)name withDefaultValue:(int)defaultValue { - return [NSNumber numberWithInt:[self attributeIntValueForName:name withDefaultValue:defaultValue]]; + return @([self attributeIntValueForName:name withDefaultValue:defaultValue]); } - (NSNumber *)attributeNumberBoolValueForName:(NSString *)name withDefaultValue:(BOOL)defaultValue { - return [NSNumber numberWithBool:[self attributeBoolValueForName:name withDefaultValue:defaultValue]]; + return @([self attributeBoolValueForName:name withDefaultValue:defaultValue]); } /** @@ -561,9 +561,9 @@ - (NSMutableDictionary *)attributesAsDictionary NSUInteger i; for(i = 0; i < [attributes count]; i++) { - NSXMLNode *node = [attributes objectAtIndex:i]; + NSXMLNode *node = attributes[i]; - [result setObject:[node stringValue] forKey:[node name]]; + result[[node name]] = [node stringValue]; } return result; } diff --git a/Core/XMPPParser.m b/Core/XMPPParser.m index d0af6ac419..692da86882 100644 --- a/Core/XMPPParser.m +++ b/Core/XMPPParser.m @@ -426,7 +426,7 @@ static void xmpp_xmlAbortDueToMemoryShortage(xmlParserCtxt *ctxt) if (parser->delegateQueue && [parser->delegate respondsToSelector:@selector(xmppParser:didFail:)]) { NSString *errMsg = @"Unable to allocate memory in xmpp parser"; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; NSError *error = [NSError errorWithDomain:@"libxmlErrorDomain" code:1001 userInfo:info]; @@ -822,7 +822,7 @@ - (void)parseData:(NSData *)data if (xmlErr->message) { NSString *errMsg = [NSString stringWithFormat:@"%s", xmlErr->message]; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; error = [NSError errorWithDomain:@"libxmlErrorDomain" code:xmlErr->code userInfo:info]; } diff --git a/Core/XMPPStream.m b/Core/XMPPStream.m index 3ebe8a3db3..604702c81c 100644 --- a/Core/XMPPStream.m +++ b/Core/XMPPStream.m @@ -1064,7 +1064,7 @@ - (BOOL)connectWithTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr if (state != STATE_XMPP_DISCONNECTED) { NSString *errMsg = @"Attempting to connect while already connected or connecting."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -1075,7 +1075,7 @@ - (BOOL)connectWithTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr if ([self isP2P]) { NSString *errMsg = @"P2P streams must use either connectTo:withAddress: or connectP2PWithSocket:."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidType userInfo:info]; @@ -1100,7 +1100,7 @@ - (BOOL)connectWithTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr // but the xmpp handshake requires the xmpp domain (testing.mycompany.com). NSString *errMsg = @"You must set myJID before calling connect."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidProperty userInfo:info]; @@ -1221,7 +1221,7 @@ - (BOOL)connectTo:(XMPPJID *)jid withAddress:(NSData *)remoteAddr withTimeout:(N if (state != STATE_XMPP_DISCONNECTED) { NSString *errMsg = @"Attempting to connect while already connected or connecting."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -1232,7 +1232,7 @@ - (BOOL)connectTo:(XMPPJID *)jid withAddress:(NSData *)remoteAddr withTimeout:(N if (![self isP2P]) { NSString *errMsg = @"Non P2P streams must use the connect: method"; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidType userInfo:info]; @@ -1307,7 +1307,7 @@ - (BOOL)connectP2PWithSocket:(GCDAsyncSocket *)acceptedSocket error:(NSError **) if (state != STATE_XMPP_DISCONNECTED) { NSString *errMsg = @"Attempting to connect while already connected or connecting."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -1318,7 +1318,7 @@ - (BOOL)connectP2PWithSocket:(GCDAsyncSocket *)acceptedSocket error:(NSError **) if (![self isP2P]) { NSString *errMsg = @"Non P2P streams must use the connect: method"; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidType userInfo:info]; @@ -1329,7 +1329,7 @@ - (BOOL)connectP2PWithSocket:(GCDAsyncSocket *)acceptedSocket error:(NSError **) if (acceptedSocket == nil) { NSString *errMsg = @"Parameter acceptedSocket is nil."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidParameter userInfo:info]; @@ -1551,7 +1551,7 @@ - (BOOL)secureConnection:(NSError **)errPtr if (state != STATE_XMPP_CONNECTED) { NSString *errMsg = @"Please wait until the stream is connected."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -1562,7 +1562,7 @@ - (BOOL)secureConnection:(NSError **)errPtr if ([self isSecure]) { NSString *errMsg = @"The connection is already secure."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -1573,7 +1573,7 @@ - (BOOL)secureConnection:(NSError **)errPtr if (![self supportsStartTLS]) { NSString *errMsg = @"The server does not support startTLS."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; @@ -1655,7 +1655,7 @@ - (BOOL)registerWithElements:(NSArray *)elements error:(NSError **)errPtr if (state != STATE_XMPP_CONNECTED) { NSString *errMsg = @"Please wait until the stream is connected."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -1666,7 +1666,7 @@ - (BOOL)registerWithElements:(NSArray *)elements error:(NSError **)errPtr if (![self supportsInBandRegistration]) { NSString *errMsg = @"The server does not support in band registration."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; @@ -1729,7 +1729,7 @@ - (BOOL)registerWithPassword:(NSString *)password error:(NSError **)errPtr if (myJID_setByClient == nil) { NSString *errMsg = @"You must set myJID before calling registerWithPassword:error:."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidProperty userInfo:info]; @@ -1846,7 +1846,7 @@ - (BOOL)authenticate:(id )inAuth error:(NSError **)errPt if (state != STATE_XMPP_CONNECTED) { NSString *errMsg = @"Please wait until the stream is connected."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -1857,7 +1857,7 @@ - (BOOL)authenticate:(id )inAuth error:(NSError **)errPt if (myJID_setByClient == nil) { NSString *errMsg = @"You must set myJID before calling authenticate:error:."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidProperty userInfo:info]; @@ -1918,7 +1918,7 @@ - (BOOL)authenticateWithPassword:(NSString *)inPassword error:(NSError **)errPtr if (state != STATE_XMPP_CONNECTED) { NSString *errMsg = @"Please wait until the stream is connected."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; @@ -1929,7 +1929,7 @@ - (BOOL)authenticateWithPassword:(NSString *)inPassword error:(NSError **)errPtr if (myJID_setByClient == nil) { NSString *errMsg = @"You must set myJID before calling authenticate:error:."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidProperty userInfo:info]; @@ -1971,7 +1971,7 @@ - (BOOL)authenticateWithPassword:(NSString *)inPassword error:(NSError **)errPtr else { NSString *errMsg = @"No suitable authentication method found"; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; @@ -3402,7 +3402,7 @@ - (void)continueStartTLS:(NSMutableDictionary *)settings if ([expectedCertName length] > 0) { - [settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName]; + settings[(NSString *) kCFStreamSSLPeerName] = expectedCertName; } } @@ -3471,7 +3471,7 @@ - (void)handleStreamFeatures // We must abort the connection as the server doesn't support our requirements. NSString *errMsg = @"The server does not support startTLS. And the startTLSPolicy is Required."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; otherError = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info]; @@ -4070,7 +4070,7 @@ - (void)tryNextSrvResult while (srvResultsIndex < [srvResults count]) { - XMPPSRVRecord *srvRecord = [srvResults objectAtIndex:srvResultsIndex]; + XMPPSRVRecord *srvRecord = srvResults[srvResultsIndex]; NSString *srvHost = srvRecord.target; UInt16 srvPort = srvRecord.port; @@ -4291,7 +4291,7 @@ - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag return; } - XMPPElementReceipt *receipt = [receipts objectAtIndex:0]; + XMPPElementReceipt *receipt = receipts[0]; [receipt signalSuccess]; [receipts removeObjectAtIndex:0]; } @@ -4503,7 +4503,7 @@ - (void)xmppParser:(XMPPParser *)sender didReadElement:(NSXMLElement *)element { // We've just read in the stream features // We consider this part of the root element, so we'll add it (replacing any previously sent features) - [rootElement setChildren:[NSArray arrayWithObject:element]]; + [rootElement setChildren:@[element]]; // Call a method to handle any requirements set forth in the features [self handleStreamFeatures]; @@ -4779,7 +4779,7 @@ - (void)registerModule:(XMPPModule *)module // Add auto delegates (if there are any) NSString *className = NSStringFromClass([module class]); - GCDMulticastDelegate *autoDelegates = [autoDelegateDict objectForKey:className]; + GCDMulticastDelegate *autoDelegates = autoDelegateDict[className]; GCDMulticastDelegateEnumerator *autoDelegatesEnumerator = [autoDelegates delegateEnumerator]; id delegate; @@ -4819,7 +4819,7 @@ - (void)unregisterModule:(XMPPModule *)module // Remove auto delegates (if there are any) NSString *className = NSStringFromClass([module class]); - GCDMulticastDelegate *autoDelegates = [autoDelegateDict objectForKey:className]; + GCDMulticastDelegate *autoDelegates = autoDelegateDict[className]; GCDMulticastDelegateEnumerator *autoDelegatesEnumerator = [autoDelegates delegateEnumerator]; id delegate; @@ -4873,12 +4873,12 @@ - (void)autoAddDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQue // Add the delegate to list of auto delegates for the given class. // It will be added as a delegate to future registered modules of the given class. - id delegates = [autoDelegateDict objectForKey:className]; + id delegates = autoDelegateDict[className]; if (delegates == nil) { delegates = [[GCDMulticastDelegate alloc] init]; - [autoDelegateDict setObject:delegates forKey:className]; + autoDelegateDict[className] = delegates; } [delegates addDelegate:delegate delegateQueue:delegateQueue]; @@ -4937,7 +4937,7 @@ - (void)removeAutoDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegate // Remove the delegate from list of auto delegates for the given class, // so that it will not be added as a delegate to future registered modules of the given class. - GCDMulticastDelegate *delegates = [autoDelegateDict objectForKey:className]; + GCDMulticastDelegate *delegates = autoDelegateDict[className]; [delegates removeDelegate:delegate delegateQueue:delegateQueue]; if ([delegates count] == 0) diff --git a/Extensions/GoogleSharedStatus/XMPPGoogleSharedStatus.m b/Extensions/GoogleSharedStatus/XMPPGoogleSharedStatus.m index eea122206f..21a07680fa 100644 --- a/Extensions/GoogleSharedStatus/XMPPGoogleSharedStatus.m +++ b/Extensions/GoogleSharedStatus/XMPPGoogleSharedStatus.m @@ -119,44 +119,44 @@ - (void)updateSharedStatus:(NSString *)status show:(NSString *)show invisible:(B status = [status substringToIndex:_statusMessageMaxLength]; // If the show has changed update it. - if(![show isEqualToString:[sharedStatusUpdate objectForKey:XMPPGoogleSharedStatusShow]]) { + if(![show isEqualToString:sharedStatusUpdate[XMPPGoogleSharedStatusShow]]) { [sharedStatusUpdate removeObjectForKey:XMPPGoogleSharedStatusShow]; - [sharedStatusUpdate setObject:show forKey:XMPPGoogleSharedStatusShow]; + sharedStatusUpdate[XMPPGoogleSharedStatusShow] = show; } // Get the current show value, and whether the status should update for it. BOOL displayShow = ([show isEqualToString:XMPPGoogleSharedStatusShowAvailable] || [show isEqualToString:XMPPGoogleSharedStatusShowBusy]); - NSString *currentShow = [self.sharedStatus objectForKey:XMPPGoogleSharedStatusShow]; + NSString *currentShow = self.sharedStatus[XMPPGoogleSharedStatusShow]; // Since we can't show an away status, only change the status it has // changed and is not showing idle. - if(![status isEqualToString:[sharedStatusUpdate objectForKey:XMPPGoogleSharedStatusStatus]] && displayShow) { + if(![status isEqualToString:sharedStatusUpdate[XMPPGoogleSharedStatusStatus]] && displayShow) { [sharedStatusUpdate removeObjectForKey:XMPPGoogleSharedStatusStatus]; - [sharedStatusUpdate setObject:status forKey:XMPPGoogleSharedStatusStatus]; + sharedStatusUpdate[XMPPGoogleSharedStatusStatus] = status; // Update the appropriate status list by adding the new status. // If the list max count was reached, truncate its earliest status. - NSMutableArray *statusList = [[sharedStatusUpdate objectForKey:currentShow] mutableCopy]; + NSMutableArray *statusList = [sharedStatusUpdate[currentShow] mutableCopy]; [statusList insertObject:status atIndex:0]; if(statusList.count > _statusListMaxCount) [statusList removeObjectAtIndex:statusList.count-1]; // Remove any blank statuses. for(int i = 0; i < statusList.count; i++) { - NSString *status = [statusList objectAtIndex:i]; + NSString *status = statusList[i]; if([status isEqualToString:@""]) [statusList removeObjectAtIndex:i]; } // Update the status list for this status. [sharedStatusUpdate removeObjectForKey:currentShow]; - [sharedStatusUpdate setObject:statusList forKey:currentShow]; + sharedStatusUpdate[currentShow] = statusList; } // Update the invisibility for this shared status. [sharedStatusUpdate removeObjectForKey:XMPPGoogleSharedStatusInvisible]; - [sharedStatusUpdate setObject:[NSNumber numberWithBool:invisible] forKey:XMPPGoogleSharedStatusInvisible]; + sharedStatusUpdate[XMPPGoogleSharedStatusInvisible] = @(invisible); // Wrap it in an XMPPIQ "set" and send it to the server. XMPPIQ *statusIQ = [XMPPIQ iqWithType:@"set" to:self.xmppStream.myJID.bareJID]; @@ -211,12 +211,12 @@ - (void)refreshSharedStatus { // information attributes as well, so save those. // If we received a discovery IQ, determine shared status support. - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq { - XMPPElement *query = (XMPPElement *)[[iq children] objectAtIndex:0]; + XMPPElement *query = (XMPPElement *) [iq children][0]; if([query.xmlns isEqualToString:GOOGLE_SHARED_STATUS] && self.sharedStatusSupported) { self.sharedStatus = [self unpackSharedStatus:query]; - _show = [self.sharedStatus objectForKey:XMPPGoogleSharedStatusShow]; - _status = [self.sharedStatus objectForKey:XMPPGoogleSharedStatusStatus]; - _invisible = [[self.sharedStatus objectForKey:XMPPGoogleSharedStatusInvisible] boolValue]; + _show = self.sharedStatus[XMPPGoogleSharedStatusShow]; + _status = self.sharedStatus[XMPPGoogleSharedStatusStatus]; + _invisible = [self.sharedStatus[XMPPGoogleSharedStatusInvisible] boolValue]; [multicastDelegate xmppGoogleSharedStatus:self didReceiveUpdatedStatus:self.sharedStatus]; if([query attributeForName:@"status-max"]) @@ -247,14 +247,13 @@ - (NSDictionary *)unpackSharedStatus:(XMPPElement *)sharedStatus { NSMutableArray *array = [NSMutableArray array]; for(XMPPElement *status in element.children) [array addObject:[status stringValue]]; - [dict setObject:array forKey:[[element attributeForName:XMPPGoogleSharedStatusShow] stringValue]]; + dict[[[element attributeForName:XMPPGoogleSharedStatusShow] stringValue]] = array; } else if([element.name isEqualToString:XMPPGoogleSharedStatusStatus]) { - [dict setObject:[element stringValue] forKey:element.name]; + dict[element.name] = [element stringValue]; } else if([element.name isEqualToString:XMPPGoogleSharedStatusShow]) { - [dict setObject:[element stringValue] forKey:element.name]; + dict[element.name] = [element stringValue]; } else if([element.name isEqualToString:XMPPGoogleSharedStatusInvisible]) { - [dict setObject:[NSNumber numberWithBool:[[[element attributeForName:@"value"] stringValue] boolValue]] - forKey:element.name]; + dict[element.name] = @([[[element attributeForName:@"value"] stringValue] boolValue]); } else { NSLog(@"Missed element: %@", element); } @@ -273,15 +272,15 @@ - (XMPPElement *)packSharedStatus:(NSDictionary *)sharedStatus { [element addAttributeWithName:@"version" stringValue:@"2"]; [element addChild:[XMPPElement elementWithName:XMPPGoogleSharedStatusStatus - stringValue:[sharedStatus objectForKey:XMPPGoogleSharedStatusStatus]]]; + stringValue:sharedStatus[XMPPGoogleSharedStatusStatus]]]; [element addChild:[XMPPElement elementWithName:XMPPGoogleSharedStatusShow - stringValue:[sharedStatus objectForKey:XMPPGoogleSharedStatusShow]]]; + stringValue:sharedStatus[XMPPGoogleSharedStatusShow]]]; for(NSString *key in sharedStatus.allKeys.reverseObjectEnumerator) { if([key isEqualToString:XMPPGoogleSharedStatusShowAvailable] || [key isEqualToString:XMPPGoogleSharedStatusShowBusy]) { - NSArray *statusList = [sharedStatus objectForKey:key]; + NSArray *statusList = sharedStatus[key]; XMPPElement *statusElement = [XMPPElement elementWithName:@"status-list"]; [statusElement addAttributeWithName:@"show" stringValue:key]; diff --git a/Extensions/ProcessOne/XMPPProcessOne.m b/Extensions/ProcessOne/XMPPProcessOne.m index 2ebbae4b71..a5d003bfde 100644 --- a/Extensions/ProcessOne/XMPPProcessOne.m +++ b/Extensions/ProcessOne/XMPPProcessOne.m @@ -311,7 +311,7 @@ - (BOOL)start:(NSError **)errPtr if (!sessionID || !sessionJID) { NSString *errMsg = @"Missing sessionID and/or sessionJID."; - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *info = @{NSLocalizedDescriptionKey : errMsg}; NSError *err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamInvalidState userInfo:info]; diff --git a/Extensions/XEP-0016/XMPPPrivacy.m b/Extensions/XEP-0016/XMPPPrivacy.m index 345211b069..cdf6880105 100644 --- a/Extensions/XEP-0016/XMPPPrivacy.m +++ b/Extensions/XEP-0016/XMPPPrivacy.m @@ -296,7 +296,7 @@ - (NSArray *)listWithName:(NSString *)privacyListName { NSArray* (^block)() = ^ NSArray* () { - id result = [privacyDict objectForKey:privacyListName]; + id result = privacyDict[privacyListName]; if (result == [NSNull null]) // Not fetched yet return nil; @@ -482,7 +482,7 @@ - (void)addQueryInfo:(XMPPPrivacyQueryInfo *)queryInfo withKey:(NSString *)uuid queryInfo.timer = timer; // Add to dictionary - [pendingQueries setObject:queryInfo forKey:uuid]; + pendingQueries[uuid] = queryInfo; } - (void)removeQueryInfo:(XMPPPrivacyQueryInfo *)queryInfo withKey:(NSString *)uuid @@ -522,7 +522,7 @@ - (void)processQuery:(XMPPPrivacyQueryInfo *)queryInfo withFailureCode:(XMPPPriv - (void)queryTimeout:(NSString *)uuid { - XMPPPrivacyQueryInfo *queryInfo = [privacyDict objectForKey:uuid]; + XMPPPrivacyQueryInfo *queryInfo = privacyDict[uuid]; if (queryInfo) { [self processQuery:queryInfo withFailureCode:XMPPPrivacyQueryTimeout]; @@ -615,10 +615,10 @@ - (void)processQueryResponse:(XMPPIQ *)iq withInfo:(XMPPPrivacyQueryInfo *)query NSString *name = [listName attributeStringValueForName:@"name"]; if (name) { - id value = [privacyDict objectForKey:name]; + id value = privacyDict[name]; if (value == nil) { - [privacyDict setObject:[NSNull null] forKey:name]; + privacyDict[name] = [NSNull null]; } } } @@ -670,7 +670,7 @@ - (void)processQueryResponse:(XMPPIQ *)iq withInfo:(XMPPPrivacyQueryInfo *)query items = [NSArray array]; } - [privacyDict setObject:items forKey:queryInfo.privacyListName]; + privacyDict[queryInfo.privacyListName] = items; [multicastDelegate xmppPrivacy:self didReceiveListWithName:queryInfo.privacyListName items:items]; } @@ -696,7 +696,7 @@ - (void)processQueryResponse:(XMPPIQ *)iq withInfo:(XMPPPrivacyQueryInfo *)query items = [NSArray array]; } - [privacyDict setObject:items forKey:queryInfo.privacyListName]; + privacyDict[queryInfo.privacyListName] = items; [multicastDelegate xmppPrivacy:self didSetListWithName:queryInfo.privacyListName]; } @@ -832,7 +832,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq { // This may be a response to a query we sent - XMPPPrivacyQueryInfo *queryInfo = [pendingQueries objectForKey:[iq elementID]]; + XMPPPrivacyQueryInfo *queryInfo = pendingQueries[[iq elementID]]; if (queryInfo) { [self processQueryResponse:iq withInfo:queryInfo]; @@ -841,7 +841,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq { for (NSString *privacyListName in privacyDict) { - id privacyListItems = [privacyDict objectForKey:privacyListName]; + id privacyListItems = privacyDict[privacyListName]; if (privacyListItems == [NSNull null]) { @@ -864,7 +864,7 @@ -(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error for (NSString *uuid in pendingQueries) { - XMPPPrivacyQueryInfo *queryInfo = [privacyDict objectForKey:uuid]; + XMPPPrivacyQueryInfo *queryInfo = privacyDict[uuid]; [self processQuery:queryInfo withFailureCode:XMPPPrivacyDisconnect]; } diff --git a/Extensions/XEP-0054/CoreDataStorage/XMPPvCardCoreDataStorage.m b/Extensions/XEP-0054/CoreDataStorage/XMPPvCardCoreDataStorage.m index e7b84ec7bc..221073c0bc 100644 --- a/Extensions/XEP-0054/CoreDataStorage/XMPPvCardCoreDataStorage.m +++ b/Extensions/XEP-0054/CoreDataStorage/XMPPvCardCoreDataStorage.m @@ -170,7 +170,7 @@ - (void)setvCardTemp:(XMPPvCardTemp *)vCardTemp forJID:(XMPPJID *)jid xmppStream vCard = [XMPPvCardCoreDataStorageObject fetchOrInsertvCardForJID:jid inManagedObjectContext:[self managedObjectContext]]; - vCard.waitingForFetch = [NSNumber numberWithBool:NO]; + vCard.waitingForFetch = @NO; vCard.vCardTemp = vCardTemp; // Update photo and photo hash @@ -210,7 +210,7 @@ - (BOOL)shouldFetchvCardTempForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)strea } else if (!waitingForFetch) { - vCard.waitingForFetch = [NSNumber numberWithBool:YES]; + vCard.waitingForFetch = @YES; vCard.lastUpdated = [NSDate date]; result = YES; diff --git a/Extensions/XEP-0054/XMPPvCardTemp.m b/Extensions/XEP-0054/XMPPvCardTemp.m index 63faffc488..a4df1f9597 100644 --- a/Extensions/XEP-0054/XMPPvCardTemp.m +++ b/Extensions/XEP-0054/XMPPvCardTemp.m @@ -858,7 +858,7 @@ - (void)setPrivacyClass:(XMPPvCardTempClass)privacyClass { } if (elem != nil) { - for (NSString *cls in [NSArray arrayWithObjects:@"PUBLIC", @"PRIVATE", @"CONFIDENTIAL", nil]) { + for (NSString *cls in @[@"PUBLIC", @"PRIVATE", @"CONFIDENTIAL"]) { NSXMLElement *priv = [elem elementForName:cls]; if (priv != nil) { [elem removeChildAtIndex:[[elem children] indexOfObject:priv]]; diff --git a/Extensions/XEP-0065/TURNSocket.m b/Extensions/XEP-0065/TURNSocket.m index a25c3f5f51..121f324e84 100644 --- a/Extensions/XEP-0065/TURNSocket.m +++ b/Extensions/XEP-0065/TURNSocket.m @@ -92,7 +92,7 @@ + (void)initialize initialized = YES; existingTurnSockets = [[NSMutableDictionary alloc] init]; - proxyCandidates = [[NSMutableArray alloc] initWithObjects:@"jabber.org", nil]; + proxyCandidates = [@[@"jabber.org"] mutableCopy]; } } @@ -140,7 +140,7 @@ + (BOOL)isNewStartTURNRequest:(XMPPIQ *)iq @synchronized(existingTurnSockets) { - if ([existingTurnSockets objectForKey:uuid]) + if (existingTurnSockets[uuid]) return NO; else return YES; @@ -266,7 +266,7 @@ - (void)performPostInitSetup @synchronized(existingTurnSockets) { - [existingTurnSockets setObject:self forKey:uuid]; + existingTurnSockets[uuid] = self; } } @@ -441,7 +441,7 @@ - (void)sendRequest NSUInteger i; for(i = 0; i < [streamhosts count]; i++) { - [query addChild:[streamhosts objectAtIndex:i]]; + [query addChild:streamhosts[i]]; } XMPPIQ *iq = [XMPPIQ iqWithType:@"set" to:jid elementID:uuid child:query]; @@ -603,7 +603,7 @@ - (void)processDiscoItemsResponse:(XMPPIQ *)iq NSUInteger i; for(i = 0; i < [items count]; i++) { - NSString *itemJidStr = [[[items objectAtIndex:i] attributeForName:@"jid"] stringValue]; + NSString *itemJidStr = [[items[i] attributeForName:@"jid"] stringValue]; XMPPJID *itemJid = [XMPPJID jidWithString:itemJidStr]; if(itemJid) @@ -636,7 +636,7 @@ - (void)processDiscoInfoResponse:(XMPPIQ *)iq NSUInteger i; for(i = 0; i < [identities count] && !found; i++) { - NSXMLElement *identity = [identities objectAtIndex:i]; + NSXMLElement *identity = identities[i]; NSString *category = [[identity attributeForName:@"category"] stringValue]; NSString *type = [[identity attributeForName:@"type"] stringValue]; @@ -663,7 +663,7 @@ - (void)processDiscoInfoResponse:(XMPPIQ *)iq // We could ignore the 404 error, and try to connect anyways, // but this would be useless because we'd be unable to activate the stream later. - XMPPJID *candidateJID = [candidateJIDs objectAtIndex:candidateJIDIndex]; + XMPPJID *candidateJID = candidateJIDs[candidateJIDIndex]; // So the service was not a useable proxy service, or will not allow us to use its proxy. // @@ -731,7 +731,7 @@ - (void)processRequestResponse:(XMPPIQ *)iq NSUInteger i; for(i = 0; i < [streamhosts count] && !found; i++) { - NSXMLElement *streamhost = [streamhosts objectAtIndex:i]; + NSXMLElement *streamhost = streamhosts[i]; NSString *streamhostJID = [[streamhost attributeForName:@"jid"] stringValue]; @@ -839,7 +839,7 @@ - (void)queryNextProxyCandidate { while ((proxyCandidateJID == nil) && (++proxyCandidateIndex < [proxyCandidates count])) { - NSString *proxyCandidate = [proxyCandidates objectAtIndex:proxyCandidateIndex]; + NSString *proxyCandidate = proxyCandidates[proxyCandidateIndex]; proxyCandidateJID = [XMPPJID jidWithString:proxyCandidate]; if (proxyCandidateJID == nil) @@ -896,7 +896,7 @@ - (void)queryCandidateJIDs NSUInteger i; for (i = 0; i < [candidateJIDs count]; i++) { - XMPPJID *candidateJID = [candidateJIDs objectAtIndex:i]; + XMPPJID *candidateJID = candidateJIDs[i]; NSRange proxyRange = [[candidateJID domain] rangeOfString:@"proxy" options:NSCaseInsensitiveSearch]; @@ -930,7 +930,7 @@ - (void)queryNextCandidateJID { [self updateDiscoUUID]; - XMPPJID *candidateJID = [candidateJIDs objectAtIndex:candidateJIDIndex]; + XMPPJID *candidateJID = candidateJIDs[candidateJIDIndex]; NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"http://jabber.org/protocol/disco#info"]; @@ -960,7 +960,7 @@ - (void)queryProxyAddress [self updateDiscoUUID]; - XMPPJID *candidateJID = [candidateJIDs objectAtIndex:candidateJIDIndex]; + XMPPJID *candidateJID = candidateJIDs[candidateJIDIndex]; NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"http://jabber.org/protocol/bytestreams"]; @@ -994,7 +994,7 @@ - (void)targetNextConnect streamhostIndex++; if(streamhostIndex < [streamhosts count]) { - NSXMLElement *streamhost = [streamhosts objectAtIndex:streamhostIndex]; + NSXMLElement *streamhost = streamhosts[streamhostIndex]; proxyJID = [XMPPJID jidWithString:[[streamhost attributeForName:@"jid"] stringValue]]; diff --git a/Utilities/XMPPIDTracker.m b/Utilities/XMPPIDTracker.m index b7e8ac6a5d..2bd62db7d5 100644 --- a/Utilities/XMPPIDTracker.m +++ b/Utilities/XMPPIDTracker.m @@ -128,7 +128,7 @@ - (void)addID:(NSString *)elementID trackingInfo:(id )tracking { AssertProperQueue(); - [dict setObject:trackingInfo forKey:elementID]; + dict[elementID] = trackingInfo; [trackingInfo setElementID:elementID]; [trackingInfo createTimerWithDispatchQueue:queue]; @@ -140,7 +140,7 @@ - (void)addElement:(XMPPElement *)element trackingInfo:(id )tr if([[element elementID] length] == 0) return; - [dict setObject:trackingInfo forKey:[element elementID]]; + dict[[element elementID]] = trackingInfo; [trackingInfo setElementID:[element elementID]]; [trackingInfo setElement:element]; @@ -153,7 +153,7 @@ - (BOOL)invokeForID:(NSString *)elementID withObject:(id)obj if([elementID length] == 0) return NO; - id info = [dict objectForKey:elementID]; + id info = dict[elementID]; if (info) { @@ -175,7 +175,7 @@ - (BOOL)invokeForElement:(XMPPElement *)element withObject:(id)obj if ([elementID length] == 0) return NO; - id info = [dict objectForKey:elementID]; + id info = dict[elementID]; if(info) { BOOL valid = YES; @@ -219,7 +219,7 @@ - (void)removeID:(NSString *)elementID { AssertProperQueue(); - id info = [dict objectForKey:elementID]; + id info = dict[elementID]; if (info) { [info cancelTimer]; diff --git a/Utilities/XMPPSRVResolver.m b/Utilities/XMPPSRVResolver.m index 0e9e985b27..8faa6ea8cb 100644 --- a/Utilities/XMPPSRVResolver.m +++ b/Utilities/XMPPSRVResolver.m @@ -168,7 +168,7 @@ - (void)sortResults if (srvResultsCount == 1) { - XMPPSRVRecord *srvRecord = [results objectAtIndex:0]; + XMPPSRVRecord *srvRecord = results[0]; [sortedResults addObject:srvRecord]; [results removeObjectAtIndex:0]; @@ -188,7 +188,7 @@ - (void)sortResults NSUInteger runningSum = 0; NSMutableArray *samePriorityRecords = [NSMutableArray arrayWithCapacity:srvResultsCount]; - XMPPSRVRecord *srvRecord = [results objectAtIndex:0]; + XMPPSRVRecord *srvRecord = results[0]; NSUInteger initialPriority = srvRecord.priority; NSUInteger index = 0; @@ -216,7 +216,7 @@ - (void)sortResults if (++index < srvResultsCount) { - srvRecord = [results objectAtIndex:index]; + srvRecord = results[index]; } else { @@ -540,7 +540,7 @@ - (void)startWithSRVName:(NSString *)aSRVName timeout:(NSTimeInterval)aTimeout dispatch_source_set_event_handler(timeoutTimer, ^{ @autoreleasepool { NSString *errMsg = @"Operation timed out"; - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + NSDictionary *userInfo = @{NSLocalizedDescriptionKey : errMsg}; NSError *err = [NSError errorWithDomain:XMPPSRVResolverErrorDomain code:0 userInfo:userInfo]; diff --git a/Xcode/iPhoneXMPP/Classes/RootViewController.m b/Xcode/iPhoneXMPP/Classes/RootViewController.m index 215582f3bb..4d447cbff0 100644 --- a/Xcode/iPhoneXMPP/Classes/RootViewController.m +++ b/Xcode/iPhoneXMPP/Classes/RootViewController.m @@ -76,7 +76,7 @@ - (NSFetchedResultsController *)fetchedResultsController NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:@"sectionNum" ascending:YES]; NSSortDescriptor *sd2 = [[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES]; - NSArray *sortDescriptors = [NSArray arrayWithObjects:sd1, sd2, nil]; + NSArray *sortDescriptors = @[sd1, sd2]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:entity]; @@ -145,7 +145,7 @@ - (NSString *)tableView:(UITableView *)sender titleForHeaderInSection:(NSInteger if (sectionIndex < [sections count]) { - id sectionInfo = [sections objectAtIndex:sectionIndex]; + id sectionInfo = sections[sectionIndex]; int section = [sectionInfo.name intValue]; switch (section) @@ -165,7 +165,7 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger if (sectionIndex < [sections count]) { - id sectionInfo = [sections objectAtIndex:sectionIndex]; + id sectionInfo = sections[sectionIndex]; return sectionInfo.numberOfObjects; } diff --git a/Xcode/iPhoneXMPP/Classes/iPhoneXMPPAppDelegate.m b/Xcode/iPhoneXMPP/Classes/iPhoneXMPPAppDelegate.m index c7c7f7db5a..8508aaeddf 100644 --- a/Xcode/iPhoneXMPP/Classes/iPhoneXMPPAppDelegate.m +++ b/Xcode/iPhoneXMPP/Classes/iPhoneXMPPAppDelegate.m @@ -395,12 +395,12 @@ - (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDiction NSString *expectedCertName = [xmppStream.myJID domain]; if (expectedCertName) { - [settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName]; + settings[(NSString *) kCFStreamSSLPeerName] = expectedCertName; } if (customCertEvaluation) { - [settings setObject:@(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust]; + settings[GCDAsyncSocketManuallyEvaluateTrust] = @(YES); } } From c978ad077a52e51fd9b0c4aaa99488fbd5514466 Mon Sep 17 00:00:00 2001 From: vitalyster Date: Sat, 21 Feb 2015 17:39:29 +0300 Subject: [PATCH 013/356] Fix XEP-0092 namespace --- Extensions/XEP-0092/XMPPSoftwareVersion.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extensions/XEP-0092/XMPPSoftwareVersion.m b/Extensions/XEP-0092/XMPPSoftwareVersion.m index 20dcda4317..0c41e0b9e9 100644 --- a/Extensions/XEP-0092/XMPPSoftwareVersion.m +++ b/Extensions/XEP-0092/XMPPSoftwareVersion.m @@ -6,7 +6,7 @@ #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). #endif -#define XMLNS_URN_XMPP_VERSION @"urn:xmpp:jabber:iq:version" +#define XMLNS_URN_XMPP_VERSION @"jabber:iq:version" @implementation XMPPSoftwareVersion From 15f2ec8c7ff5fc5e3d5b449ecb45450265538599 Mon Sep 17 00:00:00 2001 From: Arman Yessenamanov Date: Thu, 26 Feb 2015 20:54:07 +0600 Subject: [PATCH 014/356] Notify delegate about acks that were received during stream resumption. --- Extensions/XEP-0198/XMPPStreamManagement.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Extensions/XEP-0198/XMPPStreamManagement.m b/Extensions/XEP-0198/XMPPStreamManagement.m index a4ef0b382c..8e49094350 100644 --- a/Extensions/XEP-0198/XMPPStreamManagement.m +++ b/Extensions/XEP-0198/XMPPStreamManagement.m @@ -588,6 +588,10 @@ - (void)processResumed:(NSXMLElement *)resumed lastHandledByServer:lastHandledByServer pendingOutgoingStanzas:nil forStream:xmppStream]; + + // Notify delegate + + [multicastDelegate xmppStreamManagement:self didReceiveAckForStanzaIds:stanzaIds]; }}; if (dispatch_get_specific(moduleQueueTag)) From 2f80eef031fc48c2a65cb3c7fe2cab6e31322c05 Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Fri, 20 Mar 2015 15:09:33 +0000 Subject: [PATCH 015/356] Fixes #511 --- Extensions/XEP-0054/XMPPvCardTemp.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/Extensions/XEP-0054/XMPPvCardTemp.m b/Extensions/XEP-0054/XMPPvCardTemp.m index a4df1f9597..db593f5617 100644 --- a/Extensions/XEP-0054/XMPPvCardTemp.m +++ b/Extensions/XEP-0054/XMPPvCardTemp.m @@ -21,8 +21,6 @@ #if DEBUG static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; -#else - static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; #endif NSString *const kXMPPNSvCardTemp = @"vcard-temp"; From b8d724c77fbb07cd08e5ebaa45532408e6eb7e03 Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Mon, 23 Mar 2015 21:54:39 +0000 Subject: [PATCH 016/356] Fixes #511 --- Extensions/XEP-0054/XMPPvCardTempAdr.m | 2 -- Extensions/XEP-0054/XMPPvCardTempEmail.m | 2 -- Extensions/XEP-0054/XMPPvCardTempLabel.m | 2 -- Extensions/XEP-0054/XMPPvCardTempTel.m | 2 -- 4 files changed, 8 deletions(-) diff --git a/Extensions/XEP-0054/XMPPvCardTempAdr.m b/Extensions/XEP-0054/XMPPvCardTempAdr.m index 3bc4f34703..24eb38f3b8 100644 --- a/Extensions/XEP-0054/XMPPvCardTempAdr.m +++ b/Extensions/XEP-0054/XMPPvCardTempAdr.m @@ -19,8 +19,6 @@ #if DEBUG static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; -#else - static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; #endif diff --git a/Extensions/XEP-0054/XMPPvCardTempEmail.m b/Extensions/XEP-0054/XMPPvCardTempEmail.m index 609948bd4c..f3dd91edbb 100644 --- a/Extensions/XEP-0054/XMPPvCardTempEmail.m +++ b/Extensions/XEP-0054/XMPPvCardTempEmail.m @@ -19,8 +19,6 @@ #if DEBUG static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; -#else - static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; #endif diff --git a/Extensions/XEP-0054/XMPPvCardTempLabel.m b/Extensions/XEP-0054/XMPPvCardTempLabel.m index 26f987714f..2e4875c60b 100644 --- a/Extensions/XEP-0054/XMPPvCardTempLabel.m +++ b/Extensions/XEP-0054/XMPPvCardTempLabel.m @@ -19,8 +19,6 @@ #if DEBUG static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; -#else - static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; #endif diff --git a/Extensions/XEP-0054/XMPPvCardTempTel.m b/Extensions/XEP-0054/XMPPvCardTempTel.m index 1d883a8436..fa5a94360c 100644 --- a/Extensions/XEP-0054/XMPPvCardTempTel.m +++ b/Extensions/XEP-0054/XMPPvCardTempTel.m @@ -19,8 +19,6 @@ #if DEBUG static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; -#else - static const int xmppLogLevel = XMPP_LOG_LEVEL_ERROR; #endif From a68f74c3f73aae828b2e803aecb55e272a5aae3d Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Sat, 18 Apr 2015 11:16:45 -0400 Subject: [PATCH 017/356] Update out-of-date ref to MulticastDelegateTest --- .../Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Xcode/Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata b/Xcode/Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata index eb12c3490a..6febaa1704 100644 --- a/Xcode/Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata +++ b/Xcode/Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata @@ -23,7 +23,10 @@ location = "group:FacebookTest/FacebookTest.xcodeproj"> + location = "group:MulticastDelegateTest/Desktop/MulticastDelegateTest.xcodeproj"> + + From f4a7b7f61384eb81c28693409be06865829d27e3 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Sat, 18 Apr 2015 11:19:23 -0400 Subject: [PATCH 018/356] Add some missing test projects --- .../XMPPTesting.xcworkspace/contents.xcworkspacedata | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Xcode/Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata b/Xcode/Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata index 6febaa1704..a749c0b46c 100644 --- a/Xcode/Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata +++ b/Xcode/Testing/XMPPTesting.xcworkspace/contents.xcworkspacedata @@ -43,6 +43,9 @@ + + @@ -52,6 +55,12 @@ + + + + From d3aa5d348c083a63a1b8fd9076318d67c5dd2bcf Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Sat, 18 Apr 2015 12:38:44 -0400 Subject: [PATCH 019/356] GCDAsyncSocket: Upgrade to 7.4.1 --- Vendor/CocoaAsyncSocket/GCDAsyncSocket.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h b/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h index a0d1c52bca..374bcdd89d 100644 --- a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h +++ b/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h @@ -90,7 +90,11 @@ typedef enum GCDAsyncSocketError GCDAsyncSocketError; #pragma mark Configuration @property (atomic, weak, readwrite) id delegate; +#if OS_OBJECT_USE_OBJC @property (atomic, strong, readwrite) dispatch_queue_t delegateQueue; +#else +@property (atomic, assign, readwrite) dispatch_queue_t delegateQueue; +#endif - (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr; - (void)setDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; From 78c8c59b262e45da8f83b4c8db6aaa3716f9adcf Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Sat, 18 Apr 2015 12:38:51 -0400 Subject: [PATCH 020/356] Get tests passing in Xcode 6.3 --- .../AutoPingTest.xcodeproj/project.pbxproj | 22 +- .../AutoPingTest/AutoPingTestAppDelegate.m | 2 +- .../AutoPingTest.xcodeproj/project.pbxproj | 22 +- .../AutoPingTest/AutoPingTestAppDelegate.m | 2 +- .../AutoTimeTest.xcodeproj/project.pbxproj | 44 ++- .../AutoTimeTest/AutoTimeTestAppDelegate.m | 2 +- .../AutoTimeTest.xcodeproj/project.pbxproj | 46 ++- .../AutoTimeTest/AutoTimeTestAppDelegate.m | 2 +- .../FacebookTest.xcodeproj/project.pbxproj | 56 ++-- .../MUCTesting.xcodeproj/project.pbxproj | 30 +- .../MUCTesting/MUCTestingAppDelegate.m | 2 +- .../project.pbxproj | 24 +- .../project.pbxproj | 18 +- .../project.pbxproj | 18 +- .../TestIDTracker.xcodeproj/project.pbxproj | 317 ++++++++++++++++++ .../Mac/TestXEP82.xcodeproj/project.pbxproj | 6 +- 16 files changed, 522 insertions(+), 91 deletions(-) diff --git a/Xcode/Testing/AutoPingTest/Desktop/AutoPingTest.xcodeproj/project.pbxproj b/Xcode/Testing/AutoPingTest/Desktop/AutoPingTest.xcodeproj/project.pbxproj index 369dbf5719..ecc97e927f 100644 --- a/Xcode/Testing/AutoPingTest/Desktop/AutoPingTest.xcodeproj/project.pbxproj +++ b/Xcode/Testing/AutoPingTest/Desktop/AutoPingTest.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 56F8388914C79AEB00AF62B3 /* XMPPAutoTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 56F8388614C79AEB00AF62B3 /* XMPPAutoTime.m */; }; 56F8388A14C79AEB00AF62B3 /* XMPPTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 56F8388814C79AEB00AF62B3 /* XMPPTime.m */; }; + 9E8E5BBD1AE2ADD600BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E8E5BBC1AE2ADD600BE3E34 /* XMPPSCRAMSHA1Authentication.m */; }; DC17CD3E1355ED29007A32CC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC17CD3D1355ED29007A32CC /* Cocoa.framework */; }; DC17CD481355ED29007A32CC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC17CD461355ED29007A32CC /* InfoPlist.strings */; }; DC17CD4B1355ED29007A32CC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DC17CD4A1355ED29007A32CC /* main.m */; }; @@ -60,6 +61,9 @@ 56F8388614C79AEB00AF62B3 /* XMPPAutoTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPAutoTime.m; sourceTree = ""; }; 56F8388714C79AEB00AF62B3 /* XMPPTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPTime.h; sourceTree = ""; }; 56F8388814C79AEB00AF62B3 /* XMPPTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPTime.m; sourceTree = ""; }; + 9E8E5BB91AE2ADA900BE3E34 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9E8E5BBB1AE2ADD600BE3E34 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9E8E5BBC1AE2ADD600BE3E34 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; DC17CD391355ED29007A32CC /* AutoPingTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoPingTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; DC17CD3D1355ED29007A32CC /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; DC17CD401355ED29007A32CC /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; @@ -114,7 +118,7 @@ DC597EB114101FBF0050774C /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPParser.m; sourceTree = ""; }; DC597EB214101FBF0050774C /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPresence.h; sourceTree = ""; }; DC597EB314101FBF0050774C /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPresence.m; sourceTree = ""; }; - DC597EB414101FBF0050774C /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; }; + DC597EB414101FBF0050774C /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DC597EB514101FBF0050774C /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStream.m; sourceTree = ""; }; DC597F0A14101FBF0050774C /* NSDate+XMPPDateTimeProfiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+XMPPDateTimeProfiles.h"; sourceTree = ""; }; DC597F0B14101FBF0050774C /* NSDate+XMPPDateTimeProfiles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+XMPPDateTimeProfiles.m"; sourceTree = ""; }; @@ -181,6 +185,15 @@ path = "XEP-0202"; sourceTree = ""; }; + 9E8E5BBA1AE2ADD600BE3E34 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9E8E5BBB1AE2ADD600BE3E34 /* XMPPSCRAMSHA1Authentication.h */, + 9E8E5BBC1AE2ADD600BE3E34 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC17CD2E1355ED29007A32CC = { isa = PBXGroup; children = ( @@ -267,7 +280,9 @@ DC30E7D3153E0A88001B9E6D /* Deprecated-Plain */, DC30E7D6153E0A88001B9E6D /* Digest-MD5 */, DC30E7D9153E0A88001B9E6D /* Plain */, + 9E8E5BBA1AE2ADD600BE3E34 /* SCRAM-SHA-1 */, DC30E7DC153E0A88001B9E6D /* X-Facebook-Platform */, + 9E8E5BB91AE2ADA900BE3E34 /* XMPPCustomBinding.h */, DC30E7DF153E0A88001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -562,6 +577,7 @@ DC597F9E14101FBF0050774C /* DDLog.m in Sources */, DC597F9F14101FBF0050774C /* DDTTYLogger.m in Sources */, 56F8388914C79AEB00AF62B3 /* XMPPAutoTime.m in Sources */, + 9E8E5BBD1AE2ADD600BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */, 56F8388A14C79AEB00AF62B3 /* XMPPTime.m in Sources */, DC30E7E0153E0A88001B9E6D /* XMPPAnonymousAuthentication.m in Sources */, DC30E7E1153E0A88001B9E6D /* XMPPDeprecatedDigestAuthentication.m in Sources */, @@ -615,7 +631,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; @@ -631,7 +647,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.10; SDKROOT = macosx; }; name = Release; diff --git a/Xcode/Testing/AutoPingTest/Desktop/AutoPingTest/AutoPingTestAppDelegate.m b/Xcode/Testing/AutoPingTest/Desktop/AutoPingTest/AutoPingTestAppDelegate.m index eb6a827c87..55fe85bfb7 100644 --- a/Xcode/Testing/AutoPingTest/Desktop/AutoPingTest/AutoPingTestAppDelegate.m +++ b/Xcode/Testing/AutoPingTest/Desktop/AutoPingTest/AutoPingTestAppDelegate.m @@ -44,7 +44,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification NSError *error = nil; - if (![xmppStream connect:&error]) + if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]) { DDLogError(@"%@: Error connecting: %@", [self class], error); } diff --git a/Xcode/Testing/AutoPingTest/Mobile/AutoPingTest.xcodeproj/project.pbxproj b/Xcode/Testing/AutoPingTest/Mobile/AutoPingTest.xcodeproj/project.pbxproj index c70d4492ca..19090f62fe 100644 --- a/Xcode/Testing/AutoPingTest/Mobile/AutoPingTest.xcodeproj/project.pbxproj +++ b/Xcode/Testing/AutoPingTest/Mobile/AutoPingTest.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 9E8E5BC81AE2AF9B00BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E8E5BC71AE2AF9B00BE3E34 /* XMPPSCRAMSHA1Authentication.m */; }; DC30E328153DFD3E001B9E6D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC30E327153DFD3E001B9E6D /* Security.framework */; }; DC30E7FB153E0AA8001B9E6D /* XMPPAnonymousAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E7EA153E0AA8001B9E6D /* XMPPAnonymousAuthentication.m */; }; DC30E7FC153E0AA8001B9E6D /* XMPPDeprecatedDigestAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E7ED153E0AA8001B9E6D /* XMPPDeprecatedDigestAuthentication.m */; }; @@ -61,6 +62,9 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 9E8E5BC41AE2AF9B00BE3E34 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9E8E5BC61AE2AF9B00BE3E34 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9E8E5BC71AE2AF9B00BE3E34 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; DC30E327153DFD3E001B9E6D /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; DC30E7E9153E0AA8001B9E6D /* XMPPAnonymousAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPAnonymousAuthentication.h; sourceTree = ""; }; DC30E7EA153E0AA8001B9E6D /* XMPPAnonymousAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPAnonymousAuthentication.m; sourceTree = ""; }; @@ -115,7 +119,7 @@ DC598113141033210050774C /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPParser.m; sourceTree = ""; }; DC598114141033210050774C /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPresence.h; sourceTree = ""; }; DC598115141033210050774C /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPresence.m; sourceTree = ""; }; - DC598116141033210050774C /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; }; + DC598116141033210050774C /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DC598117141033210050774C /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStream.m; sourceTree = ""; }; DC59816C141033210050774C /* NSDate+XMPPDateTimeProfiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+XMPPDateTimeProfiles.h"; sourceTree = ""; }; DC59816D141033210050774C /* NSDate+XMPPDateTimeProfiles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+XMPPDateTimeProfiles.m"; sourceTree = ""; }; @@ -184,6 +188,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9E8E5BC51AE2AF9B00BE3E34 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9E8E5BC61AE2AF9B00BE3E34 /* XMPPSCRAMSHA1Authentication.h */, + 9E8E5BC71AE2AF9B00BE3E34 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC30E7E7153E0AA8001B9E6D /* Authentication */ = { isa = PBXGroup; children = ( @@ -192,7 +205,9 @@ DC30E7EE153E0AA8001B9E6D /* Deprecated-Plain */, DC30E7F1153E0AA8001B9E6D /* Digest-MD5 */, DC30E7F4153E0AA8001B9E6D /* Plain */, + 9E8E5BC51AE2AF9B00BE3E34 /* SCRAM-SHA-1 */, DC30E7F7153E0AA8001B9E6D /* X-Facebook-Platform */, + 9E8E5BC41AE2AF9B00BE3E34 /* XMPPCustomBinding.h */, DC30E7FA153E0AA8001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -578,6 +593,7 @@ DC5981E8141033210050774C /* NSDate+XMPPDateTimeProfiles.m in Sources */, DC5981E9141033210050774C /* XMPPDateTimeProfiles.m in Sources */, DC5981F1141033210050774C /* XMPPAutoPing.m in Sources */, + 9E8E5BC81AE2AF9B00BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */, DC5981F2141033210050774C /* XMPPPing.m in Sources */, DC5981F6141033210050774C /* DDList.m in Sources */, DC5981F7141033210050774C /* GCDMulticastDelegate.m in Sources */, @@ -654,7 +670,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; SDKROOT = iphoneos; }; name = Debug; @@ -672,7 +688,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; diff --git a/Xcode/Testing/AutoPingTest/Mobile/AutoPingTest/AutoPingTestAppDelegate.m b/Xcode/Testing/AutoPingTest/Mobile/AutoPingTest/AutoPingTestAppDelegate.m index 2fcd2527da..1cfd3ca029 100644 --- a/Xcode/Testing/AutoPingTest/Mobile/AutoPingTest/AutoPingTestAppDelegate.m +++ b/Xcode/Testing/AutoPingTest/Mobile/AutoPingTest/AutoPingTestAppDelegate.m @@ -38,7 +38,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( NSError *error = nil; - if (![xmppStream connect:&error]) + if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]) { DDLogError(@"%@: Error connecting: %@", [self class], error); } diff --git a/Xcode/Testing/AutoTimeTest/Desktop/AutoTimeTest.xcodeproj/project.pbxproj b/Xcode/Testing/AutoTimeTest/Desktop/AutoTimeTest.xcodeproj/project.pbxproj index 778a895f98..9f8747fb70 100644 --- a/Xcode/Testing/AutoTimeTest/Desktop/AutoTimeTest.xcodeproj/project.pbxproj +++ b/Xcode/Testing/AutoTimeTest/Desktop/AutoTimeTest.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 9E8E5BD21AE2B33300BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E8E5BD11AE2B33300BE3E34 /* XMPPSCRAMSHA1Authentication.m */; }; DC30E513153DFFAD001B9E6D /* NSData+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E464153DFFAD001B9E6D /* NSData+XMPP.m */; }; DC30E514153DFFAD001B9E6D /* NSNumber+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E466153DFFAD001B9E6D /* NSNumber+XMPP.m */; }; DC30E515153DFFAD001B9E6D /* NSXMLElement+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E468153DFFAD001B9E6D /* NSXMLElement+XMPP.m */; }; @@ -30,10 +31,9 @@ DC30E529153DFFAD001B9E6D /* DDFileLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E49A153DFFAD001B9E6D /* DDFileLogger.m */; }; DC30E52A153DFFAD001B9E6D /* DDLog.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E49C153DFFAD001B9E6D /* DDLog.m */; }; DC30E52B153DFFAD001B9E6D /* DDTTYLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E49E153DFFAD001B9E6D /* DDTTYLogger.m */; }; - DC30E52C153DFFAD001B9E6D /* ContextFilterLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E4A1153DFFAD001B9E6D /* ContextFilterLogFormatter.m */; }; - DC30E52D153DFFAD001B9E6D /* DispatchQueueLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E4A3153DFFAD001B9E6D /* DispatchQueueLogFormatter.m */; }; + DC30E52C153DFFAD001B9E6D /* DDContextFilterLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E4A1153DFFAD001B9E6D /* DDContextFilterLogFormatter.m */; }; + DC30E52D153DFFAD001B9E6D /* DDDispatchQueueLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E4A3153DFFAD001B9E6D /* DDDispatchQueueLogFormatter.m */; }; DC30E52E153DFFAD001B9E6D /* README.txt in Resources */ = {isa = PBXBuildFile; fileRef = DC30E4A4153DFFAD001B9E6D /* README.txt */; }; - DC30E558153DFFAE001B9E6D /* libidn-1.24.tar.gz in Resources */ = {isa = PBXBuildFile; fileRef = DC30E505153DFFAD001B9E6D /* libidn-1.24.tar.gz */; }; DC30E559153DFFAE001B9E6D /* libidn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC30E506153DFFAD001B9E6D /* libidn.a */; }; DC30E56F153DFFE4001B9E6D /* NSDate+XMPPDateTimeProfiles.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E567153DFFE4001B9E6D /* NSDate+XMPPDateTimeProfiles.m */; }; DC30E570153DFFE4001B9E6D /* XMPPDateTimeProfiles.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E569153DFFE4001B9E6D /* XMPPDateTimeProfiles.m */; }; @@ -61,6 +61,9 @@ 56F8342A14C76FA100AF62B3 /* XMPPAutoPing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPAutoPing.m; sourceTree = ""; }; 56F8342B14C76FA100AF62B3 /* XMPPPing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPing.h; sourceTree = ""; }; 56F8342C14C76FA100AF62B3 /* XMPPPing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPing.m; sourceTree = ""; }; + 9E8E5BCE1AE2B33300BE3E34 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9E8E5BD01AE2B33300BE3E34 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9E8E5BD11AE2B33300BE3E34 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; DC30E463153DFFAD001B9E6D /* NSData+XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+XMPP.h"; sourceTree = ""; }; DC30E464153DFFAD001B9E6D /* NSData+XMPP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+XMPP.m"; sourceTree = ""; }; DC30E465153DFFAD001B9E6D /* NSNumber+XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNumber+XMPP.h"; sourceTree = ""; }; @@ -84,7 +87,7 @@ DC30E479153DFFAD001B9E6D /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPParser.m; sourceTree = ""; }; DC30E47A153DFFAD001B9E6D /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPresence.h; sourceTree = ""; }; DC30E47B153DFFAD001B9E6D /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPresence.m; sourceTree = ""; }; - DC30E47C153DFFAD001B9E6D /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; }; + DC30E47C153DFFAD001B9E6D /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DC30E47D153DFFAD001B9E6D /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStream.m; sourceTree = ""; }; DC30E47F153DFFAD001B9E6D /* DDList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDList.h; sourceTree = ""; }; DC30E480153DFFAD001B9E6D /* DDList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDList.m; sourceTree = ""; }; @@ -110,10 +113,10 @@ DC30E49C153DFFAD001B9E6D /* DDLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDLog.m; sourceTree = ""; }; DC30E49D153DFFAD001B9E6D /* DDTTYLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDTTYLogger.h; sourceTree = ""; }; DC30E49E153DFFAD001B9E6D /* DDTTYLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDTTYLogger.m; sourceTree = ""; }; - DC30E4A0153DFFAD001B9E6D /* ContextFilterLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextFilterLogFormatter.h; sourceTree = ""; }; - DC30E4A1153DFFAD001B9E6D /* ContextFilterLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContextFilterLogFormatter.m; sourceTree = ""; }; - DC30E4A2153DFFAD001B9E6D /* DispatchQueueLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchQueueLogFormatter.h; sourceTree = ""; }; - DC30E4A3153DFFAD001B9E6D /* DispatchQueueLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DispatchQueueLogFormatter.m; sourceTree = ""; }; + DC30E4A0153DFFAD001B9E6D /* DDContextFilterLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDContextFilterLogFormatter.h; sourceTree = ""; }; + DC30E4A1153DFFAD001B9E6D /* DDContextFilterLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDContextFilterLogFormatter.m; sourceTree = ""; }; + DC30E4A2153DFFAD001B9E6D /* DDDispatchQueueLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDDispatchQueueLogFormatter.h; sourceTree = ""; }; + DC30E4A3153DFFAD001B9E6D /* DDDispatchQueueLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDDispatchQueueLogFormatter.m; sourceTree = ""; }; DC30E4A4153DFFAD001B9E6D /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; DC30E504153DFFAD001B9E6D /* idn-int.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "idn-int.h"; sourceTree = ""; }; DC30E505153DFFAD001B9E6D /* libidn-1.24.tar.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = "libidn-1.24.tar.gz"; sourceTree = ""; }; @@ -184,6 +187,15 @@ path = "../../../../../Extensions/XEP-0199"; sourceTree = ""; }; + 9E8E5BCF1AE2B33300BE3E34 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9E8E5BD01AE2B33300BE3E34 /* XMPPSCRAMSHA1Authentication.h */, + 9E8E5BD11AE2B33300BE3E34 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC30E461153DFF96001B9E6D /* XMPP */ = { isa = PBXGroup; children = ( @@ -300,10 +312,10 @@ DC30E49F153DFFAD001B9E6D /* Extensions */ = { isa = PBXGroup; children = ( - DC30E4A0153DFFAD001B9E6D /* ContextFilterLogFormatter.h */, - DC30E4A1153DFFAD001B9E6D /* ContextFilterLogFormatter.m */, - DC30E4A2153DFFAD001B9E6D /* DispatchQueueLogFormatter.h */, - DC30E4A3153DFFAD001B9E6D /* DispatchQueueLogFormatter.m */, + DC30E4A0153DFFAD001B9E6D /* DDContextFilterLogFormatter.h */, + DC30E4A1153DFFAD001B9E6D /* DDContextFilterLogFormatter.m */, + DC30E4A2153DFFAD001B9E6D /* DDDispatchQueueLogFormatter.h */, + DC30E4A3153DFFAD001B9E6D /* DDDispatchQueueLogFormatter.m */, DC30E4A4153DFFAD001B9E6D /* README.txt */, ); path = Extensions; @@ -361,7 +373,9 @@ DC30E809153E0AD1001B9E6D /* Deprecated-Plain */, DC30E80C153E0AD1001B9E6D /* Digest-MD5 */, DC30E80F153E0AD1001B9E6D /* Plain */, + 9E8E5BCF1AE2B33300BE3E34 /* SCRAM-SHA-1 */, DC30E812153E0AD1001B9E6D /* X-Facebook-Platform */, + 9E8E5BCE1AE2B33300BE3E34 /* XMPPCustomBinding.h */, DC30E815153E0AD1001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -537,7 +551,6 @@ DC41733713F1D34800ED8D43 /* Credits.rtf in Resources */, DC41733D13F1D34900ED8D43 /* MainMenu.xib in Resources */, DC30E52E153DFFAD001B9E6D /* README.txt in Resources */, - DC30E558153DFFAE001B9E6D /* libidn-1.24.tar.gz in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -573,11 +586,12 @@ DC30E529153DFFAD001B9E6D /* DDFileLogger.m in Sources */, DC30E52A153DFFAD001B9E6D /* DDLog.m in Sources */, DC30E52B153DFFAD001B9E6D /* DDTTYLogger.m in Sources */, - DC30E52C153DFFAD001B9E6D /* ContextFilterLogFormatter.m in Sources */, - DC30E52D153DFFAD001B9E6D /* DispatchQueueLogFormatter.m in Sources */, + DC30E52C153DFFAD001B9E6D /* DDContextFilterLogFormatter.m in Sources */, + DC30E52D153DFFAD001B9E6D /* DDDispatchQueueLogFormatter.m in Sources */, DC30E56F153DFFE4001B9E6D /* NSDate+XMPPDateTimeProfiles.m in Sources */, DC30E570153DFFE4001B9E6D /* XMPPDateTimeProfiles.m in Sources */, DC30E571153DFFE4001B9E6D /* XMPPAutoTime.m in Sources */, + 9E8E5BD21AE2B33300BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */, DC30E572153DFFE4001B9E6D /* XMPPTime.m in Sources */, DC30E816153E0AD1001B9E6D /* XMPPAnonymousAuthentication.m in Sources */, DC30E817153E0AD1001B9E6D /* XMPPDeprecatedDigestAuthentication.m in Sources */, diff --git a/Xcode/Testing/AutoTimeTest/Desktop/AutoTimeTest/AutoTimeTestAppDelegate.m b/Xcode/Testing/AutoTimeTest/Desktop/AutoTimeTest/AutoTimeTestAppDelegate.m index 7c64b812db..513e2e1ef3 100644 --- a/Xcode/Testing/AutoTimeTest/Desktop/AutoTimeTest/AutoTimeTestAppDelegate.m +++ b/Xcode/Testing/AutoTimeTest/Desktop/AutoTimeTest/AutoTimeTestAppDelegate.m @@ -35,7 +35,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification NSError *error = nil; - if (![xmppStream connect:&error]) + if (![xmppStream connectWithTimeout: XMPPStreamTimeoutNone error:&error]) { DDLogError(@"%@: Error connecting: %@", [self class], error); } diff --git a/Xcode/Testing/AutoTimeTest/Mobile/AutoTimeTest.xcodeproj/project.pbxproj b/Xcode/Testing/AutoTimeTest/Mobile/AutoTimeTest.xcodeproj/project.pbxproj index bb1d354a83..0ef8911d9d 100644 --- a/Xcode/Testing/AutoTimeTest/Mobile/AutoTimeTest.xcodeproj/project.pbxproj +++ b/Xcode/Testing/AutoTimeTest/Mobile/AutoTimeTest.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 56F8345214C7733800AF62B3 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 56F8345114C7733800AF62B3 /* libiconv.dylib */; }; + 9E8E5BCD1AE2B1C800BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E8E5BCC1AE2B1C800BE3E34 /* XMPPSCRAMSHA1Authentication.m */; }; DC30E332153DFDF5001B9E6D /* AutoTimeTestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E32D153DFDF5001B9E6D /* AutoTimeTestAppDelegate.m */; }; DC30E333153DFDF5001B9E6D /* AutoTimeTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E32F153DFDF5001B9E6D /* AutoTimeTestViewController.m */; }; DC30E334153DFDF5001B9E6D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E330153DFDF5001B9E6D /* main.m */; }; @@ -37,8 +38,8 @@ DC30E408153DFE52001B9E6D /* DDFileLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E379153DFE52001B9E6D /* DDFileLogger.m */; }; DC30E409153DFE52001B9E6D /* DDLog.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E37B153DFE52001B9E6D /* DDLog.m */; }; DC30E40A153DFE52001B9E6D /* DDTTYLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E37D153DFE52001B9E6D /* DDTTYLogger.m */; }; - DC30E40B153DFE52001B9E6D /* ContextFilterLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E380153DFE52001B9E6D /* ContextFilterLogFormatter.m */; }; - DC30E40C153DFE52001B9E6D /* DispatchQueueLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E382153DFE52001B9E6D /* DispatchQueueLogFormatter.m */; }; + DC30E40B153DFE52001B9E6D /* DDContextFilterLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E380153DFE52001B9E6D /* DDContextFilterLogFormatter.m */; }; + DC30E40C153DFE52001B9E6D /* DDDispatchQueueLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E382153DFE52001B9E6D /* DDDispatchQueueLogFormatter.m */; }; DC30E433153DFE52001B9E6D /* NSString+DDXML.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E3D8153DFE52001B9E6D /* NSString+DDXML.m */; }; DC30E434153DFE52001B9E6D /* DDXMLDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E3DB153DFE52001B9E6D /* DDXMLDocument.m */; }; DC30E435153DFE52001B9E6D /* DDXMLElement.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E3DD153DFE52001B9E6D /* DDXMLElement.m */; }; @@ -65,6 +66,9 @@ /* Begin PBXFileReference section */ 56F8345114C7733800AF62B3 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; + 9E8E5BC91AE2B1C800BE3E34 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9E8E5BCB1AE2B1C800BE3E34 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9E8E5BCC1AE2B1C800BE3E34 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; DC30E32A153DFDF5001B9E6D /* AutoTimeTest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "AutoTimeTest-Info.plist"; sourceTree = ""; }; DC30E32B153DFDF5001B9E6D /* AutoTimeTest-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AutoTimeTest-Prefix.pch"; sourceTree = ""; }; DC30E32C153DFDF5001B9E6D /* AutoTimeTestAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoTimeTestAppDelegate.h; sourceTree = ""; }; @@ -98,7 +102,7 @@ DC30E358153DFE52001B9E6D /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPParser.m; sourceTree = ""; }; DC30E359153DFE52001B9E6D /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPresence.h; sourceTree = ""; }; DC30E35A153DFE52001B9E6D /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPresence.m; sourceTree = ""; }; - DC30E35B153DFE52001B9E6D /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; }; + DC30E35B153DFE52001B9E6D /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DC30E35C153DFE52001B9E6D /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStream.m; sourceTree = ""; }; DC30E35E153DFE52001B9E6D /* DDList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDList.h; sourceTree = ""; }; DC30E35F153DFE52001B9E6D /* DDList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDList.m; sourceTree = ""; }; @@ -124,10 +128,10 @@ DC30E37B153DFE52001B9E6D /* DDLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDLog.m; sourceTree = ""; }; DC30E37C153DFE52001B9E6D /* DDTTYLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDTTYLogger.h; sourceTree = ""; }; DC30E37D153DFE52001B9E6D /* DDTTYLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDTTYLogger.m; sourceTree = ""; }; - DC30E37F153DFE52001B9E6D /* ContextFilterLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextFilterLogFormatter.h; sourceTree = ""; }; - DC30E380153DFE52001B9E6D /* ContextFilterLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContextFilterLogFormatter.m; sourceTree = ""; }; - DC30E381153DFE52001B9E6D /* DispatchQueueLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchQueueLogFormatter.h; sourceTree = ""; }; - DC30E382153DFE52001B9E6D /* DispatchQueueLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DispatchQueueLogFormatter.m; sourceTree = ""; }; + DC30E37F153DFE52001B9E6D /* DDContextFilterLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDContextFilterLogFormatter.h; sourceTree = ""; }; + DC30E380153DFE52001B9E6D /* DDContextFilterLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDContextFilterLogFormatter.m; sourceTree = ""; }; + DC30E381153DFE52001B9E6D /* DDDispatchQueueLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDDispatchQueueLogFormatter.h; sourceTree = ""; }; + DC30E382153DFE52001B9E6D /* DDDispatchQueueLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDDispatchQueueLogFormatter.m; sourceTree = ""; }; DC30E383153DFE52001B9E6D /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; DC30E3D7153DFE52001B9E6D /* NSString+DDXML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+DDXML.h"; sourceTree = ""; }; DC30E3D8153DFE52001B9E6D /* NSString+DDXML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+DDXML.m"; sourceTree = ""; }; @@ -194,6 +198,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9E8E5BCA1AE2B1C800BE3E34 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9E8E5BCB1AE2B1C800BE3E34 /* XMPPSCRAMSHA1Authentication.h */, + 9E8E5BCC1AE2B1C800BE3E34 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC30E335153DFE09001B9E6D /* Supporting Files */ = { isa = PBXGroup; children = ( @@ -308,10 +321,10 @@ DC30E37E153DFE52001B9E6D /* Extensions */ = { isa = PBXGroup; children = ( - DC30E37F153DFE52001B9E6D /* ContextFilterLogFormatter.h */, - DC30E380153DFE52001B9E6D /* ContextFilterLogFormatter.m */, - DC30E381153DFE52001B9E6D /* DispatchQueueLogFormatter.h */, - DC30E382153DFE52001B9E6D /* DispatchQueueLogFormatter.m */, + DC30E37F153DFE52001B9E6D /* DDContextFilterLogFormatter.h */, + DC30E380153DFE52001B9E6D /* DDContextFilterLogFormatter.m */, + DC30E381153DFE52001B9E6D /* DDDispatchQueueLogFormatter.h */, + DC30E382153DFE52001B9E6D /* DDDispatchQueueLogFormatter.m */, DC30E383153DFE52001B9E6D /* README.txt */, ); path = Extensions; @@ -415,7 +428,9 @@ DC30E824153E0AF0001B9E6D /* Deprecated-Plain */, DC30E827153E0AF0001B9E6D /* Digest-MD5 */, DC30E82A153E0AF0001B9E6D /* Plain */, + 9E8E5BCA1AE2B1C800BE3E34 /* SCRAM-SHA-1 */, DC30E82D153E0AF0001B9E6D /* X-Facebook-Platform */, + 9E8E5BC91AE2B1C800BE3E34 /* XMPPCustomBinding.h */, DC30E830153E0AF0001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -603,6 +618,7 @@ DC30E3FD153DFE52001B9E6D /* DDList.m in Sources */, DC30E3FE153DFE52001B9E6D /* GCDMulticastDelegate.m in Sources */, DC30E3FF153DFE52001B9E6D /* XMPPStringPrep.m in Sources */, + 9E8E5BCD1AE2B1C800BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */, DC30E400153DFE52001B9E6D /* RFImageToDataTransformer.m in Sources */, DC30E402153DFE52001B9E6D /* XMPPIDTracker.m in Sources */, DC30E403153DFE52001B9E6D /* XMPPSRVResolver.m in Sources */, @@ -612,8 +628,8 @@ DC30E408153DFE52001B9E6D /* DDFileLogger.m in Sources */, DC30E409153DFE52001B9E6D /* DDLog.m in Sources */, DC30E40A153DFE52001B9E6D /* DDTTYLogger.m in Sources */, - DC30E40B153DFE52001B9E6D /* ContextFilterLogFormatter.m in Sources */, - DC30E40C153DFE52001B9E6D /* DispatchQueueLogFormatter.m in Sources */, + DC30E40B153DFE52001B9E6D /* DDContextFilterLogFormatter.m in Sources */, + DC30E40C153DFE52001B9E6D /* DDDispatchQueueLogFormatter.m in Sources */, DC30E433153DFE52001B9E6D /* NSString+DDXML.m in Sources */, DC30E434153DFE52001B9E6D /* DDXMLDocument.m in Sources */, DC30E435153DFE52001B9E6D /* DDXMLElement.m in Sources */, @@ -681,7 +697,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; SDKROOT = iphoneos; }; name = Debug; @@ -699,7 +715,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; diff --git a/Xcode/Testing/AutoTimeTest/Mobile/AutoTimeTest/AutoTimeTestAppDelegate.m b/Xcode/Testing/AutoTimeTest/Mobile/AutoTimeTest/AutoTimeTestAppDelegate.m index 9c599af658..66ced01520 100644 --- a/Xcode/Testing/AutoTimeTest/Mobile/AutoTimeTest/AutoTimeTestAppDelegate.m +++ b/Xcode/Testing/AutoTimeTest/Mobile/AutoTimeTest/AutoTimeTestAppDelegate.m @@ -37,7 +37,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( NSError *error = nil; - if (![xmppStream connect:&error]) + if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]) { DDLogError(@"%@: Error connecting: %@", [self class], error); } diff --git a/Xcode/Testing/FacebookTest/FacebookTest.xcodeproj/project.pbxproj b/Xcode/Testing/FacebookTest/FacebookTest.xcodeproj/project.pbxproj index b0ee66c279..d8cb944b8e 100644 --- a/Xcode/Testing/FacebookTest/FacebookTest.xcodeproj/project.pbxproj +++ b/Xcode/Testing/FacebookTest/FacebookTest.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 4AB0D3B31746851500B4034A /* libfacebook_ios_sdk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4AB0D3B01746850500B4034A /* libfacebook_ios_sdk.a */; }; + 9E8E5BC21AE2AF2900BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E8E5BC11AE2AF2900BE3E34 /* XMPPSCRAMSHA1Authentication.m */; }; + 9E8E5BD51AE2B54200BE3E34 /* XMPPIDTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E8E5BD31AE2B54200BE3E34 /* XMPPIDTracker.m */; }; DC30E5D3153E0204001B9E6D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC30E5D2153E0204001B9E6D /* Security.framework */; }; DC30E84D153E0B72001B9E6D /* XMPPAnonymousAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E83C153E0B72001B9E6D /* XMPPAnonymousAuthentication.m */; }; DC30E84E153E0B72001B9E6D /* XMPPDeprecatedDigestAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E83F153E0B72001B9E6D /* XMPPDeprecatedDigestAuthentication.m */; }; @@ -70,24 +72,15 @@ remoteGlobalIDString = D2AAC07D0554694100DB518D; remoteInfo = "facebook-ios-sdk"; }; - DC49313D17F8E0FA00402F77 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4AB0D3AB1746850500B4034A /* facebook-ios-sdk.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = B9CBC519152537270036AA71; - remoteInfo = FacebookSDKTests; - }; - DC49313F17F8E0FA00402F77 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4AB0D3AB1746850500B4034A /* facebook-ios-sdk.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 85A44B9F16A8CE05007BE80E; - remoteInfo = FacebookSDKIntegrationTests; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 4AB0D3AB1746850500B4034A /* facebook-ios-sdk.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "facebook-ios-sdk.xcodeproj"; path = "facebook-ios-sdk/src/facebook-ios-sdk.xcodeproj"; sourceTree = ""; }; + 9E8E5BBE1AE2AF2200BE3E34 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9E8E5BC01AE2AF2900BE3E34 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9E8E5BC11AE2AF2900BE3E34 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; + 9E8E5BD31AE2B54200BE3E34 /* XMPPIDTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPIDTracker.m; sourceTree = ""; }; + 9E8E5BD41AE2B54200BE3E34 /* XMPPIDTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPIDTracker.h; sourceTree = ""; }; DC0AC2A913490B3F00D053E3 /* XMPPInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPInternal.h; sourceTree = ""; }; DC30E5D2153E0204001B9E6D /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; DC30E83B153E0B72001B9E6D /* XMPPAnonymousAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPAnonymousAuthentication.h; sourceTree = ""; }; @@ -210,12 +203,19 @@ isa = PBXGroup; children = ( 4AB0D3B01746850500B4034A /* libfacebook_ios_sdk.a */, - DC49313E17F8E0FA00402F77 /* FacebookSDKTests.octest */, - DC49314017F8E0FA00402F77 /* FacebookSDKIntegrationTests.octest */, ); name = Products; sourceTree = ""; }; + 9E8E5BBF1AE2AF2900BE3E34 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9E8E5BC01AE2AF2900BE3E34 /* XMPPSCRAMSHA1Authentication.h */, + 9E8E5BC11AE2AF2900BE3E34 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC30E839153E0B72001B9E6D /* Authentication */ = { isa = PBXGroup; children = ( @@ -224,7 +224,9 @@ DC30E840153E0B72001B9E6D /* Deprecated-Plain */, DC30E843153E0B72001B9E6D /* Digest-MD5 */, DC30E846153E0B72001B9E6D /* Plain */, + 9E8E5BBF1AE2AF2900BE3E34 /* SCRAM-SHA-1 */, DC30E849153E0B72001B9E6D /* X-Facebook-Platform */, + 9E8E5BBE1AE2AF2200BE3E34 /* XMPPCustomBinding.h */, DC30E84C153E0B72001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -343,6 +345,8 @@ children = ( DCC494CD1333043200F3C8F6 /* GCDMulticastDelegate.h */, DCC494CE1333043200F3C8F6 /* GCDMulticastDelegate.m */, + 9E8E5BD31AE2B54200BE3E34 /* XMPPIDTracker.m */, + 9E8E5BD41AE2B54200BE3E34 /* XMPPIDTracker.h */, DCC494CF1333043200F3C8F6 /* XMPPStringPrep.h */, DCC494D01333043200F3C8F6 /* XMPPStringPrep.m */, DCF3C1371367276900111BA3 /* XMPPSRVResolver.h */, @@ -558,20 +562,6 @@ remoteRef = 4AB0D3AF1746850500B4034A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - DC49313E17F8E0FA00402F77 /* FacebookSDKTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = FacebookSDKTests.octest; - remoteRef = DC49313D17F8E0FA00402F77 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - DC49314017F8E0FA00402F77 /* FacebookSDKIntegrationTests.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = FacebookSDKIntegrationTests.octest; - remoteRef = DC49313F17F8E0FA00402F77 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ @@ -602,6 +592,7 @@ DCC494F61333043200F3C8F6 /* XMPPMessage.m in Sources */, DCC494F71333043200F3C8F6 /* XMPPModule.m in Sources */, DCC494F81333043200F3C8F6 /* XMPPParser.m in Sources */, + 9E8E5BD51AE2B54200BE3E34 /* XMPPIDTracker.m in Sources */, DCC494F91333043200F3C8F6 /* XMPPPresence.m in Sources */, DCC494FB1333043200F3C8F6 /* XMPPStream.m in Sources */, DCC494FC1333043200F3C8F6 /* DDList.m in Sources */, @@ -623,6 +614,7 @@ DC30E84D153E0B72001B9E6D /* XMPPAnonymousAuthentication.m in Sources */, DC30E84E153E0B72001B9E6D /* XMPPDeprecatedDigestAuthentication.m in Sources */, DC30E84F153E0B72001B9E6D /* XMPPDeprecatedPlainAuthentication.m in Sources */, + 9E8E5BC21AE2AF2900BE3E34 /* XMPPSCRAMSHA1Authentication.m in Sources */, DC30E850153E0B72001B9E6D /* XMPPDigestMD5Authentication.m in Sources */, DC30E851153E0B72001B9E6D /* XMPPPlainAuthentication.m in Sources */, DC30E852153E0B72001B9E6D /* XMPPXFacebookPlatformAuthentication.m in Sources */, @@ -680,7 +672,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; OTHER_LDFLAGS = "-lxml2"; SDKROOT = iphoneos; }; @@ -696,7 +688,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; OTHER_LDFLAGS = "-lxml2"; SDKROOT = iphoneos; diff --git a/Xcode/Testing/MUCTesting/MUCTesting.xcodeproj/project.pbxproj b/Xcode/Testing/MUCTesting/MUCTesting.xcodeproj/project.pbxproj index f283b2f7db..74edf84499 100644 --- a/Xcode/Testing/MUCTesting/MUCTesting.xcodeproj/project.pbxproj +++ b/Xcode/Testing/MUCTesting/MUCTesting.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 9EF4C51A1AE2BA340019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5191AE2BA340019F001 /* XMPPSCRAMSHA1Authentication.m */; }; DC30E868153E0BAC001B9E6D /* XMPPAnonymousAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E857153E0BAC001B9E6D /* XMPPAnonymousAuthentication.m */; }; DC30E869153E0BAC001B9E6D /* XMPPDeprecatedDigestAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E85A153E0BAC001B9E6D /* XMPPDeprecatedDigestAuthentication.m */; }; DC30E86A153E0BAC001B9E6D /* XMPPDeprecatedPlainAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E85D153E0BAC001B9E6D /* XMPPDeprecatedPlainAuthentication.m */; }; @@ -56,7 +57,7 @@ DCC8905E13EB611200CDAB56 /* XMPPAutoPing.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8904F13EB611200CDAB56 /* XMPPAutoPing.m */; }; DCC8905F13EB611200CDAB56 /* XMPPPing.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8905113EB611200CDAB56 /* XMPPPing.m */; }; DCC8906013EB611200CDAB56 /* XMPPTime.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8905413EB611200CDAB56 /* XMPPTime.m */; }; - DCC8906113EB611200CDAB56 /* XMPPElement+Delay.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8905713EB611200CDAB56 /* XMPPElement+Delay.m */; }; + DCC8906113EB611200CDAB56 /* NSXMLElement+XEP_0203.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8905713EB611200CDAB56 /* NSXMLElement+XEP_0203.m */; }; DCC8907113EB614500CDAB56 /* XMPPCoreDataStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8906413EB614500CDAB56 /* XMPPCoreDataStorage.m */; }; DCC8907213EB614500CDAB56 /* XMPPCapabilities.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = DCC8906813EB614500CDAB56 /* XMPPCapabilities.xcdatamodel */; }; DCC8907313EB614500CDAB56 /* XMPPCapabilitiesCoreDataStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC8906A13EB614500CDAB56 /* XMPPCapabilitiesCoreDataStorage.m */; }; @@ -68,6 +69,9 @@ /* Begin PBXFileReference section */ 56F834A414C7775F00AF62B3 /* XMPPFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPFramework.h; sourceTree = ""; }; + 9EF4C5161AE2BA340019F001 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9EF4C5181AE2BA340019F001 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9EF4C5191AE2BA340019F001 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; DC30E856153E0BAC001B9E6D /* XMPPAnonymousAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPAnonymousAuthentication.h; sourceTree = ""; }; DC30E857153E0BAC001B9E6D /* XMPPAnonymousAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPAnonymousAuthentication.m; sourceTree = ""; }; DC30E859153E0BAC001B9E6D /* XMPPDeprecatedDigestAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPDeprecatedDigestAuthentication.h; sourceTree = ""; }; @@ -117,7 +121,7 @@ DCC88FE313EB5D0B00CDAB56 /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPParser.m; sourceTree = ""; }; DCC88FE413EB5D0B00CDAB56 /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPresence.h; sourceTree = ""; }; DCC88FE513EB5D0B00CDAB56 /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPresence.m; sourceTree = ""; }; - DCC88FE613EB5D0B00CDAB56 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; }; + DCC88FE613EB5D0B00CDAB56 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DCC88FE713EB5D0B00CDAB56 /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStream.m; sourceTree = ""; }; DCC88FE913EB5D0B00CDAB56 /* DDList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDList.h; sourceTree = ""; }; DCC88FEA13EB5D0B00CDAB56 /* DDList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDList.m; sourceTree = ""; }; @@ -169,8 +173,8 @@ DCC8905113EB611200CDAB56 /* XMPPPing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPing.m; sourceTree = ""; }; DCC8905313EB611200CDAB56 /* XMPPTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPTime.h; sourceTree = ""; }; DCC8905413EB611200CDAB56 /* XMPPTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPTime.m; sourceTree = ""; }; - DCC8905613EB611200CDAB56 /* XMPPElement+Delay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XMPPElement+Delay.h"; sourceTree = ""; }; - DCC8905713EB611200CDAB56 /* XMPPElement+Delay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XMPPElement+Delay.m"; sourceTree = ""; }; + DCC8905613EB611200CDAB56 /* NSXMLElement+XEP_0203.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSXMLElement+XEP_0203.h"; sourceTree = ""; }; + DCC8905713EB611200CDAB56 /* NSXMLElement+XEP_0203.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSXMLElement+XEP_0203.m"; sourceTree = ""; }; DCC8906313EB614500CDAB56 /* XMPPCoreDataStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCoreDataStorage.h; sourceTree = ""; }; DCC8906413EB614500CDAB56 /* XMPPCoreDataStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPCoreDataStorage.m; sourceTree = ""; }; DCC8906513EB614500CDAB56 /* XMPPCoreDataStorageProtected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCoreDataStorageProtected.h; sourceTree = ""; }; @@ -204,6 +208,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9EF4C5171AE2BA340019F001 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9EF4C5181AE2BA340019F001 /* XMPPSCRAMSHA1Authentication.h */, + 9EF4C5191AE2BA340019F001 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC30E854153E0BAC001B9E6D /* Authentication */ = { isa = PBXGroup; children = ( @@ -212,7 +225,9 @@ DC30E85B153E0BAC001B9E6D /* Deprecated-Plain */, DC30E85E153E0BAC001B9E6D /* Digest-MD5 */, DC30E861153E0BAC001B9E6D /* Plain */, + 9EF4C5171AE2BA340019F001 /* SCRAM-SHA-1 */, DC30E864153E0BAC001B9E6D /* X-Facebook-Platform */, + 9EF4C5161AE2BA340019F001 /* XMPPCustomBinding.h */, DC30E867153E0BAC001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -538,8 +553,8 @@ DCC8905513EB611200CDAB56 /* XEP-0203 */ = { isa = PBXGroup; children = ( - DCC8905613EB611200CDAB56 /* XMPPElement+Delay.h */, - DCC8905713EB611200CDAB56 /* XMPPElement+Delay.m */, + DCC8905613EB611200CDAB56 /* NSXMLElement+XEP_0203.h */, + DCC8905713EB611200CDAB56 /* NSXMLElement+XEP_0203.m */, ); name = "XEP-0203"; path = "../../../Extensions/XEP-0203"; @@ -678,12 +693,13 @@ DCC8905E13EB611200CDAB56 /* XMPPAutoPing.m in Sources */, DCC8905F13EB611200CDAB56 /* XMPPPing.m in Sources */, DCC8906013EB611200CDAB56 /* XMPPTime.m in Sources */, - DCC8906113EB611200CDAB56 /* XMPPElement+Delay.m in Sources */, + DCC8906113EB611200CDAB56 /* NSXMLElement+XEP_0203.m in Sources */, DCC8907113EB614500CDAB56 /* XMPPCoreDataStorage.m in Sources */, DCC8907213EB614500CDAB56 /* XMPPCapabilities.xcdatamodel in Sources */, DCC8907313EB614500CDAB56 /* XMPPCapabilitiesCoreDataStorage.m in Sources */, DCC8907413EB614500CDAB56 /* XMPPCapsCoreDataStorageObject.m in Sources */, DCC8907513EB614500CDAB56 /* XMPPCapsResourceCoreDataStorageObject.m in Sources */, + 9EF4C51A1AE2BA340019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */, DCC8907613EB614500CDAB56 /* XMPPCapabilities.m in Sources */, DCC8911613EC072300CDAB56 /* XMPPAutoTime.m in Sources */, DC30E868153E0BAC001B9E6D /* XMPPAnonymousAuthentication.m in Sources */, diff --git a/Xcode/Testing/MUCTesting/MUCTesting/MUCTestingAppDelegate.m b/Xcode/Testing/MUCTesting/MUCTesting/MUCTestingAppDelegate.m index 276fa20a81..a98e2fd71b 100644 --- a/Xcode/Testing/MUCTesting/MUCTesting/MUCTestingAppDelegate.m +++ b/Xcode/Testing/MUCTesting/MUCTesting/MUCTestingAppDelegate.m @@ -40,7 +40,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification // Start connection process NSError *err = nil; - if (![xmppStream connect:&err]) + if (![xmppStream connectWithTimeout: XMPPStreamTimeoutNone error:&err]) { DDLogError(@"MUCTesting: Cannot connect: %@", err); } diff --git a/Xcode/Testing/TestCapabilitiesHashing/Mac/TestCapabilitiesHashing/TestCapabilitiesHashing.xcodeproj/project.pbxproj b/Xcode/Testing/TestCapabilitiesHashing/Mac/TestCapabilitiesHashing/TestCapabilitiesHashing.xcodeproj/project.pbxproj index 1eaa4f54b9..00eb5b29c4 100644 --- a/Xcode/Testing/TestCapabilitiesHashing/Mac/TestCapabilitiesHashing/TestCapabilitiesHashing.xcodeproj/project.pbxproj +++ b/Xcode/Testing/TestCapabilitiesHashing/Mac/TestCapabilitiesHashing/TestCapabilitiesHashing.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; + 9EF4C51F1AE2BAA60019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C51E1AE2BAA60019F001 /* XMPPSCRAMSHA1Authentication.m */; }; DC30E67F153E04B8001B9E6D /* libidn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC30E67E153E04B8001B9E6D /* libidn.a */; }; DC30E883153E0BF7001B9E6D /* XMPPAnonymousAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E872153E0BF7001B9E6D /* XMPPAnonymousAuthentication.m */; }; DC30E884153E0BF7001B9E6D /* XMPPDeprecatedDigestAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E875153E0BF7001B9E6D /* XMPPDeprecatedDigestAuthentication.m */; }; @@ -69,6 +70,9 @@ 56F8384914C794BF00AF62B3 /* XMPPIDTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPIDTracker.m; path = ../../../../../Utilities/XMPPIDTracker.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* TestCapabilitiesHashing-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TestCapabilitiesHashing-Info.plist"; sourceTree = ""; }; 8D1107320486CEB800E47090 /* TestCapabilitiesHashing.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestCapabilitiesHashing.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9EF4C51B1AE2BAA60019F001 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9EF4C51D1AE2BAA60019F001 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9EF4C51E1AE2BAA60019F001 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; DC30E67E153E04B8001B9E6D /* libidn.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libidn.a; path = ../../../../../Vendor/libidn/libidn.a; sourceTree = ""; }; DC30E871153E0BF7001B9E6D /* XMPPAnonymousAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPAnonymousAuthentication.h; sourceTree = ""; }; DC30E872153E0BF7001B9E6D /* XMPPAnonymousAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPAnonymousAuthentication.m; sourceTree = ""; }; @@ -116,7 +120,7 @@ DCC0C231130340D200EC45D2 /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPParser.m; path = ../../../../../Core/XMPPParser.m; sourceTree = SOURCE_ROOT; }; DCC0C232130340D200EC45D2 /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPPresence.h; path = ../../../../../Core/XMPPPresence.h; sourceTree = SOURCE_ROOT; }; DCC0C233130340D200EC45D2 /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPPresence.m; path = ../../../../../Core/XMPPPresence.m; sourceTree = SOURCE_ROOT; }; - DCC0C234130340D200EC45D2 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPStream.h; path = ../../../../../Core/XMPPStream.h; sourceTree = SOURCE_ROOT; }; + DCC0C234130340D200EC45D2 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPStream.h; path = ../../../../../Core/XMPPStream.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DCC0C235130340D200EC45D2 /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPStream.m; path = ../../../../../Core/XMPPStream.m; sourceTree = SOURCE_ROOT; }; DCC0C2511303412E00EC45D2 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GCDAsyncSocket.h; path = ../../../../../Vendor/CocoaAsyncSocket/GCDAsyncSocket.h; sourceTree = SOURCE_ROOT; }; DCC0C2521303412E00EC45D2 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GCDAsyncSocket.m; path = ../../../../../Vendor/CocoaAsyncSocket/GCDAsyncSocket.m; sourceTree = SOURCE_ROOT; }; @@ -242,6 +246,15 @@ name = Frameworks; sourceTree = ""; }; + 9EF4C51C1AE2BAA60019F001 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9EF4C51D1AE2BAA60019F001 /* XMPPSCRAMSHA1Authentication.h */, + 9EF4C51E1AE2BAA60019F001 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC30E86F153E0BF7001B9E6D /* Authentication */ = { isa = PBXGroup; children = ( @@ -250,7 +263,9 @@ DC30E876153E0BF7001B9E6D /* Deprecated-Plain */, DC30E879153E0BF7001B9E6D /* Digest-MD5 */, DC30E87C153E0BF7001B9E6D /* Plain */, + 9EF4C51C1AE2BAA60019F001 /* SCRAM-SHA-1 */, DC30E87F153E0BF7001B9E6D /* X-Facebook-Platform */, + 9EF4C51B1AE2BAA60019F001 /* XMPPCustomBinding.h */, DC30E882153E0BF7001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -496,6 +511,8 @@ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; + attributes = { + }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "TestCapabilitiesHashing" */; compatibilityVersion = "Xcode 3.1"; developmentRegion = English; @@ -552,6 +569,7 @@ DCC0C2631303418B00EC45D2 /* DDList.m in Sources */, DCC0C2641303418B00EC45D2 /* XMPPStringPrep.m in Sources */, DCC0C2E71303467700EC45D2 /* XMPPCapabilities.xcdatamodel in Sources */, + 9EF4C51F1AE2BAA60019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */, DCC0C2E81303467700EC45D2 /* XMPPCapabilitiesCoreDataStorage.m in Sources */, DCC0C2E91303467700EC45D2 /* XMPPCapsCoreDataStorageObject.m in Sources */, DCC0C2EA1303467700EC45D2 /* XMPPCapsResourceCoreDataStorageObject.m in Sources */, @@ -613,7 +631,6 @@ "\"$(SRCROOT)/../../../../../Vendor/libidn\"", ); PRODUCT_NAME = TestCapabilitiesHashing; - SDKROOT = macosx10.7; }; name = Debug; }; @@ -634,7 +651,6 @@ "\"$(SRCROOT)/../../../../../Vendor/libidn\"", ); PRODUCT_NAME = TestCapabilitiesHashing; - SDKROOT = macosx10.7; }; name = Release; }; @@ -650,7 +666,6 @@ HEADER_SEARCH_PATHS = /usr/include/libxml2; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; - SDKROOT = macosx10.6; }; name = Debug; }; @@ -663,7 +678,6 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = /usr/include/libxml2; PREBINDING = NO; - SDKROOT = macosx10.6; }; name = Release; }; diff --git a/Xcode/Testing/TestCapabilitiesHashing/iPhone/TestCapabilitiesHashing/TestCapabilitiesHashing.xcodeproj/project.pbxproj b/Xcode/Testing/TestCapabilitiesHashing/iPhone/TestCapabilitiesHashing/TestCapabilitiesHashing.xcodeproj/project.pbxproj index 187a11531e..61a9c2216d 100755 --- a/Xcode/Testing/TestCapabilitiesHashing/iPhone/TestCapabilitiesHashing/TestCapabilitiesHashing.xcodeproj/project.pbxproj +++ b/Xcode/Testing/TestCapabilitiesHashing/iPhone/TestCapabilitiesHashing/TestCapabilitiesHashing.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 28D7ACF80DDB3853001CB0EB /* TestCapabilitiesHashingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* TestCapabilitiesHashingViewController.m */; }; 56F8385F14C7962300AF62B3 /* RFImageToDataTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 56F8385714C7962300AF62B3 /* RFImageToDataTransformer.m */; }; 56F8386114C7962300AF62B3 /* XMPPIDTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 56F8385B14C7962300AF62B3 /* XMPPIDTracker.m */; }; + 9EF4C5241AE2BAB70019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5231AE2BAB70019F001 /* XMPPSCRAMSHA1Authentication.m */; }; DC30E682153E050B001B9E6D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC30E681153E050B001B9E6D /* Security.framework */; }; DC30E684153E0531001B9E6D /* libidn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC30E683153E0531001B9E6D /* libidn.a */; }; DC30E89E153E0C22001B9E6D /* XMPPAnonymousAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E88D153E0C22001B9E6D /* XMPPAnonymousAuthentication.m */; }; @@ -79,6 +80,9 @@ 56F8385A14C7962300AF62B3 /* XMPPIDTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPIDTracker.h; path = ../../../../../Utilities/XMPPIDTracker.h; sourceTree = ""; }; 56F8385B14C7962300AF62B3 /* XMPPIDTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPIDTracker.m; path = ../../../../../Utilities/XMPPIDTracker.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* TestCapabilitiesHashing-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TestCapabilitiesHashing-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; + 9EF4C5201AE2BAB70019F001 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9EF4C5221AE2BAB70019F001 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9EF4C5231AE2BAB70019F001 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; DC30E681153E050B001B9E6D /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; DC30E683153E0531001B9E6D /* libidn.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libidn.a; path = ../../../../../Vendor/libidn/libidn.a; sourceTree = ""; }; DC30E88C153E0C22001B9E6D /* XMPPAnonymousAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPAnonymousAuthentication.h; sourceTree = ""; }; @@ -142,7 +146,7 @@ DCC0C35A130349C300EC45D2 /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPParser.m; path = ../../../../../Core/XMPPParser.m; sourceTree = SOURCE_ROOT; }; DCC0C35B130349C300EC45D2 /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPPresence.h; path = ../../../../../Core/XMPPPresence.h; sourceTree = SOURCE_ROOT; }; DCC0C35C130349C300EC45D2 /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPPresence.m; path = ../../../../../Core/XMPPPresence.m; sourceTree = SOURCE_ROOT; }; - DCC0C35F130349C300EC45D2 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPStream.h; path = ../../../../../Core/XMPPStream.h; sourceTree = SOURCE_ROOT; }; + DCC0C35F130349C300EC45D2 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPStream.h; path = ../../../../../Core/XMPPStream.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DCC0C360130349C300EC45D2 /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPStream.m; path = ../../../../../Core/XMPPStream.m; sourceTree = SOURCE_ROOT; }; DCC0C36C13034A1000EC45D2 /* XMPPCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPPCapabilities.h; path = "../../../../../Extensions/XEP-0115/XMPPCapabilities.h"; sourceTree = SOURCE_ROOT; }; DCC0C36D13034A1000EC45D2 /* XMPPCapabilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XMPPCapabilities.m; path = "../../../../../Extensions/XEP-0115/XMPPCapabilities.m"; sourceTree = SOURCE_ROOT; }; @@ -253,6 +257,15 @@ name = Frameworks; sourceTree = ""; }; + 9EF4C5211AE2BAB70019F001 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9EF4C5221AE2BAB70019F001 /* XMPPSCRAMSHA1Authentication.h */, + 9EF4C5231AE2BAB70019F001 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC30E88A153E0C22001B9E6D /* Authentication */ = { isa = PBXGroup; children = ( @@ -261,7 +274,9 @@ DC30E891153E0C22001B9E6D /* Deprecated-Plain */, DC30E894153E0C22001B9E6D /* Digest-MD5 */, DC30E897153E0C22001B9E6D /* Plain */, + 9EF4C5211AE2BAB70019F001 /* SCRAM-SHA-1 */, DC30E89A153E0C22001B9E6D /* X-Facebook-Platform */, + 9EF4C5201AE2BAB70019F001 /* XMPPCustomBinding.h */, DC30E89D153E0C22001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -619,6 +634,7 @@ DC30E8A0153E0C22001B9E6D /* XMPPDeprecatedPlainAuthentication.m in Sources */, DC30E8A1153E0C22001B9E6D /* XMPPDigestMD5Authentication.m in Sources */, DC30E8A2153E0C22001B9E6D /* XMPPPlainAuthentication.m in Sources */, + 9EF4C5241AE2BAB70019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */, DC30E8A3153E0C22001B9E6D /* XMPPXFacebookPlatformAuthentication.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Xcode/Testing/TestElementReceipt/TestElementReceipt.xcodeproj/project.pbxproj b/Xcode/Testing/TestElementReceipt/TestElementReceipt.xcodeproj/project.pbxproj index be2015d3ca..cf78c9aea1 100644 --- a/Xcode/Testing/TestElementReceipt/TestElementReceipt.xcodeproj/project.pbxproj +++ b/Xcode/Testing/TestElementReceipt/TestElementReceipt.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 9EF4C5291AE2BC2F0019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5281AE2BC2F0019F001 /* XMPPSCRAMSHA1Authentication.m */; }; DC30E8B9153E0C42001B9E6D /* XMPPAnonymousAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E8A8153E0C42001B9E6D /* XMPPAnonymousAuthentication.m */; }; DC30E8BA153E0C42001B9E6D /* XMPPDeprecatedDigestAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E8AB153E0C42001B9E6D /* XMPPDeprecatedDigestAuthentication.m */; }; DC30E8BB153E0C42001B9E6D /* XMPPDeprecatedPlainAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = DC30E8AE153E0C42001B9E6D /* XMPPDeprecatedPlainAuthentication.m */; }; @@ -49,6 +50,9 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 9EF4C5251AE2BC2F0019F001 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9EF4C5271AE2BC2F0019F001 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9EF4C5281AE2BC2F0019F001 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; DC30E8A7153E0C42001B9E6D /* XMPPAnonymousAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPAnonymousAuthentication.h; sourceTree = ""; }; DC30E8A8153E0C42001B9E6D /* XMPPAnonymousAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPAnonymousAuthentication.m; sourceTree = ""; }; DC30E8AA153E0C42001B9E6D /* XMPPDeprecatedDigestAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPDeprecatedDigestAuthentication.h; sourceTree = ""; }; @@ -98,7 +102,7 @@ DCC890BE13EBF90C00CDAB56 /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPParser.m; sourceTree = ""; }; DCC890BF13EBF90C00CDAB56 /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPresence.h; sourceTree = ""; }; DCC890C013EBF90C00CDAB56 /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPresence.m; sourceTree = ""; }; - DCC890C113EBF90C00CDAB56 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; }; + DCC890C113EBF90C00CDAB56 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DCC890C213EBF90C00CDAB56 /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStream.m; sourceTree = ""; }; DCC890C413EBF90C00CDAB56 /* DDList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDList.h; sourceTree = ""; }; DCC890C513EBF90C00CDAB56 /* DDList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDList.m; sourceTree = ""; }; @@ -148,6 +152,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9EF4C5261AE2BC2F0019F001 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9EF4C5271AE2BC2F0019F001 /* XMPPSCRAMSHA1Authentication.h */, + 9EF4C5281AE2BC2F0019F001 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; DC30E8A5153E0C42001B9E6D /* Authentication */ = { isa = PBXGroup; children = ( @@ -156,7 +169,9 @@ DC30E8AC153E0C42001B9E6D /* Deprecated-Plain */, DC30E8AF153E0C42001B9E6D /* Digest-MD5 */, DC30E8B2153E0C42001B9E6D /* Plain */, + 9EF4C5261AE2BC2F0019F001 /* SCRAM-SHA-1 */, DC30E8B5153E0C42001B9E6D /* X-Facebook-Platform */, + 9EF4C5251AE2BC2F0019F001 /* XMPPCustomBinding.h */, DC30E8B8153E0C42001B9E6D /* XMPPSASLAuthentication.h */, ); name = Authentication; @@ -463,6 +478,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9EF4C5291AE2BC2F0019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */, DCC8909713EBF8EC00CDAB56 /* main.m in Sources */, DCC8909E13EBF8EC00CDAB56 /* TestElementReceiptAppDelegate.m in Sources */, DCC890F113EBF90C00CDAB56 /* NSData+XMPP.m in Sources */, diff --git a/Xcode/Testing/TestIDTracker/TestIDTracker.xcodeproj/project.pbxproj b/Xcode/Testing/TestIDTracker/TestIDTracker.xcodeproj/project.pbxproj index 7faf29138d..373b308b30 100644 --- a/Xcode/Testing/TestIDTracker/TestIDTracker.xcodeproj/project.pbxproj +++ b/Xcode/Testing/TestIDTracker/TestIDTracker.xcodeproj/project.pbxproj @@ -7,6 +7,34 @@ objects = { /* Begin PBXBuildFile section */ + 9EF4C5461AE2BCBC0019F001 /* XMPPAnonymousAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C52E1AE2BCBC0019F001 /* XMPPAnonymousAuthentication.m */; }; + 9EF4C5471AE2BCBC0019F001 /* XMPPDeprecatedDigestAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5311AE2BCBC0019F001 /* XMPPDeprecatedDigestAuthentication.m */; }; + 9EF4C5481AE2BCBC0019F001 /* XMPPDeprecatedPlainAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5341AE2BCBC0019F001 /* XMPPDeprecatedPlainAuthentication.m */; }; + 9EF4C5491AE2BCBC0019F001 /* XMPPDigestMD5Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5371AE2BCBC0019F001 /* XMPPDigestMD5Authentication.m */; }; + 9EF4C54A1AE2BCBC0019F001 /* XMPPPlainAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C53A1AE2BCBC0019F001 /* XMPPPlainAuthentication.m */; }; + 9EF4C54B1AE2BCBC0019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C53D1AE2BCBC0019F001 /* XMPPSCRAMSHA1Authentication.m */; }; + 9EF4C54C1AE2BCBC0019F001 /* XMPPXFacebookPlatformAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5401AE2BCBC0019F001 /* XMPPXFacebookPlatformAuthentication.m */; }; + 9EF4C54D1AE2BCBC0019F001 /* XMPPXOAuth2Google.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5431AE2BCBC0019F001 /* XMPPXOAuth2Google.m */; }; + 9EF4C5511AE2BCD10019F001 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5501AE2BCD10019F001 /* GCDAsyncSocket.m */; }; + 9EF4C5571AE2BD4B0019F001 /* GCDMulticastDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5551AE2BD4B0019F001 /* GCDMulticastDelegate.m */; }; + 9EF4C56E1AE2BD660019F001 /* XMPPConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C55B1AE2BD660019F001 /* XMPPConstants.m */; }; + 9EF4C56F1AE2BD660019F001 /* XMPPElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C55D1AE2BD660019F001 /* XMPPElement.m */; }; + 9EF4C5701AE2BD660019F001 /* XMPPIQ.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5601AE2BD660019F001 /* XMPPIQ.m */; }; + 9EF4C5711AE2BD660019F001 /* XMPPJID.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5621AE2BD660019F001 /* XMPPJID.m */; }; + 9EF4C5721AE2BD660019F001 /* XMPPMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5651AE2BD660019F001 /* XMPPMessage.m */; }; + 9EF4C5731AE2BD660019F001 /* XMPPModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5671AE2BD660019F001 /* XMPPModule.m */; }; + 9EF4C5741AE2BD660019F001 /* XMPPParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5691AE2BD660019F001 /* XMPPParser.m */; }; + 9EF4C5751AE2BD660019F001 /* XMPPPresence.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C56B1AE2BD660019F001 /* XMPPPresence.m */; }; + 9EF4C5761AE2BD660019F001 /* XMPPStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C56D1AE2BD660019F001 /* XMPPStream.m */; }; + 9EF4C57E1AE2BD870019F001 /* NSData+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5791AE2BD870019F001 /* NSData+XMPP.m */; }; + 9EF4C57F1AE2BD870019F001 /* NSNumber+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C57B1AE2BD870019F001 /* NSNumber+XMPP.m */; }; + 9EF4C5801AE2BD870019F001 /* NSXMLElement+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C57D1AE2BD870019F001 /* NSXMLElement+XMPP.m */; }; + 9EF4C5821AE2BDC90019F001 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C5811AE2BDC90019F001 /* libxml2.dylib */; }; + 9EF4C5851AE2BE4E0019F001 /* XMPPSRVResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5831AE2BE4E0019F001 /* XMPPSRVResolver.m */; }; + 9EF4C5881AE2BE5C0019F001 /* XMPPStringPrep.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5861AE2BE5C0019F001 /* XMPPStringPrep.m */; }; + 9EF4C5911AE2BEBE0019F001 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C5901AE2BEBE0019F001 /* Security.framework */; }; + 9EF4C5931AE2BED70019F001 /* libidn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C5921AE2BED70019F001 /* libidn.a */; }; + 9EF4C5971AE2BF1C0019F001 /* libresolv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C5961AE2BF1C0019F001 /* libresolv.dylib */; }; DCC88A7B13E7770D00CDAB56 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC88A7A13E7770D00CDAB56 /* Cocoa.framework */; }; DCC88A8513E7770D00CDAB56 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DCC88A8313E7770D00CDAB56 /* InfoPlist.strings */; }; DCC88A8713E7770D00CDAB56 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC88A8613E7770D00CDAB56 /* main.m */; }; @@ -22,6 +50,67 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 9EF4C52A1AE2BC9E0019F001 /* XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XMPP.h; path = ../../../../Core/XMPP.h; sourceTree = ""; }; + 9EF4C52D1AE2BCBC0019F001 /* XMPPAnonymousAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPAnonymousAuthentication.h; sourceTree = ""; }; + 9EF4C52E1AE2BCBC0019F001 /* XMPPAnonymousAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPAnonymousAuthentication.m; sourceTree = ""; }; + 9EF4C5301AE2BCBC0019F001 /* XMPPDeprecatedDigestAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPDeprecatedDigestAuthentication.h; sourceTree = ""; }; + 9EF4C5311AE2BCBC0019F001 /* XMPPDeprecatedDigestAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPDeprecatedDigestAuthentication.m; sourceTree = ""; }; + 9EF4C5331AE2BCBC0019F001 /* XMPPDeprecatedPlainAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPDeprecatedPlainAuthentication.h; sourceTree = ""; }; + 9EF4C5341AE2BCBC0019F001 /* XMPPDeprecatedPlainAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPDeprecatedPlainAuthentication.m; sourceTree = ""; }; + 9EF4C5361AE2BCBC0019F001 /* XMPPDigestMD5Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPDigestMD5Authentication.h; sourceTree = ""; }; + 9EF4C5371AE2BCBC0019F001 /* XMPPDigestMD5Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPDigestMD5Authentication.m; sourceTree = ""; }; + 9EF4C5391AE2BCBC0019F001 /* XMPPPlainAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPlainAuthentication.h; sourceTree = ""; }; + 9EF4C53A1AE2BCBC0019F001 /* XMPPPlainAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPlainAuthentication.m; sourceTree = ""; }; + 9EF4C53C1AE2BCBC0019F001 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9EF4C53D1AE2BCBC0019F001 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; + 9EF4C53F1AE2BCBC0019F001 /* XMPPXFacebookPlatformAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPXFacebookPlatformAuthentication.h; sourceTree = ""; }; + 9EF4C5401AE2BCBC0019F001 /* XMPPXFacebookPlatformAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPXFacebookPlatformAuthentication.m; sourceTree = ""; }; + 9EF4C5421AE2BCBC0019F001 /* XMPPXOAuth2Google.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPXOAuth2Google.h; sourceTree = ""; }; + 9EF4C5431AE2BCBC0019F001 /* XMPPXOAuth2Google.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPXOAuth2Google.m; sourceTree = ""; }; + 9EF4C5441AE2BCBC0019F001 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9EF4C5451AE2BCBC0019F001 /* XMPPSASLAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSASLAuthentication.h; sourceTree = ""; }; + 9EF4C54F1AE2BCD10019F001 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = ""; }; + 9EF4C5501AE2BCD10019F001 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = ""; }; + 9EF4C5551AE2BD4B0019F001 /* GCDMulticastDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDMulticastDelegate.m; sourceTree = ""; }; + 9EF4C5561AE2BD4B0019F001 /* GCDMulticastDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDMulticastDelegate.h; sourceTree = ""; }; + 9EF4C5591AE2BD660019F001 /* XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPP.h; sourceTree = ""; }; + 9EF4C55A1AE2BD660019F001 /* XMPPConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPConstants.h; sourceTree = ""; }; + 9EF4C55B1AE2BD660019F001 /* XMPPConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPConstants.m; sourceTree = ""; }; + 9EF4C55C1AE2BD660019F001 /* XMPPElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPElement.h; sourceTree = ""; }; + 9EF4C55D1AE2BD660019F001 /* XMPPElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPElement.m; sourceTree = ""; }; + 9EF4C55E1AE2BD660019F001 /* XMPPInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPInternal.h; sourceTree = ""; }; + 9EF4C55F1AE2BD660019F001 /* XMPPIQ.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPIQ.h; sourceTree = ""; }; + 9EF4C5601AE2BD660019F001 /* XMPPIQ.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPIQ.m; sourceTree = ""; }; + 9EF4C5611AE2BD660019F001 /* XMPPJID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPJID.h; sourceTree = ""; }; + 9EF4C5621AE2BD660019F001 /* XMPPJID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPJID.m; sourceTree = ""; }; + 9EF4C5631AE2BD660019F001 /* XMPPLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPLogging.h; sourceTree = ""; }; + 9EF4C5641AE2BD660019F001 /* XMPPMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPMessage.h; sourceTree = ""; }; + 9EF4C5651AE2BD660019F001 /* XMPPMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPMessage.m; sourceTree = ""; }; + 9EF4C5661AE2BD660019F001 /* XMPPModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPModule.h; sourceTree = ""; }; + 9EF4C5671AE2BD660019F001 /* XMPPModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPModule.m; sourceTree = ""; }; + 9EF4C5681AE2BD660019F001 /* XMPPParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPParser.h; sourceTree = ""; }; + 9EF4C5691AE2BD660019F001 /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPParser.m; sourceTree = ""; }; + 9EF4C56A1AE2BD660019F001 /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPresence.h; sourceTree = ""; }; + 9EF4C56B1AE2BD660019F001 /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPresence.m; sourceTree = ""; }; + 9EF4C56C1AE2BD660019F001 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; }; + 9EF4C56D1AE2BD660019F001 /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStream.m; sourceTree = ""; }; + 9EF4C5781AE2BD870019F001 /* NSData+XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+XMPP.h"; sourceTree = ""; }; + 9EF4C5791AE2BD870019F001 /* NSData+XMPP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+XMPP.m"; sourceTree = ""; }; + 9EF4C57A1AE2BD870019F001 /* NSNumber+XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNumber+XMPP.h"; sourceTree = ""; }; + 9EF4C57B1AE2BD870019F001 /* NSNumber+XMPP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNumber+XMPP.m"; sourceTree = ""; }; + 9EF4C57C1AE2BD870019F001 /* NSXMLElement+XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSXMLElement+XMPP.h"; sourceTree = ""; }; + 9EF4C57D1AE2BD870019F001 /* NSXMLElement+XMPP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSXMLElement+XMPP.m"; sourceTree = ""; }; + 9EF4C5811AE2BDC90019F001 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; }; + 9EF4C5831AE2BE4E0019F001 /* XMPPSRVResolver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSRVResolver.m; sourceTree = ""; }; + 9EF4C5841AE2BE4E0019F001 /* XMPPSRVResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSRVResolver.h; sourceTree = ""; }; + 9EF4C5861AE2BE5C0019F001 /* XMPPStringPrep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStringPrep.m; sourceTree = ""; }; + 9EF4C5871AE2BE5C0019F001 /* XMPPStringPrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStringPrep.h; sourceTree = ""; }; + 9EF4C58B1AE2BE850019F001 /* idn-int.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "idn-int.h"; sourceTree = ""; }; + 9EF4C58D1AE2BE850019F001 /* stringprep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stringprep.h; sourceTree = ""; }; + 9EF4C5901AE2BEBE0019F001 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 9EF4C5921AE2BED70019F001 /* libidn.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libidn.a; path = ../../../Vendor/libidn/libidn.a; sourceTree = ""; }; + 9EF4C5941AE2BEEA0019F001 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 9EF4C5961AE2BF1C0019F001 /* libresolv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libresolv.dylib; path = usr/lib/libresolv.dylib; sourceTree = SDKROOT; }; DCC88A7613E7770D00CDAB56 /* TestIDTracker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestIDTracker.app; sourceTree = BUILT_PRODUCTS_DIR; }; DCC88A7A13E7770D00CDAB56 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; DCC88A7D13E7770D00CDAB56 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; @@ -54,6 +143,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9EF4C5971AE2BF1C0019F001 /* libresolv.dylib in Frameworks */, + 9EF4C5931AE2BED70019F001 /* libidn.a in Frameworks */, + 9EF4C5911AE2BEBE0019F001 /* Security.framework in Frameworks */, + 9EF4C5821AE2BDC90019F001 /* libxml2.dylib in Frameworks */, DCC88A7B13E7770D00CDAB56 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -61,6 +154,189 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9EF4C52B1AE2BCBC0019F001 /* Authentication */ = { + isa = PBXGroup; + children = ( + 9EF4C52C1AE2BCBC0019F001 /* Anonymous */, + 9EF4C52F1AE2BCBC0019F001 /* Deprecated-Digest */, + 9EF4C5321AE2BCBC0019F001 /* Deprecated-Plain */, + 9EF4C5351AE2BCBC0019F001 /* Digest-MD5 */, + 9EF4C5381AE2BCBC0019F001 /* Plain */, + 9EF4C53B1AE2BCBC0019F001 /* SCRAM-SHA-1 */, + 9EF4C53E1AE2BCBC0019F001 /* X-Facebook-Platform */, + 9EF4C5411AE2BCBC0019F001 /* X-OAuth2-Google */, + 9EF4C5441AE2BCBC0019F001 /* XMPPCustomBinding.h */, + 9EF4C5451AE2BCBC0019F001 /* XMPPSASLAuthentication.h */, + ); + path = Authentication; + sourceTree = ""; + }; + 9EF4C52C1AE2BCBC0019F001 /* Anonymous */ = { + isa = PBXGroup; + children = ( + 9EF4C52D1AE2BCBC0019F001 /* XMPPAnonymousAuthentication.h */, + 9EF4C52E1AE2BCBC0019F001 /* XMPPAnonymousAuthentication.m */, + ); + path = Anonymous; + sourceTree = ""; + }; + 9EF4C52F1AE2BCBC0019F001 /* Deprecated-Digest */ = { + isa = PBXGroup; + children = ( + 9EF4C5301AE2BCBC0019F001 /* XMPPDeprecatedDigestAuthentication.h */, + 9EF4C5311AE2BCBC0019F001 /* XMPPDeprecatedDigestAuthentication.m */, + ); + path = "Deprecated-Digest"; + sourceTree = ""; + }; + 9EF4C5321AE2BCBC0019F001 /* Deprecated-Plain */ = { + isa = PBXGroup; + children = ( + 9EF4C5331AE2BCBC0019F001 /* XMPPDeprecatedPlainAuthentication.h */, + 9EF4C5341AE2BCBC0019F001 /* XMPPDeprecatedPlainAuthentication.m */, + ); + path = "Deprecated-Plain"; + sourceTree = ""; + }; + 9EF4C5351AE2BCBC0019F001 /* Digest-MD5 */ = { + isa = PBXGroup; + children = ( + 9EF4C5361AE2BCBC0019F001 /* XMPPDigestMD5Authentication.h */, + 9EF4C5371AE2BCBC0019F001 /* XMPPDigestMD5Authentication.m */, + ); + path = "Digest-MD5"; + sourceTree = ""; + }; + 9EF4C5381AE2BCBC0019F001 /* Plain */ = { + isa = PBXGroup; + children = ( + 9EF4C5391AE2BCBC0019F001 /* XMPPPlainAuthentication.h */, + 9EF4C53A1AE2BCBC0019F001 /* XMPPPlainAuthentication.m */, + ); + path = Plain; + sourceTree = ""; + }; + 9EF4C53B1AE2BCBC0019F001 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9EF4C53C1AE2BCBC0019F001 /* XMPPSCRAMSHA1Authentication.h */, + 9EF4C53D1AE2BCBC0019F001 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; + 9EF4C53E1AE2BCBC0019F001 /* X-Facebook-Platform */ = { + isa = PBXGroup; + children = ( + 9EF4C53F1AE2BCBC0019F001 /* XMPPXFacebookPlatformAuthentication.h */, + 9EF4C5401AE2BCBC0019F001 /* XMPPXFacebookPlatformAuthentication.m */, + ); + path = "X-Facebook-Platform"; + sourceTree = ""; + }; + 9EF4C5411AE2BCBC0019F001 /* X-OAuth2-Google */ = { + isa = PBXGroup; + children = ( + 9EF4C5421AE2BCBC0019F001 /* XMPPXOAuth2Google.h */, + 9EF4C5431AE2BCBC0019F001 /* XMPPXOAuth2Google.m */, + ); + path = "X-OAuth2-Google"; + sourceTree = ""; + }; + 9EF4C54E1AE2BCD10019F001 /* CocoaAsyncSocket */ = { + isa = PBXGroup; + children = ( + 9EF4C54F1AE2BCD10019F001 /* GCDAsyncSocket.h */, + 9EF4C5501AE2BCD10019F001 /* GCDAsyncSocket.m */, + ); + path = CocoaAsyncSocket; + sourceTree = ""; + }; + 9EF4C5521AE2BCEC0019F001 /* Vendor */ = { + isa = PBXGroup; + children = ( + 9EF4C5891AE2BE850019F001 /* libidn */, + 9EF4C54E1AE2BCD10019F001 /* CocoaAsyncSocket */, + ); + path = Vendor; + sourceTree = ""; + }; + 9EF4C5531AE2BD240019F001 /* Utilities */ = { + isa = PBXGroup; + children = ( + 9EF4C5861AE2BE5C0019F001 /* XMPPStringPrep.m */, + 9EF4C5871AE2BE5C0019F001 /* XMPPStringPrep.h */, + 9EF4C5831AE2BE4E0019F001 /* XMPPSRVResolver.m */, + 9EF4C5841AE2BE4E0019F001 /* XMPPSRVResolver.h */, + 9EF4C5551AE2BD4B0019F001 /* GCDMulticastDelegate.m */, + 9EF4C5561AE2BD4B0019F001 /* GCDMulticastDelegate.h */, + ); + path = Utilities; + sourceTree = ""; + }; + 9EF4C5541AE2BD330019F001 /* XMPP */ = { + isa = PBXGroup; + children = ( + 9EF4C5771AE2BD870019F001 /* Categories */, + 9EF4C5581AE2BD660019F001 /* Core */, + 9EF4C5531AE2BD240019F001 /* Utilities */, + 9EF4C5521AE2BCEC0019F001 /* Vendor */, + 9EF4C52B1AE2BCBC0019F001 /* Authentication */, + ); + name = XMPP; + path = ../../../..; + sourceTree = ""; + }; + 9EF4C5581AE2BD660019F001 /* Core */ = { + isa = PBXGroup; + children = ( + 9EF4C5591AE2BD660019F001 /* XMPP.h */, + 9EF4C55A1AE2BD660019F001 /* XMPPConstants.h */, + 9EF4C55B1AE2BD660019F001 /* XMPPConstants.m */, + 9EF4C55C1AE2BD660019F001 /* XMPPElement.h */, + 9EF4C55D1AE2BD660019F001 /* XMPPElement.m */, + 9EF4C55E1AE2BD660019F001 /* XMPPInternal.h */, + 9EF4C55F1AE2BD660019F001 /* XMPPIQ.h */, + 9EF4C5601AE2BD660019F001 /* XMPPIQ.m */, + 9EF4C5611AE2BD660019F001 /* XMPPJID.h */, + 9EF4C5621AE2BD660019F001 /* XMPPJID.m */, + 9EF4C5631AE2BD660019F001 /* XMPPLogging.h */, + 9EF4C5641AE2BD660019F001 /* XMPPMessage.h */, + 9EF4C5651AE2BD660019F001 /* XMPPMessage.m */, + 9EF4C5661AE2BD660019F001 /* XMPPModule.h */, + 9EF4C5671AE2BD660019F001 /* XMPPModule.m */, + 9EF4C5681AE2BD660019F001 /* XMPPParser.h */, + 9EF4C5691AE2BD660019F001 /* XMPPParser.m */, + 9EF4C56A1AE2BD660019F001 /* XMPPPresence.h */, + 9EF4C56B1AE2BD660019F001 /* XMPPPresence.m */, + 9EF4C56C1AE2BD660019F001 /* XMPPStream.h */, + 9EF4C56D1AE2BD660019F001 /* XMPPStream.m */, + ); + path = Core; + sourceTree = ""; + }; + 9EF4C5771AE2BD870019F001 /* Categories */ = { + isa = PBXGroup; + children = ( + 9EF4C5781AE2BD870019F001 /* NSData+XMPP.h */, + 9EF4C5791AE2BD870019F001 /* NSData+XMPP.m */, + 9EF4C57A1AE2BD870019F001 /* NSNumber+XMPP.h */, + 9EF4C57B1AE2BD870019F001 /* NSNumber+XMPP.m */, + 9EF4C57C1AE2BD870019F001 /* NSXMLElement+XMPP.h */, + 9EF4C57D1AE2BD870019F001 /* NSXMLElement+XMPP.m */, + ); + path = Categories; + sourceTree = ""; + }; + 9EF4C5891AE2BE850019F001 /* libidn */ = { + isa = PBXGroup; + children = ( + 9EF4C58B1AE2BE850019F001 /* idn-int.h */, + 9EF4C58D1AE2BE850019F001 /* stringprep.h */, + ); + path = libidn; + sourceTree = ""; + }; DCC88A6B13E7770D00CDAB56 = { isa = PBXGroup; children = ( @@ -82,6 +358,11 @@ DCC88A7913E7770D00CDAB56 /* Frameworks */ = { isa = PBXGroup; children = ( + 9EF4C5961AE2BF1C0019F001 /* libresolv.dylib */, + 9EF4C5941AE2BEEA0019F001 /* CFNetwork.framework */, + 9EF4C5921AE2BED70019F001 /* libidn.a */, + 9EF4C5901AE2BEBE0019F001 /* Security.framework */, + 9EF4C5811AE2BDC90019F001 /* libxml2.dylib */, DCC88A7A13E7770D00CDAB56 /* Cocoa.framework */, DCC88A7C13E7770D00CDAB56 /* Other Frameworks */, ); @@ -101,6 +382,8 @@ DCC88A8013E7770D00CDAB56 /* TestIDTracker */ = { isa = PBXGroup; children = ( + 9EF4C5541AE2BD330019F001 /* XMPP */, + 9EF4C52A1AE2BC9E0019F001 /* XMPP.h */, DCC88A9713E7772900CDAB56 /* XMPPIDTracker.h */, DCC88A9813E7772900CDAB56 /* XMPPIDTracker.m */, DCC88A8C13E7770E00CDAB56 /* TestIDTrackerAppDelegate.h */, @@ -204,13 +487,37 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9EF4C5701AE2BD660019F001 /* XMPPIQ.m in Sources */, + 9EF4C5851AE2BE4E0019F001 /* XMPPSRVResolver.m in Sources */, DCC88A8713E7770D00CDAB56 /* main.m in Sources */, DCC88A8E13E7770E00CDAB56 /* TestIDTrackerAppDelegate.m in Sources */, + 9EF4C57E1AE2BD870019F001 /* NSData+XMPP.m in Sources */, + 9EF4C5741AE2BD660019F001 /* XMPPParser.m in Sources */, DCC88A9913E7772900CDAB56 /* XMPPIDTracker.m in Sources */, DCC88AA513E7817700CDAB56 /* DDAbstractDatabaseLogger.m in Sources */, + 9EF4C56E1AE2BD660019F001 /* XMPPConstants.m in Sources */, + 9EF4C5461AE2BCBC0019F001 /* XMPPAnonymousAuthentication.m in Sources */, + 9EF4C5511AE2BCD10019F001 /* GCDAsyncSocket.m in Sources */, DCC88AA613E7817700CDAB56 /* DDASLLogger.m in Sources */, + 9EF4C5761AE2BD660019F001 /* XMPPStream.m in Sources */, + 9EF4C54C1AE2BCBC0019F001 /* XMPPXFacebookPlatformAuthentication.m in Sources */, + 9EF4C57F1AE2BD870019F001 /* NSNumber+XMPP.m in Sources */, + 9EF4C5721AE2BD660019F001 /* XMPPMessage.m in Sources */, + 9EF4C5481AE2BCBC0019F001 /* XMPPDeprecatedPlainAuthentication.m in Sources */, + 9EF4C5491AE2BCBC0019F001 /* XMPPDigestMD5Authentication.m in Sources */, + 9EF4C5711AE2BD660019F001 /* XMPPJID.m in Sources */, + 9EF4C5751AE2BD660019F001 /* XMPPPresence.m in Sources */, DCC88AA713E7817700CDAB56 /* DDFileLogger.m in Sources */, + 9EF4C54A1AE2BCBC0019F001 /* XMPPPlainAuthentication.m in Sources */, + 9EF4C54D1AE2BCBC0019F001 /* XMPPXOAuth2Google.m in Sources */, + 9EF4C5471AE2BCBC0019F001 /* XMPPDeprecatedDigestAuthentication.m in Sources */, + 9EF4C5731AE2BD660019F001 /* XMPPModule.m in Sources */, + 9EF4C56F1AE2BD660019F001 /* XMPPElement.m in Sources */, DCC88AA813E7817700CDAB56 /* DDLog.m in Sources */, + 9EF4C54B1AE2BCBC0019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */, + 9EF4C5571AE2BD4B0019F001 /* GCDMulticastDelegate.m in Sources */, + 9EF4C5801AE2BD870019F001 /* NSXMLElement+XMPP.m in Sources */, + 9EF4C5881AE2BE5C0019F001 /* XMPPStringPrep.m in Sources */, DCC88AA913E7817700CDAB56 /* DDTTYLogger.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -265,6 +572,7 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = /usr/include/libxml2; MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -285,6 +593,7 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = /usr/include/libxml2; MACOSX_DEPLOYMENT_TARGET = 10.7; SDKROOT = macosx; }; @@ -297,6 +606,10 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "TestIDTracker/TestIDTracker-Prefix.pch"; INFOPLIST_FILE = "TestIDTracker/TestIDTracker-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /Users/pnm/code/XMPPFramework/Vendor/libidn, + ); PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -309,6 +622,10 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "TestIDTracker/TestIDTracker-Prefix.pch"; INFOPLIST_FILE = "TestIDTracker/TestIDTracker-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /Users/pnm/code/XMPPFramework/Vendor/libidn, + ); PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; diff --git a/Xcode/Testing/TestXEP82/Mac/TestXEP82.xcodeproj/project.pbxproj b/Xcode/Testing/TestXEP82/Mac/TestXEP82.xcodeproj/project.pbxproj index 4775ee6651..fa7893825d 100644 --- a/Xcode/Testing/TestXEP82/Mac/TestXEP82.xcodeproj/project.pbxproj +++ b/Xcode/Testing/TestXEP82/Mac/TestXEP82.xcodeproj/project.pbxproj @@ -162,6 +162,8 @@ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; + attributes = { + }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "TestXEP82" */; compatibilityVersion = "Xcode 3.1"; developmentRegion = English; @@ -245,7 +247,6 @@ INFOPLIST_FILE = "TestXEP82-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; PRODUCT_NAME = TestXEP82; - SDKROOT = macosx10.7; }; name = Debug; }; @@ -262,7 +263,6 @@ INFOPLIST_FILE = "TestXEP82-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; PRODUCT_NAME = TestXEP82; - SDKROOT = macosx10.7; }; name = Release; }; @@ -277,7 +277,6 @@ GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; - SDKROOT = macosx10.6; }; name = Debug; }; @@ -289,7 +288,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = macosx10.6; }; name = Release; }; From ab53f94d253190c72ba2620a459eacd4cd95a5bb Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Sat, 18 Apr 2015 13:02:11 -0400 Subject: [PATCH 021/356] Add a new test project, migrate EncodeDecodeTest --- .../project.pbxproj | 896 ++++++++++++++++++ .../XMPPFrameworkTests/AppDelegate.h | 17 + .../XMPPFrameworkTests/AppDelegate.m | 45 + .../Base.lproj/LaunchScreen.xib | 41 + .../Base.lproj/Main.storyboard | 25 + .../AppIcon.appiconset/Contents.json | 38 + .../XMPPFrameworkTests/Info.plist | 40 + .../XMPPFrameworkTests/ViewController.h | 15 + .../XMPPFrameworkTests/ViewController.m | 27 + .../XMPPFrameworkTests/main.m | 16 + .../EncodeDecodeTest.m | 101 ++ .../XMPPFrameworkTestsTests/Info.plist | 24 + 12 files changed, 1285 insertions(+) create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/AppDelegate.h create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/AppDelegate.m create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Base.lproj/LaunchScreen.xib create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Base.lproj/Main.storyboard create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Info.plist create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/ViewController.h create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/ViewController.m create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/main.m create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/EncodeDecodeTest.m create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/Info.plist diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..689f18b494 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj @@ -0,0 +1,896 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9EF4C5A71AE2C2C50019F001 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5A61AE2C2C50019F001 /* main.m */; }; + 9EF4C5AA1AE2C2C50019F001 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5A91AE2C2C50019F001 /* AppDelegate.m */; }; + 9EF4C5AD1AE2C2C50019F001 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5AC1AE2C2C50019F001 /* ViewController.m */; }; + 9EF4C5B01AE2C2C50019F001 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9EF4C5AE1AE2C2C50019F001 /* Main.storyboard */; }; + 9EF4C5B21AE2C2C50019F001 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9EF4C5B11AE2C2C50019F001 /* Images.xcassets */; }; + 9EF4C5B51AE2C2C50019F001 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9EF4C5B31AE2C2C50019F001 /* LaunchScreen.xib */; }; + 9EF4C7101AE2C2F30019F001 /* DDList.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5CD1AE2C2F30019F001 /* DDList.m */; }; + 9EF4C7111AE2C2F30019F001 /* GCDMulticastDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5CF1AE2C2F30019F001 /* GCDMulticastDelegate.m */; }; + 9EF4C7121AE2C2F30019F001 /* RFImageToDataTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5D11AE2C2F30019F001 /* RFImageToDataTransformer.m */; }; + 9EF4C7131AE2C2F30019F001 /* XMPPIDTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5D31AE2C2F30019F001 /* XMPPIDTracker.m */; }; + 9EF4C7141AE2C2F30019F001 /* XMPPSRVResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5D51AE2C2F30019F001 /* XMPPSRVResolver.m */; }; + 9EF4C7151AE2C2F30019F001 /* XMPPStringPrep.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5D71AE2C2F30019F001 /* XMPPStringPrep.m */; }; + 9EF4C7161AE2C2F30019F001 /* XMPPTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5D91AE2C2F30019F001 /* XMPPTimer.m */; }; + 9EF4C7791AE2C2F30019F001 /* XMPPConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6DB1AE2C2F30019F001 /* XMPPConstants.m */; }; + 9EF4C77A1AE2C2F30019F001 /* XMPPElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6DD1AE2C2F30019F001 /* XMPPElement.m */; }; + 9EF4C77B1AE2C2F30019F001 /* XMPPIQ.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6E01AE2C2F30019F001 /* XMPPIQ.m */; }; + 9EF4C77C1AE2C2F30019F001 /* XMPPJID.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6E21AE2C2F30019F001 /* XMPPJID.m */; }; + 9EF4C77D1AE2C2F30019F001 /* XMPPMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6E51AE2C2F30019F001 /* XMPPMessage.m */; }; + 9EF4C77E1AE2C2F30019F001 /* XMPPModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6E71AE2C2F30019F001 /* XMPPModule.m */; }; + 9EF4C77F1AE2C2F30019F001 /* XMPPParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6E91AE2C2F30019F001 /* XMPPParser.m */; }; + 9EF4C7801AE2C2F30019F001 /* XMPPPresence.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6EB1AE2C2F30019F001 /* XMPPPresence.m */; }; + 9EF4C7811AE2C2F30019F001 /* XMPPStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6ED1AE2C2F30019F001 /* XMPPStream.m */; }; + 9EF4C7821AE2C2F30019F001 /* NSData+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6F01AE2C2F30019F001 /* NSData+XMPP.m */; }; + 9EF4C7831AE2C2F30019F001 /* NSNumber+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6F21AE2C2F30019F001 /* NSNumber+XMPP.m */; }; + 9EF4C7841AE2C2F30019F001 /* NSXMLElement+XMPP.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6F41AE2C2F30019F001 /* NSXMLElement+XMPP.m */; }; + 9EF4C7851AE2C2F30019F001 /* XMPPAnonymousAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6F81AE2C2F30019F001 /* XMPPAnonymousAuthentication.m */; }; + 9EF4C7861AE2C2F30019F001 /* XMPPDeprecatedDigestAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6FB1AE2C2F30019F001 /* XMPPDeprecatedDigestAuthentication.m */; }; + 9EF4C7871AE2C2F30019F001 /* XMPPDeprecatedPlainAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C6FE1AE2C2F30019F001 /* XMPPDeprecatedPlainAuthentication.m */; }; + 9EF4C7881AE2C2F30019F001 /* XMPPDigestMD5Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7011AE2C2F30019F001 /* XMPPDigestMD5Authentication.m */; }; + 9EF4C7891AE2C2F30019F001 /* XMPPPlainAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7041AE2C2F30019F001 /* XMPPPlainAuthentication.m */; }; + 9EF4C78A1AE2C2F30019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7071AE2C2F30019F001 /* XMPPSCRAMSHA1Authentication.m */; }; + 9EF4C78B1AE2C2F30019F001 /* XMPPXFacebookPlatformAuthentication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C70A1AE2C2F30019F001 /* XMPPXFacebookPlatformAuthentication.m */; }; + 9EF4C78C1AE2C2F30019F001 /* XMPPXOAuth2Google.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C70D1AE2C2F30019F001 /* XMPPXOAuth2Google.m */; }; + 9EF4C7AC1AE2C3220019F001 /* DDAbstractDatabaseLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7951AE2C3220019F001 /* DDAbstractDatabaseLogger.m */; }; + 9EF4C7AD1AE2C3220019F001 /* DDASLLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7971AE2C3220019F001 /* DDASLLogger.m */; }; + 9EF4C7AE1AE2C3220019F001 /* DDFileLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7991AE2C3220019F001 /* DDFileLogger.m */; }; + 9EF4C7AF1AE2C3220019F001 /* DDLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C79C1AE2C3220019F001 /* DDLog.m */; }; + 9EF4C7B01AE2C3220019F001 /* DDTTYLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C79E1AE2C3220019F001 /* DDTTYLogger.m */; }; + 9EF4C7B11AE2C3220019F001 /* DDContextFilterLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7A11AE2C3220019F001 /* DDContextFilterLogFormatter.m */; }; + 9EF4C7B21AE2C3220019F001 /* DDDispatchQueueLogFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7A31AE2C3220019F001 /* DDDispatchQueueLogFormatter.m */; }; + 9EF4C7B31AE2C3220019F001 /* DDMultiFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7A51AE2C3220019F001 /* DDMultiFormatter.m */; }; + 9EF4C7B41AE2C3220019F001 /* README.txt in Resources */ = {isa = PBXBuildFile; fileRef = 9EF4C7A61AE2C3220019F001 /* README.txt */; }; + 9EF4C7B51AE2C3220019F001 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7A91AE2C3220019F001 /* GCDAsyncSocket.m */; }; + 9EF4C7C31AE2C39F0019F001 /* NSString+DDXML.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7B91AE2C39F0019F001 /* NSString+DDXML.m */; }; + 9EF4C7C41AE2C39F0019F001 /* DDXMLDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7BC1AE2C39F0019F001 /* DDXMLDocument.m */; }; + 9EF4C7C51AE2C39F0019F001 /* DDXMLElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7BE1AE2C39F0019F001 /* DDXMLElement.m */; }; + 9EF4C7C61AE2C39F0019F001 /* DDXMLNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7C01AE2C39F0019F001 /* DDXMLNode.m */; }; + 9EF4C7C81AE2C3B70019F001 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C7C71AE2C3B70019F001 /* libxml2.dylib */; }; + 9EF4C7CA1AE2C4320019F001 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C7C91AE2C4320019F001 /* Security.framework */; }; + 9EF4C7CC1AE2C43F0019F001 /* libidn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C7CB1AE2C43F0019F001 /* libidn.a */; }; + 9EF4C7CE1AE2C4480019F001 /* libresolv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C7CD1AE2C4480019F001 /* libresolv.dylib */; }; + 9EF4C7D31AE2C4CC0019F001 /* EncodeDecodeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 9EF4C5BB1AE2C2C50019F001 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9EF4C5991AE2C2C50019F001 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9EF4C5A01AE2C2C50019F001; + remoteInfo = XMPPFrameworkTests; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 9EF4C5A11AE2C2C50019F001 /* XMPPFrameworkTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XMPPFrameworkTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9EF4C5A51AE2C2C50019F001 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9EF4C5A61AE2C2C50019F001 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 9EF4C5A81AE2C2C50019F001 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 9EF4C5A91AE2C2C50019F001 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9EF4C5AB1AE2C2C50019F001 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 9EF4C5AC1AE2C2C50019F001 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 9EF4C5AF1AE2C2C50019F001 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 9EF4C5B11AE2C2C50019F001 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 9EF4C5B41AE2C2C50019F001 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 9EF4C5BA1AE2C2C50019F001 /* XMPPFrameworkTestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XMPPFrameworkTestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 9EF4C5BF1AE2C2C50019F001 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9EF4C5CC1AE2C2F30019F001 /* DDList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDList.h; sourceTree = ""; }; + 9EF4C5CD1AE2C2F30019F001 /* DDList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDList.m; sourceTree = ""; }; + 9EF4C5CE1AE2C2F30019F001 /* GCDMulticastDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDMulticastDelegate.h; sourceTree = ""; }; + 9EF4C5CF1AE2C2F30019F001 /* GCDMulticastDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDMulticastDelegate.m; sourceTree = ""; }; + 9EF4C5D01AE2C2F30019F001 /* RFImageToDataTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RFImageToDataTransformer.h; sourceTree = ""; }; + 9EF4C5D11AE2C2F30019F001 /* RFImageToDataTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RFImageToDataTransformer.m; sourceTree = ""; }; + 9EF4C5D21AE2C2F30019F001 /* XMPPIDTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPIDTracker.h; sourceTree = ""; }; + 9EF4C5D31AE2C2F30019F001 /* XMPPIDTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPIDTracker.m; sourceTree = ""; }; + 9EF4C5D41AE2C2F30019F001 /* XMPPSRVResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSRVResolver.h; sourceTree = ""; }; + 9EF4C5D51AE2C2F30019F001 /* XMPPSRVResolver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSRVResolver.m; sourceTree = ""; }; + 9EF4C5D61AE2C2F30019F001 /* XMPPStringPrep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStringPrep.h; sourceTree = ""; }; + 9EF4C5D71AE2C2F30019F001 /* XMPPStringPrep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStringPrep.m; sourceTree = ""; }; + 9EF4C5D81AE2C2F30019F001 /* XMPPTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPTimer.h; sourceTree = ""; }; + 9EF4C5D91AE2C2F30019F001 /* XMPPTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPTimer.m; sourceTree = ""; }; + 9EF4C6D91AE2C2F30019F001 /* XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPP.h; sourceTree = ""; }; + 9EF4C6DA1AE2C2F30019F001 /* XMPPConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPConstants.h; sourceTree = ""; }; + 9EF4C6DB1AE2C2F30019F001 /* XMPPConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPConstants.m; sourceTree = ""; }; + 9EF4C6DC1AE2C2F30019F001 /* XMPPElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPElement.h; sourceTree = ""; }; + 9EF4C6DD1AE2C2F30019F001 /* XMPPElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPElement.m; sourceTree = ""; }; + 9EF4C6DE1AE2C2F30019F001 /* XMPPInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPInternal.h; sourceTree = ""; }; + 9EF4C6DF1AE2C2F30019F001 /* XMPPIQ.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPIQ.h; sourceTree = ""; }; + 9EF4C6E01AE2C2F30019F001 /* XMPPIQ.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPIQ.m; sourceTree = ""; }; + 9EF4C6E11AE2C2F30019F001 /* XMPPJID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPJID.h; sourceTree = ""; }; + 9EF4C6E21AE2C2F30019F001 /* XMPPJID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPJID.m; sourceTree = ""; }; + 9EF4C6E31AE2C2F30019F001 /* XMPPLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPLogging.h; sourceTree = ""; }; + 9EF4C6E41AE2C2F30019F001 /* XMPPMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPMessage.h; sourceTree = ""; }; + 9EF4C6E51AE2C2F30019F001 /* XMPPMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPMessage.m; sourceTree = ""; }; + 9EF4C6E61AE2C2F30019F001 /* XMPPModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPModule.h; sourceTree = ""; }; + 9EF4C6E71AE2C2F30019F001 /* XMPPModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPModule.m; sourceTree = ""; }; + 9EF4C6E81AE2C2F30019F001 /* XMPPParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPParser.h; sourceTree = ""; }; + 9EF4C6E91AE2C2F30019F001 /* XMPPParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPParser.m; sourceTree = ""; }; + 9EF4C6EA1AE2C2F30019F001 /* XMPPPresence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPresence.h; sourceTree = ""; }; + 9EF4C6EB1AE2C2F30019F001 /* XMPPPresence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPresence.m; sourceTree = ""; }; + 9EF4C6EC1AE2C2F30019F001 /* XMPPStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPStream.h; sourceTree = ""; }; + 9EF4C6ED1AE2C2F30019F001 /* XMPPStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPStream.m; sourceTree = ""; }; + 9EF4C6EF1AE2C2F30019F001 /* NSData+XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+XMPP.h"; sourceTree = ""; }; + 9EF4C6F01AE2C2F30019F001 /* NSData+XMPP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+XMPP.m"; sourceTree = ""; }; + 9EF4C6F11AE2C2F30019F001 /* NSNumber+XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNumber+XMPP.h"; sourceTree = ""; }; + 9EF4C6F21AE2C2F30019F001 /* NSNumber+XMPP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNumber+XMPP.m"; sourceTree = ""; }; + 9EF4C6F31AE2C2F30019F001 /* NSXMLElement+XMPP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSXMLElement+XMPP.h"; sourceTree = ""; }; + 9EF4C6F41AE2C2F30019F001 /* NSXMLElement+XMPP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSXMLElement+XMPP.m"; sourceTree = ""; }; + 9EF4C6F71AE2C2F30019F001 /* XMPPAnonymousAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPAnonymousAuthentication.h; sourceTree = ""; }; + 9EF4C6F81AE2C2F30019F001 /* XMPPAnonymousAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPAnonymousAuthentication.m; sourceTree = ""; }; + 9EF4C6FA1AE2C2F30019F001 /* XMPPDeprecatedDigestAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPDeprecatedDigestAuthentication.h; sourceTree = ""; }; + 9EF4C6FB1AE2C2F30019F001 /* XMPPDeprecatedDigestAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPDeprecatedDigestAuthentication.m; sourceTree = ""; }; + 9EF4C6FD1AE2C2F30019F001 /* XMPPDeprecatedPlainAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPDeprecatedPlainAuthentication.h; sourceTree = ""; }; + 9EF4C6FE1AE2C2F30019F001 /* XMPPDeprecatedPlainAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPDeprecatedPlainAuthentication.m; sourceTree = ""; }; + 9EF4C7001AE2C2F30019F001 /* XMPPDigestMD5Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPDigestMD5Authentication.h; sourceTree = ""; }; + 9EF4C7011AE2C2F30019F001 /* XMPPDigestMD5Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPDigestMD5Authentication.m; sourceTree = ""; }; + 9EF4C7031AE2C2F30019F001 /* XMPPPlainAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPPlainAuthentication.h; sourceTree = ""; }; + 9EF4C7041AE2C2F30019F001 /* XMPPPlainAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPPlainAuthentication.m; sourceTree = ""; }; + 9EF4C7061AE2C2F30019F001 /* XMPPSCRAMSHA1Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSCRAMSHA1Authentication.h; sourceTree = ""; }; + 9EF4C7071AE2C2F30019F001 /* XMPPSCRAMSHA1Authentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPSCRAMSHA1Authentication.m; sourceTree = ""; }; + 9EF4C7091AE2C2F30019F001 /* XMPPXFacebookPlatformAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPXFacebookPlatformAuthentication.h; sourceTree = ""; }; + 9EF4C70A1AE2C2F30019F001 /* XMPPXFacebookPlatformAuthentication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPXFacebookPlatformAuthentication.m; sourceTree = ""; }; + 9EF4C70C1AE2C2F30019F001 /* XMPPXOAuth2Google.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPXOAuth2Google.h; sourceTree = ""; }; + 9EF4C70D1AE2C2F30019F001 /* XMPPXOAuth2Google.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPXOAuth2Google.m; sourceTree = ""; }; + 9EF4C70E1AE2C2F30019F001 /* XMPPCustomBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCustomBinding.h; sourceTree = ""; }; + 9EF4C70F1AE2C2F30019F001 /* XMPPSASLAuthentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPSASLAuthentication.h; sourceTree = ""; }; + 9EF4C7901AE2C3220019F001 /* idn-int.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "idn-int.h"; sourceTree = ""; }; + 9EF4C7921AE2C3220019F001 /* stringprep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stringprep.h; sourceTree = ""; }; + 9EF4C7941AE2C3220019F001 /* DDAbstractDatabaseLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDAbstractDatabaseLogger.h; sourceTree = ""; }; + 9EF4C7951AE2C3220019F001 /* DDAbstractDatabaseLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDAbstractDatabaseLogger.m; sourceTree = ""; }; + 9EF4C7961AE2C3220019F001 /* DDASLLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDASLLogger.h; sourceTree = ""; }; + 9EF4C7971AE2C3220019F001 /* DDASLLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDASLLogger.m; sourceTree = ""; }; + 9EF4C7981AE2C3220019F001 /* DDFileLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDFileLogger.h; sourceTree = ""; }; + 9EF4C7991AE2C3220019F001 /* DDFileLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDFileLogger.m; sourceTree = ""; }; + 9EF4C79A1AE2C3220019F001 /* DDLog+LOGV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DDLog+LOGV.h"; sourceTree = ""; }; + 9EF4C79B1AE2C3220019F001 /* DDLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDLog.h; sourceTree = ""; }; + 9EF4C79C1AE2C3220019F001 /* DDLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDLog.m; sourceTree = ""; }; + 9EF4C79D1AE2C3220019F001 /* DDTTYLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDTTYLogger.h; sourceTree = ""; }; + 9EF4C79E1AE2C3220019F001 /* DDTTYLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDTTYLogger.m; sourceTree = ""; }; + 9EF4C7A01AE2C3220019F001 /* DDContextFilterLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDContextFilterLogFormatter.h; sourceTree = ""; }; + 9EF4C7A11AE2C3220019F001 /* DDContextFilterLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDContextFilterLogFormatter.m; sourceTree = ""; }; + 9EF4C7A21AE2C3220019F001 /* DDDispatchQueueLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDDispatchQueueLogFormatter.h; sourceTree = ""; }; + 9EF4C7A31AE2C3220019F001 /* DDDispatchQueueLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDDispatchQueueLogFormatter.m; sourceTree = ""; }; + 9EF4C7A41AE2C3220019F001 /* DDMultiFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDMultiFormatter.h; sourceTree = ""; }; + 9EF4C7A51AE2C3220019F001 /* DDMultiFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDMultiFormatter.m; sourceTree = ""; }; + 9EF4C7A61AE2C3220019F001 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; + 9EF4C7A81AE2C3220019F001 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = ""; }; + 9EF4C7A91AE2C3220019F001 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = ""; }; + 9EF4C7B81AE2C39F0019F001 /* NSString+DDXML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+DDXML.h"; sourceTree = ""; }; + 9EF4C7B91AE2C39F0019F001 /* NSString+DDXML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+DDXML.m"; sourceTree = ""; }; + 9EF4C7BA1AE2C39F0019F001 /* DDXML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDXML.h; sourceTree = ""; }; + 9EF4C7BB1AE2C39F0019F001 /* DDXMLDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDXMLDocument.h; sourceTree = ""; }; + 9EF4C7BC1AE2C39F0019F001 /* DDXMLDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDXMLDocument.m; sourceTree = ""; }; + 9EF4C7BD1AE2C39F0019F001 /* DDXMLElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDXMLElement.h; sourceTree = ""; }; + 9EF4C7BE1AE2C39F0019F001 /* DDXMLElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDXMLElement.m; sourceTree = ""; }; + 9EF4C7BF1AE2C39F0019F001 /* DDXMLNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDXMLNode.h; sourceTree = ""; }; + 9EF4C7C01AE2C39F0019F001 /* DDXMLNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDXMLNode.m; sourceTree = ""; }; + 9EF4C7C21AE2C39F0019F001 /* DDXMLPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDXMLPrivate.h; sourceTree = ""; }; + 9EF4C7C71AE2C3B70019F001 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; }; + 9EF4C7C91AE2C4320019F001 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 9EF4C7CB1AE2C43F0019F001 /* libidn.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libidn.a; path = ../../../Vendor/libidn/libidn.a; sourceTree = ""; }; + 9EF4C7CD1AE2C4480019F001 /* libresolv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libresolv.dylib; path = usr/lib/libresolv.dylib; sourceTree = SDKROOT; }; + 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncodeDecodeTest.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9EF4C59E1AE2C2C50019F001 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EF4C7CE1AE2C4480019F001 /* libresolv.dylib in Frameworks */, + 9EF4C7CC1AE2C43F0019F001 /* libidn.a in Frameworks */, + 9EF4C7CA1AE2C4320019F001 /* Security.framework in Frameworks */, + 9EF4C7C81AE2C3B70019F001 /* libxml2.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9EF4C5B71AE2C2C50019F001 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9EF4C5981AE2C2C50019F001 = { + isa = PBXGroup; + children = ( + 9EF4C7CD1AE2C4480019F001 /* libresolv.dylib */, + 9EF4C7CB1AE2C43F0019F001 /* libidn.a */, + 9EF4C7C91AE2C4320019F001 /* Security.framework */, + 9EF4C7C71AE2C3B70019F001 /* libxml2.dylib */, + 9EF4C5CA1AE2C2D60019F001 /* XMPPFramework */, + 9EF4C5A31AE2C2C50019F001 /* XMPPFrameworkTests */, + 9EF4C5BD1AE2C2C50019F001 /* XMPPFrameworkTestsTests */, + 9EF4C5A21AE2C2C50019F001 /* Products */, + ); + sourceTree = ""; + }; + 9EF4C5A21AE2C2C50019F001 /* Products */ = { + isa = PBXGroup; + children = ( + 9EF4C5A11AE2C2C50019F001 /* XMPPFrameworkTests.app */, + 9EF4C5BA1AE2C2C50019F001 /* XMPPFrameworkTestsTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 9EF4C5A31AE2C2C50019F001 /* XMPPFrameworkTests */ = { + isa = PBXGroup; + children = ( + 9EF4C5A81AE2C2C50019F001 /* AppDelegate.h */, + 9EF4C5A91AE2C2C50019F001 /* AppDelegate.m */, + 9EF4C5AB1AE2C2C50019F001 /* ViewController.h */, + 9EF4C5AC1AE2C2C50019F001 /* ViewController.m */, + 9EF4C5AE1AE2C2C50019F001 /* Main.storyboard */, + 9EF4C5B11AE2C2C50019F001 /* Images.xcassets */, + 9EF4C5B31AE2C2C50019F001 /* LaunchScreen.xib */, + 9EF4C5A41AE2C2C50019F001 /* Supporting Files */, + ); + path = XMPPFrameworkTests; + sourceTree = ""; + }; + 9EF4C5A41AE2C2C50019F001 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9EF4C5A51AE2C2C50019F001 /* Info.plist */, + 9EF4C5A61AE2C2C50019F001 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 9EF4C5BD1AE2C2C50019F001 /* XMPPFrameworkTestsTests */ = { + isa = PBXGroup; + children = ( + 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */, + 9EF4C5BE1AE2C2C50019F001 /* Supporting Files */, + ); + path = XMPPFrameworkTestsTests; + sourceTree = ""; + }; + 9EF4C5BE1AE2C2C50019F001 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9EF4C5BF1AE2C2C50019F001 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 9EF4C5CA1AE2C2D60019F001 /* XMPPFramework */ = { + isa = PBXGroup; + children = ( + 9EF4C78D1AE2C3040019F001 /* Vendor */, + 9EF4C5CB1AE2C2F30019F001 /* Utilities */, + 9EF4C6D81AE2C2F30019F001 /* Core */, + 9EF4C6EE1AE2C2F30019F001 /* Categories */, + 9EF4C6F51AE2C2F30019F001 /* Authentication */, + ); + name = XMPPFramework; + path = ../../..; + sourceTree = ""; + }; + 9EF4C5CB1AE2C2F30019F001 /* Utilities */ = { + isa = PBXGroup; + children = ( + 9EF4C5CC1AE2C2F30019F001 /* DDList.h */, + 9EF4C5CD1AE2C2F30019F001 /* DDList.m */, + 9EF4C5CE1AE2C2F30019F001 /* GCDMulticastDelegate.h */, + 9EF4C5CF1AE2C2F30019F001 /* GCDMulticastDelegate.m */, + 9EF4C5D01AE2C2F30019F001 /* RFImageToDataTransformer.h */, + 9EF4C5D11AE2C2F30019F001 /* RFImageToDataTransformer.m */, + 9EF4C5D21AE2C2F30019F001 /* XMPPIDTracker.h */, + 9EF4C5D31AE2C2F30019F001 /* XMPPIDTracker.m */, + 9EF4C5D41AE2C2F30019F001 /* XMPPSRVResolver.h */, + 9EF4C5D51AE2C2F30019F001 /* XMPPSRVResolver.m */, + 9EF4C5D61AE2C2F30019F001 /* XMPPStringPrep.h */, + 9EF4C5D71AE2C2F30019F001 /* XMPPStringPrep.m */, + 9EF4C5D81AE2C2F30019F001 /* XMPPTimer.h */, + 9EF4C5D91AE2C2F30019F001 /* XMPPTimer.m */, + ); + path = Utilities; + sourceTree = ""; + }; + 9EF4C6D81AE2C2F30019F001 /* Core */ = { + isa = PBXGroup; + children = ( + 9EF4C6D91AE2C2F30019F001 /* XMPP.h */, + 9EF4C6DA1AE2C2F30019F001 /* XMPPConstants.h */, + 9EF4C6DB1AE2C2F30019F001 /* XMPPConstants.m */, + 9EF4C6DC1AE2C2F30019F001 /* XMPPElement.h */, + 9EF4C6DD1AE2C2F30019F001 /* XMPPElement.m */, + 9EF4C6DE1AE2C2F30019F001 /* XMPPInternal.h */, + 9EF4C6DF1AE2C2F30019F001 /* XMPPIQ.h */, + 9EF4C6E01AE2C2F30019F001 /* XMPPIQ.m */, + 9EF4C6E11AE2C2F30019F001 /* XMPPJID.h */, + 9EF4C6E21AE2C2F30019F001 /* XMPPJID.m */, + 9EF4C6E31AE2C2F30019F001 /* XMPPLogging.h */, + 9EF4C6E41AE2C2F30019F001 /* XMPPMessage.h */, + 9EF4C6E51AE2C2F30019F001 /* XMPPMessage.m */, + 9EF4C6E61AE2C2F30019F001 /* XMPPModule.h */, + 9EF4C6E71AE2C2F30019F001 /* XMPPModule.m */, + 9EF4C6E81AE2C2F30019F001 /* XMPPParser.h */, + 9EF4C6E91AE2C2F30019F001 /* XMPPParser.m */, + 9EF4C6EA1AE2C2F30019F001 /* XMPPPresence.h */, + 9EF4C6EB1AE2C2F30019F001 /* XMPPPresence.m */, + 9EF4C6EC1AE2C2F30019F001 /* XMPPStream.h */, + 9EF4C6ED1AE2C2F30019F001 /* XMPPStream.m */, + ); + path = Core; + sourceTree = ""; + }; + 9EF4C6EE1AE2C2F30019F001 /* Categories */ = { + isa = PBXGroup; + children = ( + 9EF4C6EF1AE2C2F30019F001 /* NSData+XMPP.h */, + 9EF4C6F01AE2C2F30019F001 /* NSData+XMPP.m */, + 9EF4C6F11AE2C2F30019F001 /* NSNumber+XMPP.h */, + 9EF4C6F21AE2C2F30019F001 /* NSNumber+XMPP.m */, + 9EF4C6F31AE2C2F30019F001 /* NSXMLElement+XMPP.h */, + 9EF4C6F41AE2C2F30019F001 /* NSXMLElement+XMPP.m */, + ); + path = Categories; + sourceTree = ""; + }; + 9EF4C6F51AE2C2F30019F001 /* Authentication */ = { + isa = PBXGroup; + children = ( + 9EF4C6F61AE2C2F30019F001 /* Anonymous */, + 9EF4C6F91AE2C2F30019F001 /* Deprecated-Digest */, + 9EF4C6FC1AE2C2F30019F001 /* Deprecated-Plain */, + 9EF4C6FF1AE2C2F30019F001 /* Digest-MD5 */, + 9EF4C7021AE2C2F30019F001 /* Plain */, + 9EF4C7051AE2C2F30019F001 /* SCRAM-SHA-1 */, + 9EF4C7081AE2C2F30019F001 /* X-Facebook-Platform */, + 9EF4C70B1AE2C2F30019F001 /* X-OAuth2-Google */, + 9EF4C70E1AE2C2F30019F001 /* XMPPCustomBinding.h */, + 9EF4C70F1AE2C2F30019F001 /* XMPPSASLAuthentication.h */, + ); + path = Authentication; + sourceTree = ""; + }; + 9EF4C6F61AE2C2F30019F001 /* Anonymous */ = { + isa = PBXGroup; + children = ( + 9EF4C6F71AE2C2F30019F001 /* XMPPAnonymousAuthentication.h */, + 9EF4C6F81AE2C2F30019F001 /* XMPPAnonymousAuthentication.m */, + ); + path = Anonymous; + sourceTree = ""; + }; + 9EF4C6F91AE2C2F30019F001 /* Deprecated-Digest */ = { + isa = PBXGroup; + children = ( + 9EF4C6FA1AE2C2F30019F001 /* XMPPDeprecatedDigestAuthentication.h */, + 9EF4C6FB1AE2C2F30019F001 /* XMPPDeprecatedDigestAuthentication.m */, + ); + path = "Deprecated-Digest"; + sourceTree = ""; + }; + 9EF4C6FC1AE2C2F30019F001 /* Deprecated-Plain */ = { + isa = PBXGroup; + children = ( + 9EF4C6FD1AE2C2F30019F001 /* XMPPDeprecatedPlainAuthentication.h */, + 9EF4C6FE1AE2C2F30019F001 /* XMPPDeprecatedPlainAuthentication.m */, + ); + path = "Deprecated-Plain"; + sourceTree = ""; + }; + 9EF4C6FF1AE2C2F30019F001 /* Digest-MD5 */ = { + isa = PBXGroup; + children = ( + 9EF4C7001AE2C2F30019F001 /* XMPPDigestMD5Authentication.h */, + 9EF4C7011AE2C2F30019F001 /* XMPPDigestMD5Authentication.m */, + ); + path = "Digest-MD5"; + sourceTree = ""; + }; + 9EF4C7021AE2C2F30019F001 /* Plain */ = { + isa = PBXGroup; + children = ( + 9EF4C7031AE2C2F30019F001 /* XMPPPlainAuthentication.h */, + 9EF4C7041AE2C2F30019F001 /* XMPPPlainAuthentication.m */, + ); + path = Plain; + sourceTree = ""; + }; + 9EF4C7051AE2C2F30019F001 /* SCRAM-SHA-1 */ = { + isa = PBXGroup; + children = ( + 9EF4C7061AE2C2F30019F001 /* XMPPSCRAMSHA1Authentication.h */, + 9EF4C7071AE2C2F30019F001 /* XMPPSCRAMSHA1Authentication.m */, + ); + path = "SCRAM-SHA-1"; + sourceTree = ""; + }; + 9EF4C7081AE2C2F30019F001 /* X-Facebook-Platform */ = { + isa = PBXGroup; + children = ( + 9EF4C7091AE2C2F30019F001 /* XMPPXFacebookPlatformAuthentication.h */, + 9EF4C70A1AE2C2F30019F001 /* XMPPXFacebookPlatformAuthentication.m */, + ); + path = "X-Facebook-Platform"; + sourceTree = ""; + }; + 9EF4C70B1AE2C2F30019F001 /* X-OAuth2-Google */ = { + isa = PBXGroup; + children = ( + 9EF4C70C1AE2C2F30019F001 /* XMPPXOAuth2Google.h */, + 9EF4C70D1AE2C2F30019F001 /* XMPPXOAuth2Google.m */, + ); + path = "X-OAuth2-Google"; + sourceTree = ""; + }; + 9EF4C78D1AE2C3040019F001 /* Vendor */ = { + isa = PBXGroup; + children = ( + 9EF4C7B61AE2C39F0019F001 /* KissXML */, + 9EF4C78E1AE2C3220019F001 /* libidn */, + 9EF4C7931AE2C3220019F001 /* CocoaLumberjack */, + 9EF4C7A71AE2C3220019F001 /* CocoaAsyncSocket */, + ); + path = Vendor; + sourceTree = ""; + }; + 9EF4C78E1AE2C3220019F001 /* libidn */ = { + isa = PBXGroup; + children = ( + 9EF4C7901AE2C3220019F001 /* idn-int.h */, + 9EF4C7921AE2C3220019F001 /* stringprep.h */, + ); + path = libidn; + sourceTree = ""; + }; + 9EF4C7931AE2C3220019F001 /* CocoaLumberjack */ = { + isa = PBXGroup; + children = ( + 9EF4C7941AE2C3220019F001 /* DDAbstractDatabaseLogger.h */, + 9EF4C7951AE2C3220019F001 /* DDAbstractDatabaseLogger.m */, + 9EF4C7961AE2C3220019F001 /* DDASLLogger.h */, + 9EF4C7971AE2C3220019F001 /* DDASLLogger.m */, + 9EF4C7981AE2C3220019F001 /* DDFileLogger.h */, + 9EF4C7991AE2C3220019F001 /* DDFileLogger.m */, + 9EF4C79A1AE2C3220019F001 /* DDLog+LOGV.h */, + 9EF4C79B1AE2C3220019F001 /* DDLog.h */, + 9EF4C79C1AE2C3220019F001 /* DDLog.m */, + 9EF4C79D1AE2C3220019F001 /* DDTTYLogger.h */, + 9EF4C79E1AE2C3220019F001 /* DDTTYLogger.m */, + 9EF4C79F1AE2C3220019F001 /* Extensions */, + ); + path = CocoaLumberjack; + sourceTree = ""; + }; + 9EF4C79F1AE2C3220019F001 /* Extensions */ = { + isa = PBXGroup; + children = ( + 9EF4C7A01AE2C3220019F001 /* DDContextFilterLogFormatter.h */, + 9EF4C7A11AE2C3220019F001 /* DDContextFilterLogFormatter.m */, + 9EF4C7A21AE2C3220019F001 /* DDDispatchQueueLogFormatter.h */, + 9EF4C7A31AE2C3220019F001 /* DDDispatchQueueLogFormatter.m */, + 9EF4C7A41AE2C3220019F001 /* DDMultiFormatter.h */, + 9EF4C7A51AE2C3220019F001 /* DDMultiFormatter.m */, + 9EF4C7A61AE2C3220019F001 /* README.txt */, + ); + path = Extensions; + sourceTree = ""; + }; + 9EF4C7A71AE2C3220019F001 /* CocoaAsyncSocket */ = { + isa = PBXGroup; + children = ( + 9EF4C7A81AE2C3220019F001 /* GCDAsyncSocket.h */, + 9EF4C7A91AE2C3220019F001 /* GCDAsyncSocket.m */, + ); + path = CocoaAsyncSocket; + sourceTree = ""; + }; + 9EF4C7B61AE2C39F0019F001 /* KissXML */ = { + isa = PBXGroup; + children = ( + 9EF4C7B71AE2C39F0019F001 /* Categories */, + 9EF4C7BA1AE2C39F0019F001 /* DDXML.h */, + 9EF4C7BB1AE2C39F0019F001 /* DDXMLDocument.h */, + 9EF4C7BC1AE2C39F0019F001 /* DDXMLDocument.m */, + 9EF4C7BD1AE2C39F0019F001 /* DDXMLElement.h */, + 9EF4C7BE1AE2C39F0019F001 /* DDXMLElement.m */, + 9EF4C7BF1AE2C39F0019F001 /* DDXMLNode.h */, + 9EF4C7C01AE2C39F0019F001 /* DDXMLNode.m */, + 9EF4C7C11AE2C39F0019F001 /* Private */, + ); + path = KissXML; + sourceTree = ""; + }; + 9EF4C7B71AE2C39F0019F001 /* Categories */ = { + isa = PBXGroup; + children = ( + 9EF4C7B81AE2C39F0019F001 /* NSString+DDXML.h */, + 9EF4C7B91AE2C39F0019F001 /* NSString+DDXML.m */, + ); + path = Categories; + sourceTree = ""; + }; + 9EF4C7C11AE2C39F0019F001 /* Private */ = { + isa = PBXGroup; + children = ( + 9EF4C7C21AE2C39F0019F001 /* DDXMLPrivate.h */, + ); + path = Private; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9EF4C5A01AE2C2C50019F001 /* XMPPFrameworkTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9EF4C5C41AE2C2C50019F001 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTests" */; + buildPhases = ( + 9EF4C59D1AE2C2C50019F001 /* Sources */, + 9EF4C59E1AE2C2C50019F001 /* Frameworks */, + 9EF4C59F1AE2C2C50019F001 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = XMPPFrameworkTests; + productName = XMPPFrameworkTests; + productReference = 9EF4C5A11AE2C2C50019F001 /* XMPPFrameworkTests.app */; + productType = "com.apple.product-type.application"; + }; + 9EF4C5B91AE2C2C50019F001 /* XMPPFrameworkTestsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9EF4C5C71AE2C2C50019F001 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTestsTests" */; + buildPhases = ( + 9EF4C5B61AE2C2C50019F001 /* Sources */, + 9EF4C5B71AE2C2C50019F001 /* Frameworks */, + 9EF4C5B81AE2C2C50019F001 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 9EF4C5BC1AE2C2C50019F001 /* PBXTargetDependency */, + ); + name = XMPPFrameworkTestsTests; + productName = XMPPFrameworkTestsTests; + productReference = 9EF4C5BA1AE2C2C50019F001 /* XMPPFrameworkTestsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9EF4C5991AE2C2C50019F001 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Paul Melnikow"; + TargetAttributes = { + 9EF4C5A01AE2C2C50019F001 = { + CreatedOnToolsVersion = 6.3; + }; + 9EF4C5B91AE2C2C50019F001 = { + CreatedOnToolsVersion = 6.3; + TestTargetID = 9EF4C5A01AE2C2C50019F001; + }; + }; + }; + buildConfigurationList = 9EF4C59C1AE2C2C50019F001 /* Build configuration list for PBXProject "XMPPFrameworkTests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 9EF4C5981AE2C2C50019F001; + productRefGroup = 9EF4C5A21AE2C2C50019F001 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9EF4C5A01AE2C2C50019F001 /* XMPPFrameworkTests */, + 9EF4C5B91AE2C2C50019F001 /* XMPPFrameworkTestsTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9EF4C59F1AE2C2C50019F001 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EF4C5B01AE2C2C50019F001 /* Main.storyboard in Resources */, + 9EF4C5B51AE2C2C50019F001 /* LaunchScreen.xib in Resources */, + 9EF4C5B21AE2C2C50019F001 /* Images.xcassets in Resources */, + 9EF4C7B41AE2C3220019F001 /* README.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9EF4C5B81AE2C2C50019F001 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9EF4C59D1AE2C2C50019F001 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EF4C7821AE2C2F30019F001 /* NSData+XMPP.m in Sources */, + 9EF4C7851AE2C2F30019F001 /* XMPPAnonymousAuthentication.m in Sources */, + 9EF4C77D1AE2C2F30019F001 /* XMPPMessage.m in Sources */, + 9EF4C78B1AE2C2F30019F001 /* XMPPXFacebookPlatformAuthentication.m in Sources */, + 9EF4C7161AE2C2F30019F001 /* XMPPTimer.m in Sources */, + 9EF4C7121AE2C2F30019F001 /* RFImageToDataTransformer.m in Sources */, + 9EF4C7151AE2C2F30019F001 /* XMPPStringPrep.m in Sources */, + 9EF4C7791AE2C2F30019F001 /* XMPPConstants.m in Sources */, + 9EF4C7C51AE2C39F0019F001 /* DDXMLElement.m in Sources */, + 9EF4C7C61AE2C39F0019F001 /* DDXMLNode.m in Sources */, + 9EF4C7B21AE2C3220019F001 /* DDDispatchQueueLogFormatter.m in Sources */, + 9EF4C77E1AE2C2F30019F001 /* XMPPModule.m in Sources */, + 9EF4C5AD1AE2C2C50019F001 /* ViewController.m in Sources */, + 9EF4C7811AE2C2F30019F001 /* XMPPStream.m in Sources */, + 9EF4C78C1AE2C2F30019F001 /* XMPPXOAuth2Google.m in Sources */, + 9EF4C7AF1AE2C3220019F001 /* DDLog.m in Sources */, + 9EF4C7841AE2C2F30019F001 /* NSXMLElement+XMPP.m in Sources */, + 9EF4C7131AE2C2F30019F001 /* XMPPIDTracker.m in Sources */, + 9EF4C77C1AE2C2F30019F001 /* XMPPJID.m in Sources */, + 9EF4C5AA1AE2C2C50019F001 /* AppDelegate.m in Sources */, + 9EF4C5A71AE2C2C50019F001 /* main.m in Sources */, + 9EF4C7AC1AE2C3220019F001 /* DDAbstractDatabaseLogger.m in Sources */, + 9EF4C7101AE2C2F30019F001 /* DDList.m in Sources */, + 9EF4C7881AE2C2F30019F001 /* XMPPDigestMD5Authentication.m in Sources */, + 9EF4C7C41AE2C39F0019F001 /* DDXMLDocument.m in Sources */, + 9EF4C7891AE2C2F30019F001 /* XMPPPlainAuthentication.m in Sources */, + 9EF4C77B1AE2C2F30019F001 /* XMPPIQ.m in Sources */, + 9EF4C7141AE2C2F30019F001 /* XMPPSRVResolver.m in Sources */, + 9EF4C77F1AE2C2F30019F001 /* XMPPParser.m in Sources */, + 9EF4C7B01AE2C3220019F001 /* DDTTYLogger.m in Sources */, + 9EF4C7111AE2C2F30019F001 /* GCDMulticastDelegate.m in Sources */, + 9EF4C7861AE2C2F30019F001 /* XMPPDeprecatedDigestAuthentication.m in Sources */, + 9EF4C7AD1AE2C3220019F001 /* DDASLLogger.m in Sources */, + 9EF4C7831AE2C2F30019F001 /* NSNumber+XMPP.m in Sources */, + 9EF4C7871AE2C2F30019F001 /* XMPPDeprecatedPlainAuthentication.m in Sources */, + 9EF4C77A1AE2C2F30019F001 /* XMPPElement.m in Sources */, + 9EF4C7B11AE2C3220019F001 /* DDContextFilterLogFormatter.m in Sources */, + 9EF4C7B51AE2C3220019F001 /* GCDAsyncSocket.m in Sources */, + 9EF4C7B31AE2C3220019F001 /* DDMultiFormatter.m in Sources */, + 9EF4C78A1AE2C2F30019F001 /* XMPPSCRAMSHA1Authentication.m in Sources */, + 9EF4C7801AE2C2F30019F001 /* XMPPPresence.m in Sources */, + 9EF4C7AE1AE2C3220019F001 /* DDFileLogger.m in Sources */, + 9EF4C7C31AE2C39F0019F001 /* NSString+DDXML.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9EF4C5B61AE2C2C50019F001 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EF4C7D31AE2C4CC0019F001 /* EncodeDecodeTest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 9EF4C5BC1AE2C2C50019F001 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9EF4C5A01AE2C2C50019F001 /* XMPPFrameworkTests */; + targetProxy = 9EF4C5BB1AE2C2C50019F001 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 9EF4C5AE1AE2C2C50019F001 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 9EF4C5AF1AE2C2C50019F001 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 9EF4C5B31AE2C2C50019F001 /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 9EF4C5B41AE2C2C50019F001 /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9EF4C5C21AE2C2C50019F001 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "/usr/include/libxml2/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 9EF4C5C31AE2C2C50019F001 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "/usr/include/libxml2/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 9EF4C5C51AE2C2C50019F001 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = XMPPFrameworkTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /Users/pnm/code/XMPPFramework/Vendor/libidn, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 9EF4C5C61AE2C2C50019F001 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = XMPPFrameworkTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /Users/pnm/code/XMPPFramework/Vendor/libidn, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 9EF4C5C81AE2C2C50019F001 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = XMPPFrameworkTestsTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XMPPFrameworkTests.app/XMPPFrameworkTests"; + }; + name = Debug; + }; + 9EF4C5C91AE2C2C50019F001 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = XMPPFrameworkTestsTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XMPPFrameworkTests.app/XMPPFrameworkTests"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9EF4C59C1AE2C2C50019F001 /* Build configuration list for PBXProject "XMPPFrameworkTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9EF4C5C21AE2C2C50019F001 /* Debug */, + 9EF4C5C31AE2C2C50019F001 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9EF4C5C41AE2C2C50019F001 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9EF4C5C51AE2C2C50019F001 /* Debug */, + 9EF4C5C61AE2C2C50019F001 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 9EF4C5C71AE2C2C50019F001 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTestsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9EF4C5C81AE2C2C50019F001 /* Debug */, + 9EF4C5C91AE2C2C50019F001 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9EF4C5991AE2C2C50019F001 /* Project object */; +} diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/AppDelegate.h b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/AppDelegate.h new file mode 100644 index 0000000000..15b698c63f --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// XMPPFrameworkTests +// +// Created by Paul Melnikow on 4/18/15. +// Copyright (c) 2015 Paul Melnikow. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/AppDelegate.m b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/AppDelegate.m new file mode 100644 index 0000000000..921371f83e --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/AppDelegate.m @@ -0,0 +1,45 @@ +// +// AppDelegate.m +// XMPPFrameworkTests +// +// Created by Paul Melnikow on 4/18/15. +// Copyright (c) 2015 Paul Melnikow. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Base.lproj/LaunchScreen.xib b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000000..d102f6a5c8 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Base.lproj/LaunchScreen.xib @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Base.lproj/Main.storyboard b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..d912f9d76b --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Images.xcassets/AppIcon.appiconset/Contents.json b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..118c98f746 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Info.plist b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Info.plist new file mode 100644 index 0000000000..244f3a2fe5 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.paulmelnikow.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/ViewController.h b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/ViewController.h new file mode 100644 index 0000000000..91dedfa9dd --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/ViewController.h @@ -0,0 +1,15 @@ +// +// ViewController.h +// XMPPFrameworkTests +// +// Created by Paul Melnikow on 4/18/15. +// Copyright (c) 2015 Paul Melnikow. All rights reserved. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/ViewController.m b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/ViewController.m new file mode 100644 index 0000000000..21b16aafbf --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/ViewController.m @@ -0,0 +1,27 @@ +// +// ViewController.m +// XMPPFrameworkTests +// +// Created by Paul Melnikow on 4/18/15. +// Copyright (c) 2015 Paul Melnikow. All rights reserved. +// + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/main.m b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/main.m new file mode 100644 index 0000000000..f0244a1705 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests/main.m @@ -0,0 +1,16 @@ +// +// main.m +// XMPPFrameworkTests +// +// Created by Paul Melnikow on 4/18/15. +// Copyright (c) 2015 Paul Melnikow. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/EncodeDecodeTest.m b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/EncodeDecodeTest.m new file mode 100644 index 0000000000..01ff93da72 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/EncodeDecodeTest.m @@ -0,0 +1,101 @@ +// +// EncodeDecodeTest.m +// XMPPFrameworkTests +// +// Created by Paul Melnikow on 4/18/15. +// Copyright (c) 2015 Paul Melnikow. All rights reserved. +// + +#import +#import +#import "XMPPJID.h" +#import "XMPPElement.h" +#import "XMPPIQ.h" +#import "XMPPMessage.h" +#import "XMPPPresence.h" + +@interface EncodeDecodeTest : XCTestCase + +@end + +@implementation EncodeDecodeTest + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testCopy +{ + XMPPJID *jid1 = [XMPPJID jidWithString:@"user@domain.com/resource"]; + XMPPJID *jid2 = [jid1 copy]; + + XCTAssert([jid1 isKindOfClass:[XMPPJID class]], @"A1"); + XCTAssert([jid2 isKindOfClass:[XMPPJID class]], @"A2"); + + XMPPIQ *iq1 = [XMPPIQ iqWithType:@"get" to:jid1 elementID:@"abc123"]; + XMPPIQ *iq2 = [iq1 copy]; + + XCTAssert([iq1 isKindOfClass:[XMPPIQ class]], @"B1"); + XCTAssert([iq2 isKindOfClass:[XMPPIQ class]], @"B2"); + + XMPPMessage *message1 = [XMPPMessage messageWithType:@"chat" to:jid1]; + XMPPMessage *message2 = [message1 copy]; + + XCTAssert([message1 isKindOfClass:[XMPPMessage class]], @"C1"); + XCTAssert([message2 isKindOfClass:[XMPPMessage class]], @"C2"); + + XMPPPresence *presence1 = [XMPPPresence presenceWithType:@"subscribe" to:jid1]; + XMPPPresence *presence2 = [presence1 copy]; + + XCTAssert([presence1 isKindOfClass:[XMPPPresence class]], @"D1"); + XCTAssert([presence2 isKindOfClass:[XMPPPresence class]], @"D2"); +} + +- (void)testArchive +{ + NSMutableDictionary *dict1 = [NSMutableDictionary dictionaryWithCapacity:4]; + + XMPPJID *jid1 = [XMPPJID jidWithString:@"user@domain.com/resource"]; + [dict1 setObject:jid1 forKey:@"jid"]; + + XMPPIQ *iq1 = [XMPPIQ iqWithType:@"get" to:jid1 elementID:@"abc123"]; + [dict1 setObject:iq1 forKey:@"iq"]; + + XMPPMessage *message1 = [XMPPMessage messageWithType:@"chat" to:jid1]; + [dict1 setObject:message1 forKey:@"message"]; + + XMPPPresence *presence1 = [XMPPPresence presenceWithType:@"subscribe" to:jid1]; + [dict1 setObject:presence1 forKey:@"presence"]; + + NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:dict1]; + + NSDictionary *dict2 = [NSKeyedUnarchiver unarchiveObjectWithData:archive]; + + XMPPJID *jid2 = [dict2 objectForKey:@"jid"]; + + XCTAssert([jid1 isKindOfClass:[XMPPJID class]], @"A1"); + XCTAssert([jid2 isKindOfClass:[XMPPJID class]], @"A2"); + + XMPPIQ *iq2 = [dict2 objectForKey:@"iq"]; + + XCTAssert([iq1 isKindOfClass:[XMPPIQ class]], @"B1"); + XCTAssert([iq2 isKindOfClass:[XMPPIQ class]], @"B2"); + + XMPPMessage *message2 = [dict2 objectForKey:@"message"]; + + XCTAssert([message1 isKindOfClass:[XMPPMessage class]], @"C1"); + XCTAssert([message2 isKindOfClass:[XMPPMessage class]], @"C2"); + + XMPPPresence *presence2 = [dict2 objectForKey:@"presence"]; + + XCTAssert([presence1 isKindOfClass:[XMPPPresence class]], @"D1"); + XCTAssert([presence2 isKindOfClass:[XMPPPresence class]], @"D2"); +} + +@end diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/Info.plist b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/Info.plist new file mode 100644 index 0000000000..ee7e3c0293 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.paulmelnikow.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + From 64859d1d12cf1215a9129e6f2254ea7be579baff Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Sat, 18 Apr 2015 14:23:31 -0400 Subject: [PATCH 022/356] Rewrite MulticastDelegateTest --- .gitignore | 1 + Xcode/Testing2/Podfile | 13 ++ .../contents.xcworkspacedata | 10 + .../XMPPFrameworkTests.xccheckout | 41 ++++ .../project.pbxproj | 67 ++++++ .../MulticastDelegateTest.m | 209 ++++++++++++++++++ 6 files changed, 341 insertions(+) create mode 100644 Xcode/Testing2/Podfile create mode 100644 Xcode/Testing2/XMPPFrameworkTests.xcworkspace/contents.xcworkspacedata create mode 100644 Xcode/Testing2/XMPPFrameworkTests.xcworkspace/xcshareddata/XMPPFrameworkTests.xccheckout create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/MulticastDelegateTest.m diff --git a/.gitignore b/.gitignore index 717f4b1953..4cd7317f1b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ xcuserdata .DS_Store project.xcworkspace .idea +Xcode/Testing2/Pods diff --git a/Xcode/Testing2/Podfile b/Xcode/Testing2/Podfile new file mode 100644 index 0000000000..b0f6a7c81a --- /dev/null +++ b/Xcode/Testing2/Podfile @@ -0,0 +1,13 @@ +xcodeproj 'XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj' + +# Uncomment this line to define a global platform for your project +# platform :ios, '6.0' + +target 'XMPPFrameworkTests' do + +end + +target 'XMPPFrameworkTestsTests' do + pod 'OCMock', '~> 3.1' +end + diff --git a/Xcode/Testing2/XMPPFrameworkTests.xcworkspace/contents.xcworkspacedata b/Xcode/Testing2/XMPPFrameworkTests.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..ba4be33bb8 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Xcode/Testing2/XMPPFrameworkTests.xcworkspace/xcshareddata/XMPPFrameworkTests.xccheckout b/Xcode/Testing2/XMPPFrameworkTests.xcworkspace/xcshareddata/XMPPFrameworkTests.xccheckout new file mode 100644 index 0000000000..cb3ab73fba --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests.xcworkspace/xcshareddata/XMPPFrameworkTests.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 027F606B-7E74-433B-B0DE-C179ACF6846D + IDESourceControlProjectName + XMPPFrameworkTests + IDESourceControlProjectOriginsDictionary + + B775552D1BBEEADC6A0BBB2FD048B6AA26CB309D + github.com:paulmelnikow/XMPPFramework.git + + IDESourceControlProjectPath + Xcode/Testing2/XMPPFrameworkTests.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + B775552D1BBEEADC6A0BBB2FD048B6AA26CB309D + ../../.. + + IDESourceControlProjectURL + github.com:paulmelnikow/XMPPFramework.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + B775552D1BBEEADC6A0BBB2FD048B6AA26CB309D + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + B775552D1BBEEADC6A0BBB2FD048B6AA26CB309D + IDESourceControlWCCName + XMPPFramework + + + + diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj index 689f18b494..8eea359395 100644 --- a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 90F596D50A8AB2CD874C400D /* libPods-XMPPFrameworkTestsTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E12FE78966D1CF605B0A4F20 /* libPods-XMPPFrameworkTestsTests.a */; }; 9EF4C5A71AE2C2C50019F001 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5A61AE2C2C50019F001 /* main.m */; }; 9EF4C5AA1AE2C2C50019F001 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5A91AE2C2C50019F001 /* AppDelegate.m */; }; 9EF4C5AD1AE2C2C50019F001 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5AC1AE2C2C50019F001 /* ViewController.m */; }; @@ -59,6 +60,7 @@ 9EF4C7CC1AE2C43F0019F001 /* libidn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C7CB1AE2C43F0019F001 /* libidn.a */; }; 9EF4C7CE1AE2C4480019F001 /* libresolv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C7CD1AE2C4480019F001 /* libresolv.dylib */; }; 9EF4C7D31AE2C4CC0019F001 /* EncodeDecodeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */; }; + 9EF4C7D51AE2C6100019F001 /* MulticastDelegateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7D41AE2C6100019F001 /* MulticastDelegateTest.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -72,6 +74,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 76C6AF82FDDA755AC643FD84 /* Pods-XMPPFrameworkTestsTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFrameworkTestsTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-XMPPFrameworkTestsTests/Pods-XMPPFrameworkTestsTests.release.xcconfig"; sourceTree = ""; }; + 9508FAAF7823E030E62A713C /* Pods-XMPPFrameworkTestsTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFrameworkTestsTests.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-XMPPFrameworkTestsTests/Pods-XMPPFrameworkTestsTests.debug.xcconfig"; sourceTree = ""; }; 9EF4C5A11AE2C2C50019F001 /* XMPPFrameworkTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XMPPFrameworkTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9EF4C5A51AE2C2C50019F001 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9EF4C5A61AE2C2C50019F001 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; @@ -180,6 +184,8 @@ 9EF4C7CB1AE2C43F0019F001 /* libidn.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libidn.a; path = ../../../Vendor/libidn/libidn.a; sourceTree = ""; }; 9EF4C7CD1AE2C4480019F001 /* libresolv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libresolv.dylib; path = usr/lib/libresolv.dylib; sourceTree = SDKROOT; }; 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncodeDecodeTest.m; sourceTree = ""; }; + 9EF4C7D41AE2C6100019F001 /* MulticastDelegateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MulticastDelegateTest.m; sourceTree = ""; }; + E12FE78966D1CF605B0A4F20 /* libPods-XMPPFrameworkTestsTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-XMPPFrameworkTestsTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -198,12 +204,30 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 90F596D50A8AB2CD874C400D /* libPods-XMPPFrameworkTestsTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 2447A4F5551AFAD7B375B8C9 /* Pods */ = { + isa = PBXGroup; + children = ( + 9508FAAF7823E030E62A713C /* Pods-XMPPFrameworkTestsTests.debug.xcconfig */, + 76C6AF82FDDA755AC643FD84 /* Pods-XMPPFrameworkTestsTests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 808D2D5B3A8FC3353BC1C1AD /* Frameworks */ = { + isa = PBXGroup; + children = ( + E12FE78966D1CF605B0A4F20 /* libPods-XMPPFrameworkTestsTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 9EF4C5981AE2C2C50019F001 = { isa = PBXGroup; children = ( @@ -215,6 +239,8 @@ 9EF4C5A31AE2C2C50019F001 /* XMPPFrameworkTests */, 9EF4C5BD1AE2C2C50019F001 /* XMPPFrameworkTestsTests */, 9EF4C5A21AE2C2C50019F001 /* Products */, + 2447A4F5551AFAD7B375B8C9 /* Pods */, + 808D2D5B3A8FC3353BC1C1AD /* Frameworks */, ); sourceTree = ""; }; @@ -255,6 +281,7 @@ isa = PBXGroup; children = ( 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */, + 9EF4C7D41AE2C6100019F001 /* MulticastDelegateTest.m */, 9EF4C5BE1AE2C2C50019F001 /* Supporting Files */, ); path = XMPPFrameworkTestsTests; @@ -551,9 +578,11 @@ isa = PBXNativeTarget; buildConfigurationList = 9EF4C5C71AE2C2C50019F001 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTestsTests" */; buildPhases = ( + 3A08A7ECFE07257C15BCB6B1 /* Check Pods Manifest.lock */, 9EF4C5B61AE2C2C50019F001 /* Sources */, 9EF4C5B71AE2C2C50019F001 /* Frameworks */, 9EF4C5B81AE2C2C50019F001 /* Resources */, + 4AFD9EB379BB30AFE2AA08DE /* Copy Pods Resources */, ); buildRules = ( ); @@ -623,6 +652,39 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 3A08A7ECFE07257C15BCB6B1 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + 4AFD9EB379BB30AFE2AA08DE /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/../Pods/Target Support Files/Pods-XMPPFrameworkTestsTests/Pods-XMPPFrameworkTestsTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 9EF4C59D1AE2C2C50019F001 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -679,6 +741,7 @@ buildActionMask = 2147483647; files = ( 9EF4C7D31AE2C4CC0019F001 /* EncodeDecodeTest.m in Sources */, + 9EF4C7D51AE2C6100019F001 /* MulticastDelegateTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -830,6 +893,7 @@ }; 9EF4C5C81AE2C2C50019F001 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 9508FAAF7823E030E62A713C /* Pods-XMPPFrameworkTestsTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( @@ -849,6 +913,7 @@ }; 9EF4C5C91AE2C2C50019F001 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 76C6AF82FDDA755AC643FD84 /* Pods-XMPPFrameworkTestsTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; FRAMEWORK_SEARCH_PATHS = ( @@ -881,6 +946,7 @@ 9EF4C5C61AE2C2C50019F001 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 9EF4C5C71AE2C2C50019F001 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTestsTests" */ = { isa = XCConfigurationList; @@ -889,6 +955,7 @@ 9EF4C5C91AE2C2C50019F001 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/MulticastDelegateTest.m b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/MulticastDelegateTest.m new file mode 100644 index 0000000000..b050de3c96 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/MulticastDelegateTest.m @@ -0,0 +1,209 @@ +// +// MulticastDelegateTest.m +// XMPPFrameworkTests +// +// Created by Paul Melnikow on 4/18/15. +// Copyright (c) 2015 Paul Melnikow. All rights reserved. +// + +#import +#import +#import "GCDMulticastDelegate.h" +#import "OCMock/OCMock.h" + +@protocol MyProtocol +@optional +- (void)didSomething; +- (void)didSomethingElse:(BOOL)flag; +- (void)foundString:(NSString *)str; +- (void)foundString:(NSString *)str andNumber:(NSNumber *)num; +@end + + +@interface MulticastDelegateTestBase : XCTestCase + +@property (strong) GCDMulticastDelegate * multicastDelegate; + +@property (strong) id del1; +@property (strong) id del2; +@property (strong) id del3; + +#if !OS_OBJECT_USE_OBJC +@property (assign) dispatch_queue_t queue1; +@property (assign) dispatch_queue_t queue2; +@property (assign) dispatch_queue_t queue3; +#else +@property (strong) dispatch_queue_t queue1; +@property (strong) dispatch_queue_t queue2; +@property (strong) dispatch_queue_t queue3; +#endif + +@end +@implementation MulticastDelegateTestBase + +- (void)setUp { + self.multicastDelegate = (GCDMulticastDelegate *)[[GCDMulticastDelegate alloc] init]; +} + +@end + +@interface MulticastDelegateTest : MulticastDelegateTestBase +@end + +@implementation MulticastDelegateTest + +- (void)setUp { + [super setUp]; + + self.del1 = OCMStrictProtocolMock(@protocol(MyProtocol)); + self.del2 = OCMStrictProtocolMock(@protocol(MyProtocol)); + self.del3 = OCMStrictProtocolMock(@protocol(MyProtocol)); + + self.queue1 = dispatch_queue_create("(1 )", NULL); + self.queue2 = dispatch_queue_create("( 2 )", NULL); + self.queue3 = dispatch_queue_create("( 3)", NULL); + + [self.multicastDelegate addDelegate:self.del1 delegateQueue:self.queue1]; + [self.multicastDelegate addDelegate:self.del2 delegateQueue:self.queue2]; + [self.multicastDelegate addDelegate:self.del3 delegateQueue:self.queue3]; +} + +-(void)tearDown +{ +#if !OS_OBJECT_USE_OBJC + dispatch_release(self.queue1); + dispatch_release(self.queue2); + dispatch_release(self.queue3); +#endif +} + +- (void)testDidSomething +{ + OCMExpect([self.del1 didSomething]); + OCMExpect([self.del2 didSomething]); + OCMExpect([self.del3 didSomething]); + + [self.multicastDelegate didSomething]; + + OCMVerifyAllWithDelay(self.del1, 0.05); + OCMVerifyAll(self.del2); + OCMVerifyAll(self.del3); +} + +- (void) testDidSomethingElse +{ + OCMExpect([self.del1 didSomethingElse:YES]); + OCMExpect([self.del2 didSomethingElse:YES]); + OCMExpect([self.del3 didSomethingElse:YES]); + + [self.multicastDelegate didSomethingElse:YES]; + + OCMVerifyAllWithDelay(self.del1, 0.05); + OCMVerifyAll(self.del2); + OCMVerifyAll(self.del3); +} + +- (void) testFoundString +{ + OCMExpect([self.del1 foundString:@"I like cheese"]); + OCMExpect([self.del2 foundString:@"I like cheese"]); + OCMExpect([self.del3 foundString:@"I like cheese"]); + + [self.multicastDelegate foundString:@"I like cheese"]; + + OCMVerifyAllWithDelay(self.del1, 0.05); + OCMVerifyAll(self.del2); + OCMVerifyAll(self.del3); +} + +- (void) testFoundStringAndNumber +{ + OCMExpect([self.del1 foundString:@"The lucky number is" andNumber:@15]); + OCMExpect([self.del2 foundString:@"The lucky number is" andNumber:@15]); + OCMExpect([self.del3 foundString:@"The lucky number is" andNumber:@15]); + + [self.multicastDelegate foundString:@"The lucky number is" andNumber:@15]; + + OCMVerifyAllWithDelay(self.del1, 0.05); + OCMVerifyAll(self.del2); + OCMVerifyAll(self.del3); +} + +- (void)testDelegateEnumerator +{ + GCDMulticastDelegateEnumerator *delegateEnum = [self.multicastDelegate delegateEnumerator]; + + id del; + dispatch_queue_t dq; + + BOOL del1Seen = false; + BOOL del2Seen = false; + BOOL del3Seen = false; + + while ([delegateEnum getNextDelegate:&del delegateQueue:&dq forSelector:@selector(didSomething)]) + { + if (del == self.del1) { + XCTAssertEqual(dq, self.queue1); + del1Seen = true; + } else if (del == self.del2) { + XCTAssertEqual(dq, self.queue2); + del2Seen = true; + } else if (del == self.del3) { + XCTAssertEqual(dq, self.queue3); + del3Seen = true; + } else { + XCTFail(@"Unexpected delegate"); + } + } + + XCTAssertTrue(del1Seen); + XCTAssertTrue(del2Seen); + XCTAssertTrue(del3Seen); +} + +@end + +// NSProxy doesn't work correctly with weak references, so this test needs a different approach. + +@interface MyMock : NSObject +@end +@implementation MyMock + +- (void)didSomething { } +- (void)didSomethingElse:(BOOL)flag { } +- (void)foundString:(NSString *)str { } +- (void)foundString:(NSString *)str andNumber:(NSNumber *)num { } + +@end + +@interface MulticastDelegateWeakReferenceTest : MulticastDelegateTestBase +@end + +@implementation MulticastDelegateWeakReferenceTest + +- (void)setUp { + [super setUp]; + + self.del1 = [[MyMock alloc] init]; + self.del2 = [[MyMock alloc] init]; + self.del3 = [[MyMock alloc] init]; + + self.queue1 = dispatch_queue_create("(1 )", NULL); + self.queue2 = dispatch_queue_create("( 2 )", NULL); + self.queue3 = dispatch_queue_create("( 3)", NULL); + + [self.multicastDelegate addDelegate:self.del1 delegateQueue:self.queue1]; + [self.multicastDelegate addDelegate:self.del2 delegateQueue:self.queue2]; + [self.multicastDelegate addDelegate:self.del3 delegateQueue:self.queue3]; +} + +- (void)testThatDelegateReferencesAreWeak +{ + XCTAssertEqual([self.multicastDelegate countForSelector:@selector(description)], 3); + + self.del1 = nil; + + XCTAssertEqual([self.multicastDelegate countForSelector:@selector(description)], 2); +} + +@end From c4960b1806eec493147318b39bf483b31ec045e0 Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Sat, 18 Apr 2015 16:48:14 -0400 Subject: [PATCH 023/356] Rewrite CapabilitiesHashingTest --- Extensions/XEP-0115/XMPPCapabilities.m | 6 +- .../CapabilitiesHashingTest.m | 143 +++++++++++++ .../XMPPFrameworkCoreDataTests/Info.plist | 24 +++ .../project.pbxproj | 194 ++++++++++++++++++ 4 files changed, 364 insertions(+), 3 deletions(-) create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkCoreDataTests/CapabilitiesHashingTest.m create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkCoreDataTests/Info.plist diff --git a/Extensions/XEP-0115/XMPPCapabilities.m b/Extensions/XEP-0115/XMPPCapabilities.m index 97318826bb..891708061e 100644 --- a/Extensions/XEP-0115/XMPPCapabilities.m +++ b/Extensions/XEP-0115/XMPPCapabilities.m @@ -496,7 +496,7 @@ static NSInteger sortFieldValues(NSXMLElement *value1, NSXMLElement *value2, voi return [str1 compare:str2 options:NSLiteralSearch]; } -- (NSString *)hashCapabilitiesFromQuery:(NSXMLElement *)query ++ (NSString *)hashCapabilitiesFromQuery:(NSXMLElement *)query { if (query == nil) return nil; @@ -796,7 +796,7 @@ - (void)continueCollectMyCapabilities:(NSXMLElement *)query XMPPLogVerbose(@"%@: My capabilities:\n%@", THIS_FILE, [query XMLStringWithOptions:(NSXMLNodeCompactEmptyElement | NSXMLNodePrettyPrint)]); - NSString *hash = [self hashCapabilitiesFromQuery:query]; + NSString *hash = [self.class hashCapabilitiesFromQuery:query]; if (hash == nil) { @@ -1258,7 +1258,7 @@ - (void)handleDiscoResponse:(NSXMLElement *)querySubElement fromJID:(XMPPJID *)j NSString *key = [self keyFromHash:hash algorithm:hashAlg]; - NSString *calculatedHash = [self hashCapabilitiesFromQuery:query]; + NSString *calculatedHash = [self.class hashCapabilitiesFromQuery:query]; if ([calculatedHash isEqualToString:hash]) { diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkCoreDataTests/CapabilitiesHashingTest.m b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkCoreDataTests/CapabilitiesHashingTest.m new file mode 100644 index 0000000000..cebb76d9c8 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkCoreDataTests/CapabilitiesHashingTest.m @@ -0,0 +1,143 @@ +// +// CapabilitiesHashingTest.m +// XMPPFrameworkTests +// +// Created by Paul Melnikow on 4/18/15. +// Copyright (c) 2015 Paul Melnikow. All rights reserved. +// + +#import +#import +#import "NSData+XMPP.h" +#import "NSXMLElement+XMPP.h" +#import "XMPPCapabilitiesCoreDataStorage.h" + +@interface XMPPCapabilities (Private) ++ (NSString *)hashCapabilitiesFromQuery:(NSXMLElement *)query; +@end + +@interface CapabilitiesHashingTest : XCTestCase +@end + +@implementation CapabilitiesHashingTest + +- (void)test1 +{ + // From XEP-0115, Section 5.2 + + NSMutableString *s = [NSMutableString string]; + [s appendString:@""]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@""]; + + NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:nil]; + + NSXMLElement *query = [doc rootElement]; + + NSString *expected = @"QgayPKawpkPSDYmwT/WM94uAlu0="; + + XCTAssertEqualObjects([XMPPCapabilities hashCapabilitiesFromQuery:query], expected); +} + +- (void)test2 +{ + // From XEP-0115, Section 5.3 + + NSMutableString *s = [NSMutableString string]; + [s appendString:@""]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" urn:xmpp:dataforms:softwareinfo"]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" ipv4"]; + [s appendString:@" ipv6"]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" Mac"]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" 10.5.1"]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" Psi"]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" 0.11"]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@""]; + + NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:nil]; + + NSXMLElement *query = [doc rootElement]; + + NSString *expected = @"q07IKJEyjvHSyhy//CH0CxmKi8w="; + + XCTAssertEqualObjects([XMPPCapabilities hashCapabilitiesFromQuery:query], expected); +} + +- (void)test3 +{ + NSMutableString *s = [NSMutableString string]; + [s appendString:@""]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@" "]; + [s appendString:@""]; + + NSXMLDocument *doc = [[NSXMLDocument alloc] initWithXMLString:s options:0 error:nil]; + + NSXMLElement *query = [doc rootElement]; + + NSString *expected = @"WsE3KKs1gYLeYKAn5zQHkTkRnUA="; + + XCTAssertEqualObjects([XMPPCapabilities hashCapabilitiesFromQuery:query], expected); +} + +@end diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkCoreDataTests/Info.plist b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkCoreDataTests/Info.plist new file mode 100644 index 0000000000..ee7e3c0293 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkCoreDataTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.paulmelnikow.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj index 8eea359395..ab119541f3 100644 --- a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj @@ -8,6 +8,14 @@ /* Begin PBXBuildFile section */ 90F596D50A8AB2CD874C400D /* libPods-XMPPFrameworkTestsTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E12FE78966D1CF605B0A4F20 /* libPods-XMPPFrameworkTestsTests.a */; }; + 9E56CB3C1AE2F7E9008CE1D5 /* CapabilitiesHashingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E56CB3B1AE2F7E9008CE1D5 /* CapabilitiesHashingTest.m */; }; + 9E56CB581AE2F823008CE1D5 /* XMPPCapabilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E56CB4D1AE2F817008CE1D5 /* XMPPCapabilities.m */; }; + 9E56CB591AE2F82B008CE1D5 /* XMPPCapabilities.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = 9E56CB451AE2F817008CE1D5 /* XMPPCapabilities.xcdatamodel */; }; + 9E56CB5A1AE2F82B008CE1D5 /* XMPPCapabilitiesCoreDataStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E56CB471AE2F817008CE1D5 /* XMPPCapabilitiesCoreDataStorage.m */; }; + 9E56CB5B1AE2F82B008CE1D5 /* XMPPCapsCoreDataStorageObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E56CB491AE2F817008CE1D5 /* XMPPCapsCoreDataStorageObject.m */; }; + 9E56CB5C1AE2F82B008CE1D5 /* XMPPCapsResourceCoreDataStorageObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E56CB4B1AE2F817008CE1D5 /* XMPPCapsResourceCoreDataStorageObject.m */; }; + 9E56CB5D1AE2F831008CE1D5 /* XMPPCoreDataStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E56CB551AE2F81E008CE1D5 /* XMPPCoreDataStorage.m */; }; + 9E56CB5F1AE2F844008CE1D5 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E56CB5E1AE2F844008CE1D5 /* CoreData.framework */; }; 9EF4C5A71AE2C2C50019F001 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5A61AE2C2C50019F001 /* main.m */; }; 9EF4C5AA1AE2C2C50019F001 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5A91AE2C2C50019F001 /* AppDelegate.m */; }; 9EF4C5AD1AE2C2C50019F001 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C5AC1AE2C2C50019F001 /* ViewController.m */; }; @@ -64,6 +72,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 9E56CB3D1AE2F7E9008CE1D5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9EF4C5991AE2C2C50019F001 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9EF4C5A01AE2C2C50019F001; + remoteInfo = XMPPFrameworkTests; + }; 9EF4C5BB1AE2C2C50019F001 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 9EF4C5991AE2C2C50019F001 /* Project object */; @@ -76,6 +91,22 @@ /* Begin PBXFileReference section */ 76C6AF82FDDA755AC643FD84 /* Pods-XMPPFrameworkTestsTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFrameworkTestsTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-XMPPFrameworkTestsTests/Pods-XMPPFrameworkTestsTests.release.xcconfig"; sourceTree = ""; }; 9508FAAF7823E030E62A713C /* Pods-XMPPFrameworkTestsTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFrameworkTestsTests.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-XMPPFrameworkTestsTests/Pods-XMPPFrameworkTestsTests.debug.xcconfig"; sourceTree = ""; }; + 9E56CB371AE2F7E9008CE1D5 /* XMPPFrameworkCoreDataTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XMPPFrameworkCoreDataTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 9E56CB3A1AE2F7E9008CE1D5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9E56CB3B1AE2F7E9008CE1D5 /* CapabilitiesHashingTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CapabilitiesHashingTest.m; sourceTree = ""; }; + 9E56CB451AE2F817008CE1D5 /* XMPPCapabilities.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = XMPPCapabilities.xcdatamodel; sourceTree = ""; }; + 9E56CB461AE2F817008CE1D5 /* XMPPCapabilitiesCoreDataStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCapabilitiesCoreDataStorage.h; sourceTree = ""; }; + 9E56CB471AE2F817008CE1D5 /* XMPPCapabilitiesCoreDataStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPCapabilitiesCoreDataStorage.m; sourceTree = ""; }; + 9E56CB481AE2F817008CE1D5 /* XMPPCapsCoreDataStorageObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCapsCoreDataStorageObject.h; sourceTree = ""; }; + 9E56CB491AE2F817008CE1D5 /* XMPPCapsCoreDataStorageObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPCapsCoreDataStorageObject.m; sourceTree = ""; }; + 9E56CB4A1AE2F817008CE1D5 /* XMPPCapsResourceCoreDataStorageObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCapsResourceCoreDataStorageObject.h; sourceTree = ""; }; + 9E56CB4B1AE2F817008CE1D5 /* XMPPCapsResourceCoreDataStorageObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPCapsResourceCoreDataStorageObject.m; sourceTree = ""; }; + 9E56CB4C1AE2F817008CE1D5 /* XMPPCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCapabilities.h; sourceTree = ""; }; + 9E56CB4D1AE2F817008CE1D5 /* XMPPCapabilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPCapabilities.m; sourceTree = ""; }; + 9E56CB541AE2F81E008CE1D5 /* XMPPCoreDataStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCoreDataStorage.h; sourceTree = ""; }; + 9E56CB551AE2F81E008CE1D5 /* XMPPCoreDataStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPCoreDataStorage.m; sourceTree = ""; }; + 9E56CB561AE2F81E008CE1D5 /* XMPPCoreDataStorageProtected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPCoreDataStorageProtected.h; sourceTree = ""; }; + 9E56CB5E1AE2F844008CE1D5 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 9EF4C5A11AE2C2C50019F001 /* XMPPFrameworkTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XMPPFrameworkTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9EF4C5A51AE2C2C50019F001 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9EF4C5A61AE2C2C50019F001 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; @@ -189,6 +220,14 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 9E56CB341AE2F7E9008CE1D5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9E56CB5F1AE2F844008CE1D5 /* CoreData.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9EF4C59E1AE2C2C50019F001 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -223,11 +262,72 @@ 808D2D5B3A8FC3353BC1C1AD /* Frameworks */ = { isa = PBXGroup; children = ( + 9E56CB5E1AE2F844008CE1D5 /* CoreData.framework */, E12FE78966D1CF605B0A4F20 /* libPods-XMPPFrameworkTestsTests.a */, ); name = Frameworks; sourceTree = ""; }; + 9E56CB381AE2F7E9008CE1D5 /* XMPPFrameworkCoreDataTests */ = { + isa = PBXGroup; + children = ( + 9E56CB3B1AE2F7E9008CE1D5 /* CapabilitiesHashingTest.m */, + 9E56CB391AE2F7E9008CE1D5 /* Supporting Files */, + ); + path = XMPPFrameworkCoreDataTests; + sourceTree = ""; + }; + 9E56CB391AE2F7E9008CE1D5 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9E56CB3A1AE2F7E9008CE1D5 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 9E56CB421AE2F808008CE1D5 /* Extensions */ = { + isa = PBXGroup; + children = ( + 9E56CB531AE2F81E008CE1D5 /* CoreDataStorage */, + 9E56CB431AE2F817008CE1D5 /* XEP-0115 */, + ); + path = Extensions; + sourceTree = ""; + }; + 9E56CB431AE2F817008CE1D5 /* XEP-0115 */ = { + isa = PBXGroup; + children = ( + 9E56CB441AE2F817008CE1D5 /* CoreDataStorage */, + 9E56CB4C1AE2F817008CE1D5 /* XMPPCapabilities.h */, + 9E56CB4D1AE2F817008CE1D5 /* XMPPCapabilities.m */, + ); + path = "XEP-0115"; + sourceTree = ""; + }; + 9E56CB441AE2F817008CE1D5 /* CoreDataStorage */ = { + isa = PBXGroup; + children = ( + 9E56CB451AE2F817008CE1D5 /* XMPPCapabilities.xcdatamodel */, + 9E56CB461AE2F817008CE1D5 /* XMPPCapabilitiesCoreDataStorage.h */, + 9E56CB471AE2F817008CE1D5 /* XMPPCapabilitiesCoreDataStorage.m */, + 9E56CB481AE2F817008CE1D5 /* XMPPCapsCoreDataStorageObject.h */, + 9E56CB491AE2F817008CE1D5 /* XMPPCapsCoreDataStorageObject.m */, + 9E56CB4A1AE2F817008CE1D5 /* XMPPCapsResourceCoreDataStorageObject.h */, + 9E56CB4B1AE2F817008CE1D5 /* XMPPCapsResourceCoreDataStorageObject.m */, + ); + path = CoreDataStorage; + sourceTree = ""; + }; + 9E56CB531AE2F81E008CE1D5 /* CoreDataStorage */ = { + isa = PBXGroup; + children = ( + 9E56CB541AE2F81E008CE1D5 /* XMPPCoreDataStorage.h */, + 9E56CB551AE2F81E008CE1D5 /* XMPPCoreDataStorage.m */, + 9E56CB561AE2F81E008CE1D5 /* XMPPCoreDataStorageProtected.h */, + ); + path = CoreDataStorage; + sourceTree = ""; + }; 9EF4C5981AE2C2C50019F001 = { isa = PBXGroup; children = ( @@ -238,6 +338,7 @@ 9EF4C5CA1AE2C2D60019F001 /* XMPPFramework */, 9EF4C5A31AE2C2C50019F001 /* XMPPFrameworkTests */, 9EF4C5BD1AE2C2C50019F001 /* XMPPFrameworkTestsTests */, + 9E56CB381AE2F7E9008CE1D5 /* XMPPFrameworkCoreDataTests */, 9EF4C5A21AE2C2C50019F001 /* Products */, 2447A4F5551AFAD7B375B8C9 /* Pods */, 808D2D5B3A8FC3353BC1C1AD /* Frameworks */, @@ -249,6 +350,7 @@ children = ( 9EF4C5A11AE2C2C50019F001 /* XMPPFrameworkTests.app */, 9EF4C5BA1AE2C2C50019F001 /* XMPPFrameworkTestsTests.xctest */, + 9E56CB371AE2F7E9008CE1D5 /* XMPPFrameworkCoreDataTests.xctest */, ); name = Products; sourceTree = ""; @@ -298,6 +400,7 @@ 9EF4C5CA1AE2C2D60019F001 /* XMPPFramework */ = { isa = PBXGroup; children = ( + 9E56CB421AE2F808008CE1D5 /* Extensions */, 9EF4C78D1AE2C3040019F001 /* Vendor */, 9EF4C5CB1AE2C2F30019F001 /* Utilities */, 9EF4C6D81AE2C2F30019F001 /* Core */, @@ -557,6 +660,24 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 9E56CB361AE2F7E9008CE1D5 /* XMPPFrameworkCoreDataTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9E56CB411AE2F7E9008CE1D5 /* Build configuration list for PBXNativeTarget "XMPPFrameworkCoreDataTests" */; + buildPhases = ( + 9E56CB331AE2F7E9008CE1D5 /* Sources */, + 9E56CB341AE2F7E9008CE1D5 /* Frameworks */, + 9E56CB351AE2F7E9008CE1D5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 9E56CB3E1AE2F7E9008CE1D5 /* PBXTargetDependency */, + ); + name = XMPPFrameworkCoreDataTests; + productName = XMPPFrameworkCoreDataTests; + productReference = 9E56CB371AE2F7E9008CE1D5 /* XMPPFrameworkCoreDataTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 9EF4C5A01AE2C2C50019F001 /* XMPPFrameworkTests */ = { isa = PBXNativeTarget; buildConfigurationList = 9EF4C5C41AE2C2C50019F001 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTests" */; @@ -603,6 +724,10 @@ LastUpgradeCheck = 0630; ORGANIZATIONNAME = "Paul Melnikow"; TargetAttributes = { + 9E56CB361AE2F7E9008CE1D5 = { + CreatedOnToolsVersion = 6.3; + TestTargetID = 9EF4C5A01AE2C2C50019F001; + }; 9EF4C5A01AE2C2C50019F001 = { CreatedOnToolsVersion = 6.3; }; @@ -627,11 +752,19 @@ targets = ( 9EF4C5A01AE2C2C50019F001 /* XMPPFrameworkTests */, 9EF4C5B91AE2C2C50019F001 /* XMPPFrameworkTestsTests */, + 9E56CB361AE2F7E9008CE1D5 /* XMPPFrameworkCoreDataTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 9E56CB351AE2F7E9008CE1D5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9EF4C59F1AE2C2C50019F001 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -686,6 +819,20 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 9E56CB331AE2F7E9008CE1D5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9E56CB591AE2F82B008CE1D5 /* XMPPCapabilities.xcdatamodel in Sources */, + 9E56CB5A1AE2F82B008CE1D5 /* XMPPCapabilitiesCoreDataStorage.m in Sources */, + 9E56CB581AE2F823008CE1D5 /* XMPPCapabilities.m in Sources */, + 9E56CB5B1AE2F82B008CE1D5 /* XMPPCapsCoreDataStorageObject.m in Sources */, + 9E56CB3C1AE2F7E9008CE1D5 /* CapabilitiesHashingTest.m in Sources */, + 9E56CB5D1AE2F831008CE1D5 /* XMPPCoreDataStorage.m in Sources */, + 9E56CB5C1AE2F82B008CE1D5 /* XMPPCapsResourceCoreDataStorageObject.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 9EF4C59D1AE2C2C50019F001 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -748,6 +895,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 9E56CB3E1AE2F7E9008CE1D5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9EF4C5A01AE2C2C50019F001 /* XMPPFrameworkTests */; + targetProxy = 9E56CB3D1AE2F7E9008CE1D5 /* PBXContainerItemProxy */; + }; 9EF4C5BC1AE2C2C50019F001 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 9EF4C5A01AE2C2C50019F001 /* XMPPFrameworkTests */; @@ -775,6 +927,40 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 9E56CB3F1AE2F7E9008CE1D5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = XMPPFrameworkCoreDataTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XMPPFrameworkTests.app/XMPPFrameworkTests"; + }; + name = Debug; + }; + 9E56CB401AE2F7E9008CE1D5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = XMPPFrameworkCoreDataTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XMPPFrameworkTests.app/XMPPFrameworkTests"; + }; + name = Release; + }; 9EF4C5C21AE2C2C50019F001 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -930,6 +1116,14 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 9E56CB411AE2F7E9008CE1D5 /* Build configuration list for PBXNativeTarget "XMPPFrameworkCoreDataTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9E56CB3F1AE2F7E9008CE1D5 /* Debug */, + 9E56CB401AE2F7E9008CE1D5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; 9EF4C59C1AE2C2C50019F001 /* Build configuration list for PBXProject "XMPPFrameworkTests" */ = { isa = XCConfigurationList; buildConfigurations = ( From fd81dff1d6ed89cf0140eaadaa2fb2dd6d137c69 Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Mon, 20 Apr 2015 13:02:03 +0100 Subject: [PATCH 024/356] Import Cocoa/UIKit Where Appropriate --- .../CoreDataStorage/XMPPUserCoreDataStorageObject.h | 6 ++++-- .../Roster/MemoryStorage/XMPPUserMemoryStorageObject.h | 6 ++++-- Extensions/Roster/XMPPRoster.h | 6 ++++-- Extensions/XEP-0092/XMPPSoftwareVersion.h | 8 ++++++++ Extensions/XEP-0153/XMPPvCardAvatarModule.h | 6 ++++-- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Extensions/Roster/CoreDataStorage/XMPPUserCoreDataStorageObject.h b/Extensions/Roster/CoreDataStorage/XMPPUserCoreDataStorageObject.h index 3604aac365..0d8e077a42 100644 --- a/Extensions/Roster/CoreDataStorage/XMPPUserCoreDataStorageObject.h +++ b/Extensions/Roster/CoreDataStorage/XMPPUserCoreDataStorageObject.h @@ -1,8 +1,10 @@ #import #import -#if !TARGET_OS_IPHONE - #import +#if TARGET_OS_IPHONE + #import +#else + #import #endif #import "XMPPUser.h" diff --git a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h index a0c9dc88a6..3841df9a8f 100644 --- a/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h +++ b/Extensions/Roster/MemoryStorage/XMPPUserMemoryStorageObject.h @@ -2,8 +2,10 @@ #import "XMPPUser.h" #import "XMPP.h" -#if !TARGET_OS_IPHONE - #import +#if TARGET_OS_IPHONE + #import +#else + #import #endif @class XMPPResourceMemoryStorageObject; diff --git a/Extensions/Roster/XMPPRoster.h b/Extensions/Roster/XMPPRoster.h index f855ddf519..403a18ec8c 100644 --- a/Extensions/Roster/XMPPRoster.h +++ b/Extensions/Roster/XMPPRoster.h @@ -1,7 +1,9 @@ #import -#if !TARGET_OS_IPHONE - #import +#if TARGET_OS_IPHONE + #import +#else + #import #endif #import "XMPP.h" diff --git a/Extensions/XEP-0092/XMPPSoftwareVersion.h b/Extensions/XEP-0092/XMPPSoftwareVersion.h index 216f407fc6..f58a52e658 100644 --- a/Extensions/XEP-0092/XMPPSoftwareVersion.h +++ b/Extensions/XEP-0092/XMPPSoftwareVersion.h @@ -1,3 +1,11 @@ +#import + +#if TARGET_OS_IPHONE + #import +#else + #import +#endif + #import "XMPPModule.h" @interface XMPPSoftwareVersion : XMPPModule diff --git a/Extensions/XEP-0153/XMPPvCardAvatarModule.h b/Extensions/XEP-0153/XMPPvCardAvatarModule.h index 77200b369f..4a58e768a9 100644 --- a/Extensions/XEP-0153/XMPPvCardAvatarModule.h +++ b/Extensions/XEP-0153/XMPPvCardAvatarModule.h @@ -12,8 +12,10 @@ #import -#if !TARGET_OS_IPHONE - #import +#if TARGET_OS_IPHONE + #import +#else + #import #endif #import "XMPP.h" From 85d1f9caff3012d3f25afda0e048b75544de888b Mon Sep 17 00:00:00 2001 From: Paul Melnikow Date: Sun, 3 May 2015 10:22:22 -0400 Subject: [PATCH 025/356] Run tests in Travis --- .travis.yml | 12 ++ .../project.pbxproj | 11 +- .../xcschemes/XMPPFrameworkTests.xcscheme | 136 ++++++++++++++++++ 3 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 .travis.yml create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/xcshareddata/xcschemes/XMPPFrameworkTests.xcscheme diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..1bad97a888 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +# references: +# * http://www.objc.io/issue-6/travis-ci.html +# * https://github.com/supermarin/xcpretty#usage + +language: objective-c +before_install: +- gem install cocoapods --no-rdoc --no-ri --no-document --quiet # Since Travis is not always on latest version +- pod install --project-directory=Xcode/Testing2 +install: +- gem install xcpretty --no-rdoc --no-ri --no-document --quiet +script: +- set -o pipefail && xcodebuild test -workspace Xcode/Testing2/XMPPFrameworkTests.xcworkspace -scheme XMPPFrameworkTests -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=8.1' | xcpretty -c diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj index ab119541f3..37fe39f998 100644 --- a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj @@ -262,6 +262,8 @@ 808D2D5B3A8FC3353BC1C1AD /* Frameworks */ = { isa = PBXGroup; children = ( + 9EF4C7CB1AE2C43F0019F001 /* libidn.a */, + 9EF4C7C91AE2C4320019F001 /* Security.framework */, 9E56CB5E1AE2F844008CE1D5 /* CoreData.framework */, E12FE78966D1CF605B0A4F20 /* libPods-XMPPFrameworkTestsTests.a */, ); @@ -332,8 +334,6 @@ isa = PBXGroup; children = ( 9EF4C7CD1AE2C4480019F001 /* libresolv.dylib */, - 9EF4C7CB1AE2C43F0019F001 /* libidn.a */, - 9EF4C7C91AE2C4320019F001 /* Security.framework */, 9EF4C7C71AE2C3B70019F001 /* libxml2.dylib */, 9EF4C5CA1AE2C2D60019F001 /* XMPPFramework */, 9EF4C5A31AE2C2C50019F001 /* XMPPFrameworkTests */, @@ -1001,7 +1001,6 @@ "$(inherited)", "/usr/include/libxml2/**", ); - IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -1042,7 +1041,6 @@ "$(inherited)", "/usr/include/libxml2/**", ); - IPHONEOS_DEPLOYMENT_TARGET = 8.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; @@ -1057,7 +1055,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - /Users/pnm/code/XMPPFramework/Vendor/libidn, + "$(SRCROOT)/../../../Vendor/libidn", ); PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -1071,7 +1069,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - /Users/pnm/code/XMPPFramework/Vendor/libidn, + "$(SRCROOT)/../../../Vendor/libidn", ); PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -1123,6 +1121,7 @@ 9E56CB401AE2F7E9008CE1D5 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 9EF4C59C1AE2C2C50019F001 /* Build configuration list for PBXProject "XMPPFrameworkTests" */ = { isa = XCConfigurationList; diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/xcshareddata/xcschemes/XMPPFrameworkTests.xcscheme b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/xcshareddata/xcschemes/XMPPFrameworkTests.xcscheme new file mode 100644 index 0000000000..8eaeac2d1a --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/xcshareddata/xcschemes/XMPPFrameworkTests.xcscheme @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 16e42aac46e70d98c9dec6c2e629efc9114ffcef Mon Sep 17 00:00:00 2001 From: Pelle Stenild Coltau Date: Thu, 7 May 2015 10:36:50 +0400 Subject: [PATCH 026/356] Implemented "6.5 Retrieve Items from a Node" from the XMPP PubSub Extension Specification (XEP-0060). --- Extensions/XEP-0060/XMPPPubSub.h | 30 +++++++ Extensions/XEP-0060/XMPPPubSub.m | 143 ++++++++++++++++++++++++------- 2 files changed, 143 insertions(+), 30 deletions(-) diff --git a/Extensions/XEP-0060/XMPPPubSub.h b/Extensions/XEP-0060/XMPPPubSub.h index 40f231095c..c065825226 100644 --- a/Extensions/XEP-0060/XMPPPubSub.h +++ b/Extensions/XEP-0060/XMPPPubSub.h @@ -307,6 +307,33 @@ **/ - (NSString *)configureNode:(NSString *)node withOptions:(NSDictionary *)options; +/** + * Retrieves items from given node. + * + * @param node + * + * The name of the node to retrieve items from. + * This should be the same node name you used when you created it. + * + * @param withItemIDs + * + * This corresponds to a list of unique ids of previously published items. + * The server will return the previously published items for those that exists. + * If none of the items exists, an empty items list will be returned. + * If you don't pass any itemIDs, the server will retrieve all items on the given node + * + * @return uuid + * + * The return value is the unique elementID of the IQ stanza that was sent. + * + * The server's response to the request will be reported via the appropriate delegate methods. + * + * @see xmppPubSub:didRetrieveItems:fromNode: + * @see xmppPubSub:didNotRetrieveItems:fromNode: + **/ +- (NSString *)retrieveItemsFromNode:(NSString *)node; +- (NSString *)retrieveItemsFromNode:(NSString *)node withItemIDs:(NSArray *)itemIds; + @end @protocol XMPPPubSubDelegate @@ -339,6 +366,9 @@ - (void)xmppPubSub:(XMPPPubSub *)sender didConfigureNode:(NSString *)node withResult:(XMPPIQ *)iq; - (void)xmppPubSub:(XMPPPubSub *)sender didNotConfigureNode:(NSString *)node withError:(XMPPIQ *)iq; +- (void)xmppPubSub:(XMPPPubSub *)sender didRetrieveItems:(XMPPIQ *)iq fromNode:(NSString *)node; +- (void)xmppPubSub:(XMPPPubSub *)sender didNotRetrieveItems:(XMPPIQ *)iq fromNode:(NSString *)node; + - (void)xmppPubSub:(XMPPPubSub *)sender didReceiveMessage:(XMPPMessage *)message; @end diff --git a/Extensions/XEP-0060/XMPPPubSub.m b/Extensions/XEP-0060/XMPPPubSub.m index 28c329598d..01a5d358cb 100644 --- a/Extensions/XEP-0060/XMPPPubSub.m +++ b/Extensions/XEP-0060/XMPPPubSub.m @@ -21,12 +21,13 @@ @implementation XMPPPubSub NSMutableDictionary *subscribeDict; NSMutableDictionary *unsubscribeDict; - NSMutableDictionary *retrieveDict; + NSMutableDictionary *retrieveSubsDict; NSMutableDictionary *configSubDict; NSMutableDictionary *createDict; NSMutableDictionary *deleteDict; NSMutableDictionary *configNodeDict; NSMutableDictionary *publishDict; + NSMutableDictionary *retrieveItemsDict; } + (BOOL)isPubSubMessage:(XMPPMessage *)message @@ -67,14 +68,15 @@ - (id)initWithServiceJID:(XMPPJID *)aServiceJID dispatchQueue:(dispatch_queue_t) { serviceJID = [aServiceJID copy]; - subscribeDict = [[NSMutableDictionary alloc] init]; - unsubscribeDict = [[NSMutableDictionary alloc] init]; - retrieveDict = [[NSMutableDictionary alloc] init]; - configSubDict = [[NSMutableDictionary alloc] init]; - createDict = [[NSMutableDictionary alloc] init]; - deleteDict = [[NSMutableDictionary alloc] init]; - configNodeDict = [[NSMutableDictionary alloc] init]; - publishDict = [[NSMutableDictionary alloc] init]; + subscribeDict = [[NSMutableDictionary alloc] init]; + unsubscribeDict = [[NSMutableDictionary alloc] init]; + retrieveSubsDict = [[NSMutableDictionary alloc] init]; + configSubDict = [[NSMutableDictionary alloc] init]; + createDict = [[NSMutableDictionary alloc] init]; + deleteDict = [[NSMutableDictionary alloc] init]; + configNodeDict = [[NSMutableDictionary alloc] init]; + publishDict = [[NSMutableDictionary alloc] init]; + retrieveItemsDict = [[NSMutableDictionary alloc] init]; } return self; } @@ -100,14 +102,15 @@ - (BOOL)activate:(XMPPStream *)aXmppStream - (void)deactivate { - [subscribeDict removeAllObjects]; - [unsubscribeDict removeAllObjects]; - [retrieveDict removeAllObjects]; - [configSubDict removeAllObjects]; - [createDict removeAllObjects]; - [deleteDict removeAllObjects]; - [configNodeDict removeAllObjects]; - [publishDict removeAllObjects]; + [subscribeDict removeAllObjects]; + [unsubscribeDict removeAllObjects]; + [retrieveSubsDict removeAllObjects]; + [configSubDict removeAllObjects]; + [createDict removeAllObjects]; + [deleteDict removeAllObjects]; + [configNodeDict removeAllObjects]; + [publishDict removeAllObjects]; + [retrieveItemsDict removeAllObjects]; if (serviceJID == nil) { [[NSNotificationCenter defaultCenter] removeObserver:self name:XMPPStreamDidChangeMyJIDNotification object:nil]; @@ -230,7 +233,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [unsubscribeDict removeObjectForKey:elementID]; return YES; } - else if ((node = retrieveDict[elementID])) + else if ((node = retrieveSubsDict[elementID])) { // Example retrieve success response: // @@ -270,7 +273,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [multicastDelegate xmppPubSub:self didNotRetrieveSubscriptions:iq forNode:node]; } - [retrieveDict removeObjectForKey:elementID]; + [retrieveSubsDict removeObjectForKey:elementID]; return YES; } else if ((node = configSubDict[elementID])) @@ -391,7 +394,37 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq [configNodeDict removeObjectForKey:elementID]; return YES; } - + else if ((node = retrieveItemsDict[elementID])) + { + // Example retrieve from node success response: + // + // + // + // + // + // ... + // + // + // + // + // + // Example delete error response: + // + // + // + // + // + // + // + + if ([[iq type] isEqualToString:@"result"]) + [multicastDelegate xmppPubSub:self didRetrieveItems:iq fromNode:node]; + else + [multicastDelegate xmppPubSub:self didNotRetrieveItems:iq fromNode:node]; + + [retrieveItemsDict removeObjectForKey:elementID]; + return YES; + } return NO; } @@ -427,14 +460,15 @@ - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error { - [subscribeDict removeAllObjects]; - [unsubscribeDict removeAllObjects]; - [retrieveDict removeAllObjects]; - [configSubDict removeAllObjects]; - [createDict removeAllObjects]; - [deleteDict removeAllObjects]; - [configNodeDict removeAllObjects]; - [publishDict removeAllObjects]; + [subscribeDict removeAllObjects]; + [unsubscribeDict removeAllObjects]; + [retrieveSubsDict removeAllObjects]; + [configSubDict removeAllObjects]; + [createDict removeAllObjects]; + [deleteDict removeAllObjects]; + [configNodeDict removeAllObjects]; + [publishDict removeAllObjects]; + [retrieveItemsDict removeAllObjects]; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -640,9 +674,9 @@ - (NSString *)retrieveSubscriptionsForNode:(NSString *)aNode NSString *uuid = [xmppStream generateUUID]; dispatch_async(moduleQueue, ^{ if (node) - retrieveDict[uuid] = node; + retrieveSubsDict[uuid] = node; else - retrieveDict[uuid] = [NSNull null]; + retrieveSubsDict[uuid] = [NSNull null]; }); // Get subscriptions for all nodes: @@ -967,4 +1001,53 @@ - (NSString *)publishToNode:(NSString *)node return uuid; } +- (NSString *)retrieveItemsFromNode:(NSString *)node +{ + return [self retrieveItemsFromNode:node withItemIDs:nil]; +} + +- (NSString *)retrieveItemsFromNode:(NSString *)node withItemIDs:(NSArray *)itemIds +{ + if (node == nil) return nil; + + // + //   + //     + //       + //       + //     + //   + // + + NSString *uuid = [xmppStream generateUUID]; + + NSXMLElement *items = [NSXMLElement elementWithName:@"items"]; + [items addAttributeWithName:@"node" stringValue:node]; + + if (itemIds) { + for (id itemId in itemIds) + { + NSXMLElement *item = [NSXMLElement elementWithName:@"item"]; + [item addAttributeWithName:@"id" stringValue:itemId]; + [items addChild:item]; + } + } + + NSXMLElement *pubsub = [NSXMLElement elementWithName:@"pubsub" xmlns:XMLNS_PUBSUB]; + [pubsub addChild:items]; + + XMPPIQ *iq = [XMPPIQ iqWithType:@"get" to:serviceJID elementID:uuid]; + [iq addChild:pubsub]; + + [xmppStream sendElement:iq]; + + dispatch_async(moduleQueue, ^{ + retrieveItemsDict[uuid] = node; + }); + return uuid; +} + @end From bebc2d4d8d92c3c0ea3a1d97e830dde654353c9c Mon Sep 17 00:00:00 2001 From: Jon Hjelle Date: Wed, 27 May 2015 15:08:21 -0700 Subject: [PATCH 027/356] Allow a username different than the user part of a JID to be used for authentication. --- Authentication/Plain/XMPPPlainAuthentication.h | 7 +++++++ Authentication/Plain/XMPPPlainAuthentication.m | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Authentication/Plain/XMPPPlainAuthentication.h b/Authentication/Plain/XMPPPlainAuthentication.h index a1f79f1ccb..0c507fe16b 100644 --- a/Authentication/Plain/XMPPPlainAuthentication.h +++ b/Authentication/Plain/XMPPPlainAuthentication.h @@ -9,6 +9,13 @@ // // See XMPPSASLAuthentication.h for more information. +/** + * Use this init method if the username used for authentication does not match the user part of the JID. + * If inUsername is nil, the user part of the JID will be used. The standard init method will use the + * user part of the JID as the username. +**/ +- (id)initWithStream:(XMPPStream *)stream username:(NSString *)inUsername password:(NSString *)inPassword; + @end //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Authentication/Plain/XMPPPlainAuthentication.m b/Authentication/Plain/XMPPPlainAuthentication.m index 590e7111ea..90c4aac7ff 100644 --- a/Authentication/Plain/XMPPPlainAuthentication.m +++ b/Authentication/Plain/XMPPPlainAuthentication.m @@ -25,6 +25,7 @@ @implementation XMPPPlainAuthentication __unsafe_unretained XMPPStream *xmppStream; #endif + NSString *username; NSString *password; } @@ -33,16 +34,22 @@ + (NSString *)mechanismName return @"PLAIN"; } -- (id)initWithStream:(XMPPStream *)stream password:(NSString *)inPassword +- (id)initWithStream:(XMPPStream *)stream username:(NSString *)inUsername password:(NSString *)inPassword { if ((self = [super init])) { xmppStream = stream; + username = inUsername; password = inPassword; } return self; } +- (id)initWithStream:(XMPPStream *)stream password:(NSString *)inPassword +{ + return [self initWithStream:stream username:nil password:inPassword]; +} + - (BOOL)start:(NSError **)errPtr { XMPPLogTrace(); @@ -54,9 +61,13 @@ - (BOOL)start:(NSError **)errPtr // authcid: authentication identity (username) // passwd : password for authcid - NSString *username = [xmppStream.myJID user]; + NSString *authUsername = username; + if (!authUsername) + { + authUsername = [xmppStream.myJID user]; + } - NSString *payload = [NSString stringWithFormat:@"\0%@\0%@", username, password]; + NSString *payload = [NSString stringWithFormat:@"\0%@\0%@", authUsername, password]; NSString *base64 = [[payload dataUsingEncoding:NSUTF8StringEncoding] xmpp_base64Encoded]; // Base-64-Info From 6ff2f9c26c2414e1ed82a96d130caad819f7f7f3 Mon Sep 17 00:00:00 2001 From: Jon Hjelle Date: Wed, 27 May 2015 15:24:34 -0700 Subject: [PATCH 028/356] Allow a username different than the user part of a JID to be used for all SASL-based authentication methods. --- .../Digest-MD5/XMPPDigestMD5Authentication.m | 11 ++++++++++- Authentication/Plain/XMPPPlainAuthentication.h | 7 ------- Authentication/Plain/XMPPPlainAuthentication.m | 10 +++++----- .../SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m | 14 +++++++++++++- Authentication/XMPPSASLAuthentication.h | 7 +++++++ 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/Authentication/Digest-MD5/XMPPDigestMD5Authentication.m b/Authentication/Digest-MD5/XMPPDigestMD5Authentication.m index 1b98b852bb..28d469760e 100644 --- a/Authentication/Digest-MD5/XMPPDigestMD5Authentication.m +++ b/Authentication/Digest-MD5/XMPPDigestMD5Authentication.m @@ -70,10 +70,16 @@ + (NSString *)mechanismName @synthesize password; - (id)initWithStream:(XMPPStream *)stream password:(NSString *)inPassword +{ + return [self initWithStream:stream username:nil password:inPassword]; +} + +- (id)initWithStream:(XMPPStream *)stream username:(NSString *)inUsername password:(NSString *)inPassword { if ((self = [super init])) { xmppStream = stream; + username = inUsername; password = inPassword; } return self; @@ -140,7 +146,10 @@ - (XMPPHandleAuthResponse)handleAuth1:(NSXMLElement *)authResponse if (cnonce == nil) cnonce = [XMPPStream generateUUID]; - username = [myJID user]; + if (username == nil) + { + username = [myJID user]; + } // Create and send challenge response element diff --git a/Authentication/Plain/XMPPPlainAuthentication.h b/Authentication/Plain/XMPPPlainAuthentication.h index 0c507fe16b..a1f79f1ccb 100644 --- a/Authentication/Plain/XMPPPlainAuthentication.h +++ b/Authentication/Plain/XMPPPlainAuthentication.h @@ -9,13 +9,6 @@ // // See XMPPSASLAuthentication.h for more information. -/** - * Use this init method if the username used for authentication does not match the user part of the JID. - * If inUsername is nil, the user part of the JID will be used. The standard init method will use the - * user part of the JID as the username. -**/ -- (id)initWithStream:(XMPPStream *)stream username:(NSString *)inUsername password:(NSString *)inPassword; - @end //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Authentication/Plain/XMPPPlainAuthentication.m b/Authentication/Plain/XMPPPlainAuthentication.m index 90c4aac7ff..7b74551964 100644 --- a/Authentication/Plain/XMPPPlainAuthentication.m +++ b/Authentication/Plain/XMPPPlainAuthentication.m @@ -34,6 +34,11 @@ + (NSString *)mechanismName return @"PLAIN"; } +- (id)initWithStream:(XMPPStream *)stream password:(NSString *)inPassword +{ + return [self initWithStream:stream username:nil password:inPassword]; +} + - (id)initWithStream:(XMPPStream *)stream username:(NSString *)inUsername password:(NSString *)inPassword { if ((self = [super init])) @@ -45,11 +50,6 @@ - (id)initWithStream:(XMPPStream *)stream username:(NSString *)inUsername passwo return self; } -- (id)initWithStream:(XMPPStream *)stream password:(NSString *)inPassword -{ - return [self initWithStream:stream username:nil password:inPassword]; -} - - (BOOL)start:(NSError **)errPtr { XMPPLogTrace(); diff --git a/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m b/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m index 5330db9f3c..a144053161 100644 --- a/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m +++ b/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m @@ -64,10 +64,22 @@ + (NSString *)mechanismName } - (id)initWithStream:(XMPPStream *)stream password:(NSString *)password +{ + return [self initWithStream:stream username:nil password:inPassword]; +} + +- (id)initWithStream:(XMPPStream *)stream username:(NSString *)inUsername password:(NSString *)inPassword { if ((self = [super init])) { xmppStream = stream; - _username = [XMPPStringPrep prepNode:[xmppStream.myJID user]]; + if (inUsername) + { + _username = inUsername; + } + else + { + _username = [XMPPStringPrep prepNode:[xmppStream.myJID user]]; + } _password = [XMPPStringPrep prepPassword:password]; _hashAlgorithm = kCCHmacAlgSHA1; } diff --git a/Authentication/XMPPSASLAuthentication.h b/Authentication/XMPPSASLAuthentication.h index 9d0d1df921..d3d2e0a55d 100644 --- a/Authentication/XMPPSASLAuthentication.h +++ b/Authentication/XMPPSASLAuthentication.h @@ -58,6 +58,13 @@ typedef NS_ENUM(NSInteger, XMPPHandleAuthResponse) { **/ - (id)initWithStream:(XMPPStream *)stream password:(NSString *)password; +/** + * Use this init method if the username used for authentication does not match the user part of the JID. + * If username is nil, the user part of the JID will be used. + * The standard init method uses this init method, passing nil for the username. +**/ +- (id)initWithStream:(XMPPStream *)stream username:(NSString *)username password:(NSString *)password; + /** * Attempts to start the authentication process. * The auth mechanism should send whatever stanzas are needed to begin the authentication process. From 2a2434e6cf89be877c0c65666e996697178b4731 Mon Sep 17 00:00:00 2001 From: Jon Hjelle Date: Wed, 27 May 2015 15:43:48 -0700 Subject: [PATCH 029/356] Fix mismatched parameter names --- .../SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m b/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m index a144053161..d0d795b229 100644 --- a/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m +++ b/Authentication/SCRAM-SHA-1/XMPPSCRAMSHA1Authentication.m @@ -65,20 +65,20 @@ + (NSString *)mechanismName - (id)initWithStream:(XMPPStream *)stream password:(NSString *)password { - return [self initWithStream:stream username:nil password:inPassword]; + return [self initWithStream:stream username:nil password:password]; } -- (id)initWithStream:(XMPPStream *)stream username:(NSString *)inUsername password:(NSString *)inPassword +- (id)initWithStream:(XMPPStream *)stream username:(NSString *)username password:(NSString *)password { if ((self = [super init])) { xmppStream = stream; - if (inUsername) + if (username) { - _username = inUsername; + _username = username; } else { - _username = [XMPPStringPrep prepNode:[xmppStream.myJID user]]; + _username = [XMPPStringPrep prepNode:[xmppStream.myJID user]]; } _password = [XMPPStringPrep prepPassword:password]; _hashAlgorithm = kCCHmacAlgSHA1; From 115d43060ce166e8038f2ba91e21023f97274566 Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Wed, 3 Jun 2015 22:14:35 +0100 Subject: [PATCH 030/356] XMPPSASLAuthentication Fixes XMPPSASLAuthentication initWithStream:username:password: is now Optional --- Authentication/XMPPSASLAuthentication.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Authentication/XMPPSASLAuthentication.h b/Authentication/XMPPSASLAuthentication.h index d3d2e0a55d..fb788720d0 100644 --- a/Authentication/XMPPSASLAuthentication.h +++ b/Authentication/XMPPSASLAuthentication.h @@ -58,12 +58,6 @@ typedef NS_ENUM(NSInteger, XMPPHandleAuthResponse) { **/ - (id)initWithStream:(XMPPStream *)stream password:(NSString *)password; -/** - * Use this init method if the username used for authentication does not match the user part of the JID. - * If username is nil, the user part of the JID will be used. - * The standard init method uses this init method, passing nil for the username. -**/ -- (id)initWithStream:(XMPPStream *)stream username:(NSString *)username password:(NSString *)password; /** * Attempts to start the authentication process. @@ -92,6 +86,13 @@ typedef NS_ENUM(NSInteger, XMPPHandleAuthResponse) { @optional +/** + * Use this init method if the username used for authentication does not match the user part of the JID. + * If username is nil, the user part of the JID will be used. + * The standard init method uses this init method, passing nil for the username. + **/ +- (id)initWithStream:(XMPPStream *)stream username:(NSString *)username password:(NSString *)password; + /** * Optionally implement this method to override the default behavior. * The default value is YES. From 656313d92390531c9341d3dfdbfd8246dce2904c Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Wed, 3 Jun 2015 22:17:03 +0100 Subject: [PATCH 031/356] Persistent Store Directory Fixes #537 Persistent Store Directory is now based on CFBundleIdentifier rather than CFBundleDisplayName to prevent issues when the user changes their language settings --- .../CoreDataStorage/XMPPCoreDataStorage.m | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/Extensions/CoreDataStorage/XMPPCoreDataStorage.m b/Extensions/CoreDataStorage/XMPPCoreDataStorage.m index de887075ed..39218e30f0 100644 --- a/Extensions/CoreDataStorage/XMPPCoreDataStorage.m +++ b/Extensions/CoreDataStorage/XMPPCoreDataStorage.m @@ -445,30 +445,25 @@ - (void)updateJidCache:(NSNotification *)notification - (NSString *)persistentStoreDirectory { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? paths[0] : NSTemporaryDirectory(); - - // Attempt to find a name for this application - NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; - if (appName == nil) { - appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; - } - - if (appName == nil) { - appName = @"xmppframework"; - } - - - NSString *result = [basePath stringByAppendingPathComponent:appName]; - - NSFileManager *fileManager = [NSFileManager defaultManager]; - - if (![fileManager fileExistsAtPath:result]) - { - [fileManager createDirectoryAtPath:result withIntermediateDirectories:YES attributes:nil error:nil]; - } - - return result; + NSFileManager *fileManager = [NSFileManager defaultManager]; + + // Previously the Peristent Story Directory was based on the Bundle Display Name but this can be Localized + // If Peristent Story Directory already exists we will use that + NSString *bundleDisplayName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + NSString *legacyPersistentStoreDirectory = [basePath stringByAppendingPathComponent:bundleDisplayName]; + if ([fileManager fileExistsAtPath:legacyPersistentStoreDirectory]) { + return legacyPersistentStoreDirectory; + } + + // Peristent Story Directory now uses the Bundle Identifier + NSString *bundleIdentifier = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]; + NSString *persistentStoreDirectory = [basePath stringByAppendingPathComponent:bundleIdentifier]; + if (![fileManager fileExistsAtPath:persistentStoreDirectory]) { + [fileManager createDirectoryAtPath:persistentStoreDirectory withIntermediateDirectories:YES attributes:nil error:nil]; + } + return persistentStoreDirectory; } - (NSManagedObjectModel *)managedObjectModel From d3a09342e4107ea11c73c09d9e905c9ccdd3092b Mon Sep 17 00:00:00 2001 From: Chris Ballinger Date: Tue, 9 Jun 2015 21:21:47 -0700 Subject: [PATCH 032/356] Support for XMPP URIs (XEP-0147) --- Extensions/XEP-0147/XMPPURI.h | 55 +++++++++++ Extensions/XEP-0147/XMPPURI.m | 91 +++++++++++++++++++ Xcode/Testing2/Podfile | 3 +- Xcode/Testing2/Podfile.lock | 10 ++ .../project.pbxproj | 18 ++++ .../XMPPFrameworkTestsTests/XMPPURITests.m | 66 ++++++++++++++ 6 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 Extensions/XEP-0147/XMPPURI.h create mode 100644 Extensions/XEP-0147/XMPPURI.m create mode 100644 Xcode/Testing2/Podfile.lock create mode 100644 Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/XMPPURITests.m diff --git a/Extensions/XEP-0147/XMPPURI.h b/Extensions/XEP-0147/XMPPURI.h new file mode 100644 index 0000000000..cd379bbe83 --- /dev/null +++ b/Extensions/XEP-0147/XMPPURI.h @@ -0,0 +1,55 @@ +// +// XMPPURI.h +// ChatSecure +// +// Created by Christopher Ballinger on 5/15/15. +// Copyright (c) 2015 Chris Ballinger. All rights reserved. +// + +#import +#import "XMPPJID.h" + +/** + * For parsing and creating XMPP URIs RFC5122/XEP-0147 + * e.g. xmpp:username@domain.com?subscribe + * http://www.xmpp.org/extensions/xep-0147.html + */ +@interface XMPPURI : NSObject + +@property (nonatomic, strong, readonly) XMPPJID *jid; + +/** + * XMPP query action. e.g. subscribe + * For example, the query action below would be 'subscribe' + * xmpp:romeo@montague.net?subscribe + * For full list: http://xmpp.org/registrar/querytypes.html + */ +@property (nonatomic, strong, readonly) NSString *queryAction; + +/** + * XMPP query parameters. e.g. subject=Test + * + * For example the query parameters for + * xmpp:romeo@montague.net?message;subject=Test%20Message;body=Here%27s%20a%20test%20message + * would be + * {"subject": "Test Message", + * "body": "Here's a test message"} + */ +@property (nonatomic, strong, readonly) NSDictionary *queryParameters; + +/** + * Generates URI string from jid, queryAction, and queryParameters + * e.g. xmpp:romeo@montague.net?subscribe + */ +- (NSString*) uriString; + +// Parsing XMPP URIs +- (instancetype) initWithURL:(NSURL*)url; +- (instancetype) initWithURIString:(NSString*)uriString; + +// Creating XMPP URIs +- (instancetype) initWithJID:(XMPPJID*)jid + queryAction:(NSString*)queryAction + queryParameters:(NSDictionary*)queryParameters; + +@end diff --git a/Extensions/XEP-0147/XMPPURI.m b/Extensions/XEP-0147/XMPPURI.m new file mode 100644 index 0000000000..845ef92ff5 --- /dev/null +++ b/Extensions/XEP-0147/XMPPURI.m @@ -0,0 +1,91 @@ +// +// XMPPURI.m +// ChatSecure +// +// Created by Christopher Ballinger on 5/15/15. +// Copyright (c) 2015 Chris Ballinger. All rights reserved. +// + +#import "XMPPURI.h" + +@implementation XMPPURI + +- (instancetype) initWithURIString:(NSString *)uriString { + if (self = [super init]) { + [self parseURIString:uriString]; + } + return self; +} + +- (instancetype) initWithURL:(NSURL *)url { + if (self = [self initWithURIString:url.absoluteString]) { + } + return self; +} + +- (instancetype) initWithJID:(XMPPJID*)jid + queryAction:(NSString*)queryAction + queryParameters:(NSDictionary*)queryParameters { + if (self = [super init]) { + _jid = [jid copy]; + _queryAction = [queryAction copy]; + _queryParameters = [queryParameters copy]; + } + return self; +} + +- (NSString*) uriString { + NSMutableString *uriString = [NSMutableString stringWithFormat:@"xmpp:%@", self.jid.bare]; + if (self.queryAction) { + [uriString appendFormat:@"?%@", self.queryAction]; + } + [self.queryParameters enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { + [uriString appendFormat:@";%@=%@", key, [obj stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + }]; + return uriString; +} + +- (void) parseURIString:(NSString*)uriString { + // Fix potentially malformed URIs + if ([uriString containsString:@"://"]) { + uriString = [uriString stringByReplacingOccurrencesOfString:@"://" withString:@":" options:0 range:NSMakeRange(0, uriString.length)]; + } + NSArray *uriComponents = [uriString componentsSeparatedByString:@":"]; + NSString *scheme = nil; + NSString *jidString = nil; + + if (uriComponents.count >= 2) { + scheme = uriComponents[0]; + NSString *path = uriComponents[1]; + if ([path containsString:@"?"]) { + NSArray *queryComponents = [path componentsSeparatedByString:@"?"]; + jidString = queryComponents[0]; + NSString *query = queryComponents[1]; + NSArray *queryKeys = [query componentsSeparatedByString:@";"]; + + NSMutableDictionary *queryParameters = [NSMutableDictionary dictionaryWithCapacity:queryKeys.count]; + [queryKeys enumerateObjectsUsingBlock:^(NSString *queryItem, NSUInteger idx, BOOL *stop) { + if (idx == 0) { + _queryAction = queryItem; + } else { + NSArray *keyValue = [queryItem componentsSeparatedByString:@"="]; + if (keyValue.count == 2) { + NSString *key = keyValue[0]; + NSString *value = [keyValue[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + if (key && value) { + queryParameters[key] = value; + } + } + } + }]; + _queryParameters = queryParameters; + } else { + jidString = path; + } + } + if (jidString) { + _jid = [XMPPJID jidWithString:jidString]; + } +} + +@end diff --git a/Xcode/Testing2/Podfile b/Xcode/Testing2/Podfile index b0f6a7c81a..f58cdc2aa4 100644 --- a/Xcode/Testing2/Podfile +++ b/Xcode/Testing2/Podfile @@ -1,7 +1,8 @@ xcodeproj 'XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj' # Uncomment this line to define a global platform for your project -# platform :ios, '6.0' + +platform :ios, '6.0' target 'XMPPFrameworkTests' do diff --git a/Xcode/Testing2/Podfile.lock b/Xcode/Testing2/Podfile.lock new file mode 100644 index 0000000000..8ba75d67bd --- /dev/null +++ b/Xcode/Testing2/Podfile.lock @@ -0,0 +1,10 @@ +PODS: + - OCMock (3.1.2) + +DEPENDENCIES: + - OCMock (~> 3.1) + +SPEC CHECKSUMS: + OCMock: a10ea9f0a6e921651f96f78b6faee95ebc813b92 + +COCOAPODS: 0.37.2 diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj index 37fe39f998..849a436407 100644 --- a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTests.xcodeproj/project.pbxproj @@ -69,6 +69,8 @@ 9EF4C7CE1AE2C4480019F001 /* libresolv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF4C7CD1AE2C4480019F001 /* libresolv.dylib */; }; 9EF4C7D31AE2C4CC0019F001 /* EncodeDecodeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */; }; 9EF4C7D51AE2C6100019F001 /* MulticastDelegateTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EF4C7D41AE2C6100019F001 /* MulticastDelegateTest.m */; }; + D9A3CB311B27F0C8000A50C6 /* XMPPURI.m in Sources */ = {isa = PBXBuildFile; fileRef = D9A3CB301B27F0C8000A50C6 /* XMPPURI.m */; }; + D9A3CB331B27F0FD000A50C6 /* XMPPURITests.m in Sources */ = {isa = PBXBuildFile; fileRef = D9A3CB321B27F0FD000A50C6 /* XMPPURITests.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -216,6 +218,9 @@ 9EF4C7CD1AE2C4480019F001 /* libresolv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libresolv.dylib; path = usr/lib/libresolv.dylib; sourceTree = SDKROOT; }; 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncodeDecodeTest.m; sourceTree = ""; }; 9EF4C7D41AE2C6100019F001 /* MulticastDelegateTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MulticastDelegateTest.m; sourceTree = ""; }; + D9A3CB2F1B27F0C8000A50C6 /* XMPPURI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMPPURI.h; sourceTree = ""; }; + D9A3CB301B27F0C8000A50C6 /* XMPPURI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPURI.m; sourceTree = ""; }; + D9A3CB321B27F0FD000A50C6 /* XMPPURITests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XMPPURITests.m; sourceTree = ""; }; E12FE78966D1CF605B0A4F20 /* libPods-XMPPFrameworkTestsTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-XMPPFrameworkTestsTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -290,6 +295,7 @@ 9E56CB421AE2F808008CE1D5 /* Extensions */ = { isa = PBXGroup; children = ( + D9A3CB2E1B27F0C8000A50C6 /* XEP-0147 */, 9E56CB531AE2F81E008CE1D5 /* CoreDataStorage */, 9E56CB431AE2F817008CE1D5 /* XEP-0115 */, ); @@ -382,6 +388,7 @@ 9EF4C5BD1AE2C2C50019F001 /* XMPPFrameworkTestsTests */ = { isa = PBXGroup; children = ( + D9A3CB321B27F0FD000A50C6 /* XMPPURITests.m */, 9EF4C7D21AE2C4CC0019F001 /* EncodeDecodeTest.m */, 9EF4C7D41AE2C6100019F001 /* MulticastDelegateTest.m */, 9EF4C5BE1AE2C2C50019F001 /* Supporting Files */, @@ -657,6 +664,15 @@ path = Private; sourceTree = ""; }; + D9A3CB2E1B27F0C8000A50C6 /* XEP-0147 */ = { + isa = PBXGroup; + children = ( + D9A3CB2F1B27F0C8000A50C6 /* XMPPURI.h */, + D9A3CB301B27F0C8000A50C6 /* XMPPURI.m */, + ); + path = "XEP-0147"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -888,6 +904,8 @@ buildActionMask = 2147483647; files = ( 9EF4C7D31AE2C4CC0019F001 /* EncodeDecodeTest.m in Sources */, + D9A3CB331B27F0FD000A50C6 /* XMPPURITests.m in Sources */, + D9A3CB311B27F0C8000A50C6 /* XMPPURI.m in Sources */, 9EF4C7D51AE2C6100019F001 /* MulticastDelegateTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/XMPPURITests.m b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/XMPPURITests.m new file mode 100644 index 0000000000..10f3db1c44 --- /dev/null +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/XMPPURITests.m @@ -0,0 +1,66 @@ +// +// XMPPURITests.m +// ChatSecure +// +// Created by Christopher Ballinger on 6/9/15. +// Copyright (c) 2015 Chris Ballinger. All rights reserved. +// + +#import +#import +#import "XMPPURI.h" + +@interface XMPPURITests : XCTestCase + +@end + +@implementation XMPPURITests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + + +- (void) testXMPPURI { + XMPPJID *jid = [XMPPJID jidWithString:@"romeo@montague.net"]; + NSString *queryAction = @"message"; + NSDictionary *queryParameters = @{@"subject": @"Test Message", + @"body": @"Here's a test message"}; + XMPPURI *uriGeneration = [[XMPPURI alloc] initWithJID:jid queryAction:queryAction queryParameters:queryParameters]; + + NSString *uriString = [uriGeneration uriString]; + NSURL *url = [NSURL URLWithString:uriString]; + + XMPPURI *uriParsing = [[XMPPURI alloc] initWithURL:url]; + + XCTAssertEqualObjects(jid.bare, uriParsing.jid.bare); + XCTAssertEqualObjects(queryAction, uriParsing.queryAction); + XCTAssertEqualObjects(queryParameters, uriParsing.queryParameters); +} + +- (void) testSubscribeWithOTR { + XMPPJID *jid = [XMPPJID jidWithString:@"romeo@montague.net"]; + NSString *queryAction = @"subscribe"; + NSString *fingerprint = @"8FBB10D4A2B73FAE935FF3AEBA5EFFE29A98966F"; + NSString *fingerprintKey = @"otr-fingerprint"; + NSDictionary *queryParameters = @{fingerprintKey: fingerprint}; + XMPPURI *uriGeneration = [[XMPPURI alloc] initWithJID:jid queryAction:queryAction queryParameters:queryParameters]; + + NSString *uriString = [uriGeneration uriString]; + NSURL *url = [NSURL URLWithString:uriString]; + + XMPPURI *uriParsing = [[XMPPURI alloc] initWithURL:url]; + + XCTAssertEqualObjects(jid.bare, uriParsing.jid.bare); + XCTAssertEqualObjects(queryAction, uriParsing.queryAction); + XCTAssertEqualObjects(queryParameters, uriParsing.queryParameters); + XCTAssertEqualObjects(fingerprint, uriParsing.queryParameters[fingerprintKey]); +} + +@end From 8ffbd09578136402f82be58476dc093079256252 Mon Sep 17 00:00:00 2001 From: Chris Ballinger Date: Tue, 9 Jun 2015 23:48:32 -0700 Subject: [PATCH 033/356] XEP-0147: Parse authority JID --- Extensions/XEP-0147/XMPPURI.h | 14 +++++++++ Extensions/XEP-0147/XMPPURI.m | 23 ++++++++++++-- .../XMPPFrameworkTestsTests/XMPPURITests.m | 31 +++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Extensions/XEP-0147/XMPPURI.h b/Extensions/XEP-0147/XMPPURI.h index cd379bbe83..4198f03364 100644 --- a/Extensions/XEP-0147/XMPPURI.h +++ b/Extensions/XEP-0147/XMPPURI.h @@ -16,8 +16,22 @@ */ @interface XMPPURI : NSObject +/** + * User JID. e.g. romeo@montague.net + * Example: xmpp:romeo@montague.net + */ @property (nonatomic, strong, readonly) XMPPJID *jid; +/** + * Account JID. (Optional) + * Used to specify an account with which to perform an action. + * For example 'guest@example.com' would be the authority portion of + * xmpp://guest@example.com/support@example.com?message + * so the application would show a dialog with an outgoing message + * to support@example.com from the user's account guest@example.com. + */ +@property (nonatomic, strong, readonly) XMPPJID *accountJID; + /** * XMPP query action. e.g. subscribe * For example, the query action below would be 'subscribe' diff --git a/Extensions/XEP-0147/XMPPURI.m b/Extensions/XEP-0147/XMPPURI.m index 845ef92ff5..672cfddde0 100644 --- a/Extensions/XEP-0147/XMPPURI.m +++ b/Extensions/XEP-0147/XMPPURI.m @@ -39,17 +39,34 @@ - (NSString*) uriString { if (self.queryAction) { [uriString appendFormat:@"?%@", self.queryAction]; } + NSMutableCharacterSet *allowedCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy; + [allowedCharacterSet removeCharactersInString:@"'"]; // what other characters should be removed? [self.queryParameters enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { - [uriString appendFormat:@";%@=%@", key, [obj stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + NSString *value = [obj stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + [uriString appendFormat:@";%@=%@", key, value]; }]; return uriString; } - (void) parseURIString:(NSString*)uriString { - // Fix potentially malformed URIs + NSString *authority = nil; + // Parse authority component if ([uriString containsString:@"://"]) { - uriString = [uriString stringByReplacingOccurrencesOfString:@"://" withString:@":" options:0 range:NSMakeRange(0, uriString.length)]; + NSRange fullRange = NSMakeRange(0, uriString.length); + NSRange startRange = [uriString rangeOfString:@"://"]; + NSUInteger trailingLocation = startRange.location + startRange.length; + NSRange trailingRange = NSMakeRange(trailingLocation, uriString.length - trailingLocation); + NSRange endRange = [uriString rangeOfString:@"/" options:0 range:trailingRange]; + NSUInteger authorityLocation = startRange.location + startRange.length; + NSRange authorityRange = NSMakeRange(authorityLocation, endRange.location - authorityLocation); + authority = [uriString substringWithRange:authorityRange]; + NSString *stringToRemove = [NSString stringWithFormat:@"://%@/", authority]; + uriString = [uriString stringByReplacingOccurrencesOfString:stringToRemove withString:@":" options:0 range:fullRange]; } + if (authority) { + _accountJID = [XMPPJID jidWithString:authority]; + } + NSArray *uriComponents = [uriString componentsSeparatedByString:@":"]; NSString *scheme = nil; NSString *jidString = nil; diff --git a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/XMPPURITests.m b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/XMPPURITests.m index 10f3db1c44..b6fc61c185 100644 --- a/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/XMPPURITests.m +++ b/Xcode/Testing2/XMPPFrameworkTests/XMPPFrameworkTestsTests/XMPPURITests.m @@ -44,6 +44,37 @@ - (void) testXMPPURI { XCTAssertEqualObjects(queryParameters, uriParsing.queryParameters); } +- (void) testURIString { + NSString *uriString = @"xmpp:romeo@montague.net?message;subject=Test%20Message;body=Here%27s%20a%20test%20message"; + XMPPURI *uri = [[XMPPURI alloc] initWithURIString:uriString]; + NSString *outURIString = uri.uriString; + XCTAssertEqualObjects(uriString, outURIString); +} + +- (void) testXMPPAuthority { + NSString *testString = @"xmpp://guest@example.com/support@example.com?message"; + NSString *authority = @"guest@example.com"; + NSString *user = @"support@example.com"; + NSString *action = @"message"; + NSString *uriString = [NSString stringWithFormat:@"xmpp://%@/%@?%@", authority, user, action]; + XCTAssertEqualObjects(testString, uriString); + XMPPURI *uri = [[XMPPURI alloc] initWithURIString:uriString]; + XCTAssertEqualObjects(uri.jid.bare, user); + XCTAssertEqualObjects(uri.accountJID.bare, authority); +} + +- (void) testXMPPAuthorityWithResource { + NSString *testString = @"xmpp://guest@example.com/support@example.com/resource?message"; + NSString *authority = @"guest@example.com"; + NSString *user = @"support@example.com/resource"; + NSString *action = @"message"; + NSString *uriString = [NSString stringWithFormat:@"xmpp://%@/%@?%@", authority, user, action]; + XCTAssertEqualObjects(testString, uriString); + XMPPURI *uri = [[XMPPURI alloc] initWithURIString:uriString]; + XCTAssertEqualObjects(uri.jid.full, user); + XCTAssertEqualObjects(uri.accountJID.bare, authority); +} + - (void) testSubscribeWithOTR { XMPPJID *jid = [XMPPJID jidWithString:@"romeo@montague.net"]; NSString *queryAction = @"subscribe"; From 4f495449b3edc03d4df34068ef76cebc315f579c Mon Sep 17 00:00:00 2001 From: Chris Ballinger Date: Fri, 12 Jun 2015 17:08:25 -0700 Subject: [PATCH 034/356] XEP-0147: Change license header --- Extensions/XEP-0147/XMPPURI.h | 2 +- Extensions/XEP-0147/XMPPURI.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Extensions/XEP-0147/XMPPURI.h b/Extensions/XEP-0147/XMPPURI.h index 4198f03364..1dc90fa234 100644 --- a/Extensions/XEP-0147/XMPPURI.h +++ b/Extensions/XEP-0147/XMPPURI.h @@ -1,6 +1,6 @@ // // XMPPURI.h -// ChatSecure +// XMPPFramework // // Created by Christopher Ballinger on 5/15/15. // Copyright (c) 2015 Chris Ballinger. All rights reserved. diff --git a/Extensions/XEP-0147/XMPPURI.m b/Extensions/XEP-0147/XMPPURI.m index 672cfddde0..d3406d3b63 100644 --- a/Extensions/XEP-0147/XMPPURI.m +++ b/Extensions/XEP-0147/XMPPURI.m @@ -1,6 +1,6 @@ // // XMPPURI.m -// ChatSecure +// XMPPFramework // // Created by Christopher Ballinger on 5/15/15. // Copyright (c) 2015 Chris Ballinger. All rights reserved. From a8b541e57384dc8dfb03be716842433c28776f99 Mon Sep 17 00:00:00 2001 From: TangSilkworm Date: Wed, 17 Jun 2015 09:34:09 +0800 Subject: [PATCH 035/356] Modified two obsolete methods --- Vendor/CocoaLumberjack/DDTTYLogger.m | 12 ++++++------ .../Extensions/DDDispatchQueueLogFormatter.m | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Vendor/CocoaLumberjack/DDTTYLogger.m b/Vendor/CocoaLumberjack/DDTTYLogger.m index 9559b8102b..4d2167784b 100755 --- a/Vendor/CocoaLumberjack/DDTTYLogger.m +++ b/Vendor/CocoaLumberjack/DDTTYLogger.m @@ -833,12 +833,12 @@ - (id)init calendar = [NSCalendar autoupdatingCurrentCalendar]; calendarUnitFlags = 0; - calendarUnitFlags |= NSYearCalendarUnit; - calendarUnitFlags |= NSMonthCalendarUnit; - calendarUnitFlags |= NSDayCalendarUnit; - calendarUnitFlags |= NSHourCalendarUnit; - calendarUnitFlags |= NSMinuteCalendarUnit; - calendarUnitFlags |= NSSecondCalendarUnit; + calendarUnitFlags |= NSCalendarUnitYear; + calendarUnitFlags |= NSCalendarUnitMonth; + calendarUnitFlags |= NSCalendarUnitDay; + calendarUnitFlags |= NSCalendarUnitHour; + calendarUnitFlags |= NSCalendarUnitMinute; + calendarUnitFlags |= NSCalendarUnitSecond; // Initialze 'app' variable (char *) diff --git a/Vendor/CocoaLumberjack/Extensions/DDDispatchQueueLogFormatter.m b/Vendor/CocoaLumberjack/Extensions/DDDispatchQueueLogFormatter.m index c370740bfd..c6a4af9290 100755 --- a/Vendor/CocoaLumberjack/Extensions/DDDispatchQueueLogFormatter.m +++ b/Vendor/CocoaLumberjack/Extensions/DDDispatchQueueLogFormatter.m @@ -100,7 +100,7 @@ - (NSString *)stringFromDate:(NSDate *)date [threadUnsafeDateFormatter setDateFormat:dateFormatString]; } - [threadUnsafeDateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]]; + [threadUnsafeDateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]]; return [threadUnsafeDateFormatter stringFromDate:date]; } else @@ -122,7 +122,7 @@ - (NSString *)stringFromDate:(NSDate *)date threadDictionary[key] = dateFormatter; } - [dateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]]; + [dateFormatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]]; return [dateFormatter stringFromDate:date]; } } From d9c522215d0021c4e07637258bda1465299c8dfe Mon Sep 17 00:00:00 2001 From: Wei Han Date: Wed, 1 Jul 2015 23:34:13 +0800 Subject: [PATCH 036/356] Fixed the ToDo marker and updated the destory delegate method with IQ result. --- Extensions/XEP-0045/XMPPRoom.h | 2 +- Extensions/XEP-0045/XMPPRoom.m | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Extensions/XEP-0045/XMPPRoom.h b/Extensions/XEP-0045/XMPPRoom.h index ae82229742..399e16b603 100644 --- a/Extensions/XEP-0045/XMPPRoom.h +++ b/Extensions/XEP-0045/XMPPRoom.h @@ -284,7 +284,7 @@ static NSString *const XMPPMUCOwnerNamespace = @"http://jabber.org/protocol/muc#%20-%20(void)xmppRoomDidJoin:(XMPPRoom%20*)sender;%20-%20(void)xmppRoomDidLeave:(XMPPRoom%20*)sender;%20--%20(void)xmppRoomDidDestroy:(XMPPRoom%20*)sender;+-%20(void)xmppRoomDidDestroy:(XMPPRoom%20*)sender%20didFailToDestroy:(XMPPIQ%20*)iqError;%20%20-%20(void)xmppRoom:(XMPPRoom%20*)sender%20occupantDidJoin:(XMPPJID%20*)occupantJID%20withPresence:(XMPPPresence%20*)presence;%20-%20(void)xmppRoom:(XMPPRoom%20*)sender%20occupantDidLeave:(XMPPJID%20*)occupantJID%20withPresence:(XMPPPresence%20*)presence;diff%20--git%20a/Extensions/XEP-0045/XMPPRoom.m%20b/Extensions/XEP-0045/XMPPRoom.mindex%2022379f3b57..47dc2d688a%20100644---%20a/Extensions/XEP-0045/XMPPRoom.m+++%20b/Extensions/XEP-0045/XMPPRoom.m@@%20-488,7%20+488,13%20@@%20-%20(void)changeNickname:(NSString%20*)newNickname%20%20-%20(void)changeRoomSubject:(NSString%20*)newRoomSubject%20{-//%20Todo+%20%20%20%20NSXMLElement%20*body%20=%20[NSXMLElement%20elementWithName:@"subject" stringValue:newRoomSubject]; + + XMPPMessage *message = [XMPPMessage message]; + [message addAttributeWithName:@"from" stringValue:[myRoomJID full]]; + [message addChild:body]; + + [self sendMessage:message]; } - (void)handleFetchBanListResponse:(XMPPIQ *)iq withInfo:(id )info @@ -765,14 +771,14 @@ - (void)handleDestroyRoomResponse:(XMPPIQ *)iq withInfo:(id )i { XMPPLogTrace(); - if ([[iq type] isEqualToString:@"result"]) + if ([iq isResultIQ]) { - [multicastDelegate xmppRoomDidDestroy:self]; + [multicastDelegate xmppRoomDidDestroy:self didFailToDestroy:nil]; } else - { - // Todo... - } + { + [multicastDelegate xmppRoomDidDestroy:self didFailToDestroy:iq]; + } } - (void)destroyRoom From c9bb57f9beeaf3936b767a4e781705107ba4bcc5 Mon Sep 17 00:00:00 2001 From: Wei Han Date: Wed, 1 Jul 2015 23:39:17 +0800 Subject: [PATCH 037/356] Replace spaces with tab. --- Extensions/XEP-0045/XMPPRoom.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Extensions/XEP-0045/XMPPRoom.m b/Extensions/XEP-0045/XMPPRoom.m index 47dc2d688a..911a85672a 100644 --- a/Extensions/XEP-0045/XMPPRoom.m +++ b/Extensions/XEP-0045/XMPPRoom.m @@ -776,9 +776,9 @@ - (void)handleDestroyRoomResponse:(XMPPIQ *)iq withInfo:(id )i [multicastDelegate xmppRoomDidDestroy:self didFailToDestroy:nil]; } else - { - [multicastDelegate xmppRoomDidDestroy:self didFailToDestroy:iq]; - } + { + [multicastDelegate xmppRoomDidDestroy:self didFailToDestroy:iq]; + } } - (void)destroyRoom From 1790ae63891ba4e2d74f44d50e01a7074c7c244c Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Sat, 4 Jul 2015 16:37:07 +0100 Subject: [PATCH 038/356] Fixes API Conventions --- Extensions/XEP-0045/XMPPRoom.h | 5 ++++- Extensions/XEP-0045/XMPPRoom.m | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Extensions/XEP-0045/XMPPRoom.h b/Extensions/XEP-0045/XMPPRoom.h index 399e16b603..fd5eaa4531 100644 --- a/Extensions/XEP-0045/XMPPRoom.h +++ b/Extensions/XEP-0045/XMPPRoom.h @@ -284,7 +284,10 @@ static NSString *const XMPPMUCOwnerNamespace = @"http://jabber.org/protocol/muc#%20-%20(void)xmppRoomDidJoin:(XMPPRoom%20*)sender;%20-%20(void)xmppRoomDidLeave:(XMPPRoom%20*)sender;%20--%20(void)xmppRoomDidDestroy:(XMPPRoom%20*)sender%20didFailToDestroy:(XMPPIQ%20*)iqError;++-%20(void)xmppRoomDidDestroy:(XMPPRoom%20*)sender;+-%20(void)xmppRoom:(XMPPRoom%20*)sender%20didFailToDestroy:(XMPPIQ%20*)iqError;+%20%20-%20(void)xmppRoom:(XMPPRoom%20*)sender%20occupantDidJoin:(XMPPJID%20*)occupantJID%20withPresence:(XMPPPresence%20*)presence;%20-%20(void)xmppRoom:(XMPPRoom%20*)sender%20occupantDidLeave:(XMPPJID%20*)occupantJID%20withPresence:(XMPPPresence%20*)presence;diff%20--git%20a/Extensions/XEP-0045/XMPPRoom.m%20b/Extensions/XEP-0045/XMPPRoom.mindex%20911a85672a..1dec23ebf4%20100644---%20a/Extensions/XEP-0045/XMPPRoom.m+++%20b/Extensions/XEP-0045/XMPPRoom.m@@%20-488,11%20+488,11%20@@%20-%20(void)changeNickname:(NSString%20*)newNickname%20%20-%20(void)changeRoomSubject:(NSString%20*)newRoomSubject%20{-%20%20%20%20NSXMLElement%20*body%20=%20[NSXMLElement%20elementWithName:@"subject" stringValue:newRoomSubject]; + NSXMLElement *subject = [NSXMLElement elementWithName:@"subject" stringValue:newRoomSubject]; XMPPMessage *message = [XMPPMessage message]; [message addAttributeWithName:@"from" stringValue:[myRoomJID full]]; - [message addChild:body]; + [message addChild:subject]; [self sendMessage:message]; } @@ -773,11 +773,11 @@ - (void)handleDestroyRoomResponse:(XMPPIQ *)iq withInfo:(id )i if ([iq isResultIQ]) { - [multicastDelegate xmppRoomDidDestroy:self didFailToDestroy:nil]; + [multicastDelegate xmppRoomDidDestroy:self]; } else { - [multicastDelegate xmppRoomDidDestroy:self didFailToDestroy:iq]; + [multicastDelegate xmppRoom:self didFailToDestroy:iq]; } } From 86cb63bf5e893ecc7bca7cd098b857a85ab8e845 Mon Sep 17 00:00:00 2001 From: Joao Nunes Date: Tue, 22 Jul 2014 14:39:46 +0300 Subject: [PATCH 039/356] Added roster versioning: http://tools.ietf.org/html/rfc6121#section-2.6 --- .../XMPPRosterCoreDataStorage.m | 2 +- .../MemoryStorage/XMPPRosterMemoryStorage.m | 2 +- Extensions/Roster/XMPPRoster.h | 5 ++-- Extensions/Roster/XMPPRoster.m | 25 ++++++++++++++++--- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m b/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m index c413b524e8..ec9c6b65e8 100644 --- a/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m +++ b/Extensions/Roster/CoreDataStorage/XMPPRosterCoreDataStorage.m @@ -260,7 +260,7 @@ - (XMPPResourceCoreDataStorageObject *)resourceForJID:(XMPPJID *)jid #pragma mark Protocol Private API //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)beginRosterPopulationForXMPPStream:(XMPPStream *)stream +- (void)beginRosterPopulationForXMPPStream:(XMPPStream *)stream withVersion:(NSString *)version { XMPPLogTrace(); diff --git a/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m b/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m index b007aff9cb..cd6e4577d4 100644 --- a/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m +++ b/Extensions/Roster/MemoryStorage/XMPPRosterMemoryStorage.m @@ -610,7 +610,7 @@ - (NSArray *)sortedResources:(BOOL)includeResourcesForMyUserExcludingMyself #pragma mark XMPPRosterStorage Protocol //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)beginRosterPopulationForXMPPStream:(XMPPStream *)stream +- (void)beginRosterPopulationForXMPPStream:(XMPPStream *)stream withVersion:(NSString *)version { XMPPLogTrace(); AssertParentQueue(); diff --git a/Extensions/Roster/XMPPRoster.h b/Extensions/Roster/XMPPRoster.h index 403a18ec8c..add0256b58 100644 --- a/Extensions/Roster/XMPPRoster.h +++ b/Extensions/Roster/XMPPRoster.h @@ -172,6 +172,7 @@ * Useful if you disable autoFetchRoster. **/ - (void)fetchRoster; +- (void)fetchRosterVersion:(NSString *)version; /** * Adds the given user to the roster with an optional nickname @@ -322,7 +323,7 @@ **/ - (BOOL)configureWithParent:(XMPPRoster *)aParent queue:(dispatch_queue_t)queue; -- (void)beginRosterPopulationForXMPPStream:(XMPPStream *)stream; +- (void)beginRosterPopulationForXMPPStream:(XMPPStream *)stream withVersion:(NSString *)version; - (void)endRosterPopulationForXMPPStream:(XMPPStream *)stream; - (void)handleRosterItem:(NSXMLElement *)item xmppStream:(XMPPStream *)stream; @@ -384,7 +385,7 @@ /** * Sent when the initial roster is received. **/ -- (void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender; +- (void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender withVersion:(NSString *)version; /** * Sent when the initial roster has been populated into storage. diff --git a/Extensions/Roster/XMPPRoster.m b/Extensions/Roster/XMPPRoster.m index b4b70db4dd..65c3d89990 100644 --- a/Extensions/Roster/XMPPRoster.m +++ b/Extensions/Roster/XMPPRoster.m @@ -680,11 +680,25 @@ - (void)rejectPresenceSubscriptionRequestFrom:(XMPPJID *)jid XMPPPresence *presence = [XMPPPresence presenceWithType:@"unsubscribed" to:[jid bareJID]]; [xmppStream sendElement:presence]; } - - (void)fetchRoster { // This is a public method, so it may be invoked on any thread/queue. + dispatch_block_t block = ^{ @autoreleasepool { + + [self fetchRosterVersion:nil]; + + }}; + + if (dispatch_get_specific(moduleQueueTag)) + block(); + else + dispatch_async(moduleQueue, block); +} +- (void)fetchRosterVersion:(NSString *)version +{ + // This is a public method, so it may be invoked on any thread/queue. + dispatch_block_t block = ^{ @autoreleasepool { if ([self _requestedRoster]) @@ -694,10 +708,12 @@ - (void)fetchRoster } // - // + // // NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:roster"]; + if (version) + [query addAttributeWithName:@"ver" stringValue:version]; XMPPIQ *iq = [XMPPIQ iqWithType:@"get" elementID:[xmppStream generateUUID]]; [iq addChild:query]; @@ -727,6 +743,7 @@ - (void)handleFetchRosterQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *) dispatch_block_t block = ^{ @autoreleasepool { NSXMLElement *query = [iq elementForName:@"query" xmlns:@"jabber:iq:roster"]; + NSString * version = [query attributeStringValueForName:@"ver"]; BOOL hasRoster = [self hasRoster]; @@ -734,8 +751,8 @@ - (void)handleFetchRosterQueryIQ:(XMPPIQ *)iq withInfo:(XMPPBasicTrackingInfo *) { [xmppRosterStorage clearAllUsersAndResourcesForXMPPStream:xmppStream]; [self _setPopulatingRoster:YES]; - [multicastDelegate xmppRosterDidBeginPopulating:self]; - [xmppRosterStorage beginRosterPopulationForXMPPStream:xmppStream]; + [multicastDelegate xmppRosterDidBeginPopulating:self withVersion:version]; + [xmppRosterStorage beginRosterPopulationForXMPPStream:xmppStream withVersion:version]; } NSArray *items = [query elementsForName:@"item"]; From 600917a15cf0fdee0f8752d822ce18c0377d8f8f Mon Sep 17 00:00:00 2001 From: Spencer MacDonald Date: Sat, 25 Jul 2015 12:21:18 +0100 Subject: [PATCH 040/356] Update Comment For Roster Versioning --- Extensions/Roster/XMPPRoster.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extensions/Roster/XMPPRoster.h b/Extensions/Roster/XMPPRoster.h index add0256b58..7342eddd0b 100644 --- a/Extensions/Roster/XMPPRoster.h +++ b/Extensions/Roster/XMPPRoster.h @@ -157,7 +157,7 @@ /** * The initial roster has been received by client and is currently being populated. - * @see xmppRosterDidBeginPopulating: + * @see xmppRosterDidBeginPopulating:withVersion: * @see xmppRosterDidEndPopulating: **/ @property (assign, getter = isPopulating, readonly) BOOL populating; From c8437b39e1de54eb3aef08385f6e1b13d3fe1003 Mon Sep 17 00:00:00 2001 From: Joao Nunes Date: Tue, 22 Jul 2014 14:28:26 +0300 Subject: [PATCH 041/356] Fixed vCard update loop, after vCard is updated the storage should not be ignored but instead used --- Extensions/XEP-0153/XMPPvCardAvatarModule.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extensions/XEP-0153/XMPPvCardAvatarModule.m b/Extensions/XEP-0153/XMPPvCardAvatarModule.m index e3d0447fcb..c2c39f92ed 100755 --- a/Extensions/XEP-0153/XMPPvCardAvatarModule.m +++ b/Extensions/XEP-0153/XMPPvCardAvatarModule.m @@ -287,7 +287,7 @@ - (void)xmppvCardTempModule:(XMPPvCardTempModule *)vCardTempModule - (void)xmppvCardTempModuleDidUpdateMyvCard:(XMPPvCardTempModule *)vCardTempModule{ //The vCard has been updated on the server so we need to cache it - [_xmppvCardTempModule fetchvCardTempForJID:[xmppStream myJID] ignoreStorage:YES]; + [_xmppvCardTempModule fetchvCardTempForJID:[xmppStream myJID] ignoreStorage:NO]; } - (void)xmppvCardTempModule:(XMPPvCardTempModule *)vCardTempModule failedToUpdateMyvCard:(NSXMLElement *)error{ From e09d5a38f684dcf5494f983a9478394843cab25c Mon Sep 17 00:00:00 2001 From: Joao Nunes Date: Tue, 22 Jul 2014 12:18:32 +0300 Subject: [PATCH 042/356] Fixed typos --- Core/XMPPStream.h | 2 +- Core/XMPPStream.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/XMPPStream.h b/Core/XMPPStream.h index 67577ce763..2eafbf3a11 100644 --- a/Core/XMPPStream.h +++ b/Core/XMPPStream.h @@ -1049,7 +1049,7 @@ extern const NSTimeInterval XMPPStreamTimeoutNone; - (void)xmppStreamDidSendClosingStreamStanza:(XMPPStream *)sender; /** - * This methods is called if the XMPP stream's connect times out. + * This method is called if the XMPP stream's connect times out. **/ - (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender; diff --git a/Core/XMPPStream.m b/Core/XMPPStream.m index 604702c81c..1e329e915d 100644 --- a/Core/XMPPStream.m +++ b/Core/XMPPStream.m @@ -2544,7 +2544,7 @@ - (void)sendElement:(NSXMLElement *)element withTag:(long)tag } /** - * This methods handles sending an XML stanza. + * This method handles sending an XML stanza. * If the XMPPStream is not connected, this method does nothing. **/ - (void)sendElement:(NSXMLElement *)element From 87f79b6e339cde288ec3ed0f05210ededcfd0045 Mon Sep 17 00:00:00 2001 From: Andrew Urban Date: Thu, 6 Aug 2015 11:35:38 +0300 Subject: [PATCH 043/356] Fixed bug when mostRecentMessageTimestampForRoom returns nil --- Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m b/Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m index f835b3cbcd..b69b379fd8 100644 --- a/Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m +++ b/Extensions/XEP-0045/CoreDataStorage/XMPPRoomCoreDataStorage.m @@ -818,11 +818,11 @@ - (NSDate *)mostRecentMessageTimestampForRoom:(XMPPJID *)roomJID NSString *streamBareJidStr = [[self myJIDForXMPPStream:xmppStream] bare]; NSString *predicateFormat = @"roomJIDStr == %@ AND streamBareJidStr == %@"; - predicate = [NSPredicate predicateWithFormat:predicateFormat, roomJID, streamBareJidStr]; + predicate = [NSPredicate predicateWithFormat:predicateFormat, roomJID.bare, streamBareJidStr]; } else { - predicate = [NSPredicate predicateWithFormat:@"roomJIDStr == %@", roomJID]; + predicate = [NSPredicate predicateWithFormat:@"roomJIDStr == %@", roomJID.bare]; } NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"localTimestamp" ascending:NO]; From 8f2c94657f2a34d07e80d66cff9f9a83e603ed24 Mon Sep 17 00:00:00 2001 From: David Chiles Date: Wed, 26 Aug 2015 16:15:32 -0700 Subject: [PATCH 044/356] Added Creation of elements for XEP-0352. Really simple XEP documented here: https://xmpp.org/extensions/xep-0352.html. --- Extensions/XEP-0352/NSXMLElement+XEP_0352.h | 9 +++++++++ Extensions/XEP-0352/NSXMLElement+XEP_0352.m | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 Extensions/XEP-0352/NSXMLElement+XEP_0352.h create mode 100644 Extensions/XEP-0352/NSXMLElement+XEP_0352.m diff --git a/Extensions/XEP-0352/NSXMLElement+XEP_0352.h b/Extensions/XEP-0352/NSXMLElement+XEP_0352.h new file mode 100644 index 0000000000..7c360fc097 --- /dev/null +++ b/Extensions/XEP-0352/NSXMLElement+XEP_0352.h @@ -0,0 +1,9 @@ + +#import "NSXMLElement+XMPP.h" + +@interface NSXMLElement (XEP0352) + ++ (instancetype)indicateInactiveElement; ++ (instancetype)indicateActiveElement; + +@end diff --git a/Extensions/XEP-0352/NSXMLElement+XEP_0352.m b/Extensions/XEP-0352/NSXMLElement+XEP_0352.m new file mode 100644 index 0000000000..1e02012e0e --- /dev/null +++ b/Extensions/XEP-0352/NSXMLElement+XEP_0352.m @@ -0,0 +1,18 @@ + +#import "NSXMLElement+XEP_0352.h" + +#define XMLNS_XMPP_CLIENT_STATE_INDICATION @"urn:xmpp:csi:0" + +@implementation NSXMLElement (XEP0352) + ++ (instancetype)indicateActiveElement +{ + return [NSXMLElement elementWithName:@"active" xmlns:XMLNS_XMPP_CLIENT_STATE_INDICATION]; +} + ++ (instancetype)indicateInactiveElement +{ + return [NSXMLElement elementWithName:@"inactive" xmlns:XMLNS_XMPP_CLIENT_STATE_INDICATION]; +} + +@end From 126dc299072fe6af82e40e4ec8d5cca6368b8acc Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Thu, 27 Aug 2015 22:48:05 +0300 Subject: [PATCH 045/356] fix XEP-0066 message namespace --- Extensions/XEP-0066/XMPPMessage+XEP_0066.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extensions/XEP-0066/XMPPMessage+XEP_0066.m b/Extensions/XEP-0066/XMPPMessage+XEP_0066.m index dd9205612c..13e78db538 100644 --- a/Extensions/XEP-0066/XMPPMessage+XEP_0066.m +++ b/Extensions/XEP-0066/XMPPMessage+XEP_0066.m @@ -6,7 +6,7 @@ #endif #define NAME_OUT_OF_BAND @"x" -#define XMLNS_OUT_OF_BAND @"jabber:iq:oob" +#define XMLNS_OUT_OF_BAND @"jabber:x:oob" @implementation XMPPMessage (XEP_0066) From 5aafcdfd27b6b4403e6e357f5687fabded3362ec Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 15 Sep 2015 16:04:39 +0200 Subject: [PATCH 046/356] Fixed dns_sd and libxml2 import (modulemap file addition) + fixed circular import in podspec with full swift support --- Core/XMPPLogging.h | 2 +- Core/XMPPStream.h | 2 +- Sample_XMPPFramework.h | 79 ----- Utilities/XMPPSRVResolver.h | 7 +- Utilities/XMPPSRVResolver.m | 4 + Vendor/KissXML/Categories/NSString+DDXML.h | 6 +- Vendor/KissXML/DDXMLNode.h | 7 +- XMPPFramework.h | 1 + XMPPFramework.podspec | 319 +++++++++++++++++++++ module/module.modulemap | 19 ++ 10 files changed, 362 insertions(+), 84 deletions(-) delete mode 100644 Sample_XMPPFramework.h create mode 100644 XMPPFramework.h create mode 100644 XMPPFramework.podspec create mode 100644 module/module.modulemap diff --git a/Core/XMPPLogging.h b/Core/XMPPLogging.h index c6e8bfab6f..975ee67d83 100644 --- a/Core/XMPPLogging.h +++ b/Core/XMPPLogging.h @@ -59,7 +59,7 @@ * If you created your project with a previous version of Xcode, you may need to add the DEBUG macro manually. **/ -#import "DDLog.h" +#import "CocoaLumberJack/DDLog.h" // Global flag to enable/disable logging throughout the entire xmpp framework. diff --git a/Core/XMPPStream.h b/Core/XMPPStream.h index 2eafbf3a11..39d4c0d3b3 100644 --- a/Core/XMPPStream.h +++ b/Core/XMPPStream.h @@ -1,8 +1,8 @@ #import #import "XMPPSASLAuthentication.h" #import "XMPPCustomBinding.h" -#import "GCDAsyncSocket.h" #import "GCDMulticastDelegate.h" +#import "CocoaAsyncSocket/GCDAsyncSocket.h" #if TARGET_OS_IPHONE #import "DDXML.h" diff --git a/Sample_XMPPFramework.h b/Sample_XMPPFramework.h deleted file mode 100644 index 65bf268f09..0000000000 --- a/Sample_XMPPFramework.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// This file is designed to be customized by YOU. -// -// Copy this file and rename it to "XMPPFramework.h". Then add it to your project. -// As you pick and choose which parts of the framework you need for your application, add them to this header file. -// -// Various modules available within the framework optionally interact with each other. -// E.g. The XMPPPing module utilizes the XMPPCapabilities module to advertise support XEP-0199. -// -// However, the modules can only interact if they're both added to your xcode project. -// E.g. If XMPPCapabilities isn't a part of your xcode project, then XMPPPing shouldn't attempt to reference it. -// -// So how do the individual modules know if other modules are available? -// Via this header file. -// -// If you #import "XMPPCapabilities.h" in this file, then _XMPP_CAPABILITIES_H will be defined for other modules. -// And they can automatically take advantage of it. -// - -// CUSTOMIZE ME ! -// THIS HEADER FILE SHOULD BE TAILORED TO MATCH YOUR APPLICATION. - -// The following is standard: - -#import "XMPP.h" - -// List the modules you're using here: -// (the following may not be a complete list) - -//#import "XMPPBandwidthMonitor.h" -// -//#import "XMPPCoreDataStorage.h" -// -//#import "XMPPReconnect.h" -// -//#import "XMPPRoster.h" -//#import "XMPPRosterMemoryStorage.h" -//#import "XMPPRosterCoreDataStorage.h" -// -//#import "XMPPJabberRPCModule.h" -//#import "XMPPIQ+JabberRPC.h" -//#import "XMPPIQ+JabberRPCResponse.h" -// -//#import "XMPPPrivacy.h" -// -//#import "XMPPMUC.h" -//#import "XMPPRoom.h" -//#import "XMPPRoomMemoryStorage.h" -//#import "XMPPRoomCoreDataStorage.h" -//#import "XMPPRoomHybridStorage.h" -// -//#import "XMPPvCardTempModule.h" -//#import "XMPPvCardCoreDataStorage.h" -// -//#import "XMPPPubSub.h" -// -//#import "TURNSocket.h" -// -//#import "XMPPDateTimeProfiles.h" -//#import "NSDate+XMPPDateTimeProfiles.h" -// -//#import "XMPPMessage+XEP_0085.h" -// -//#import "XMPPTransports.h" -// -//#import "XMPPCapabilities.h" -//#import "XMPPCapabilitiesCoreDataStorage.h" -// -//#import "XMPPvCardAvatarModule.h" -// -//#import "XMPPMessage+XEP_0184.h" -// -//#import "XMPPPing.h" -//#import "XMPPAutoPing.h" -// -//#import "XMPPTime.h" -//#import "XMPPAutoTime.h" -// -//#import "XMPPElement+Delay.h" diff --git a/Utilities/XMPPSRVResolver.h b/Utilities/XMPPSRVResolver.h index 3d9ce0d7ea..b1411c6b4a 100644 --- a/Utilities/XMPPSRVResolver.h +++ b/Utilities/XMPPSRVResolver.h @@ -6,7 +6,12 @@ // #import -#import + +#if !(TARGET_IPHONE_SIMULATOR) +@import dnssd; +#else +@import dnssdSimu; +#endif extern NSString *const XMPPSRVResolverErrorDomain; diff --git a/Utilities/XMPPSRVResolver.m b/Utilities/XMPPSRVResolver.m index 8faa6ea8cb..7a4c543675 100644 --- a/Utilities/XMPPSRVResolver.m +++ b/Utilities/XMPPSRVResolver.m @@ -8,6 +8,10 @@ #import "XMPPSRVResolver.h" #import "XMPPLogging.h" +//#warning Fix "dns.h" issue without resorting to this ugly hack. +// This is a hack to prevent OnionKit's clobbering of the actual system's +//#include "/usr/include/dns.h" + #include #include diff --git a/Vendor/KissXML/Categories/NSString+DDXML.h b/Vendor/KissXML/Categories/NSString+DDXML.h index f077f90aeb..e9b919e49d 100644 --- a/Vendor/KissXML/Categories/NSString+DDXML.h +++ b/Vendor/KissXML/Categories/NSString+DDXML.h @@ -1,6 +1,10 @@ #import -#import +#if !(TARGET_IPHONE_SIMULATOR) +@import libxml; +#else +@import libxmlSimu; +#endif @interface NSString (DDXML) diff --git a/Vendor/KissXML/DDXMLNode.h b/Vendor/KissXML/DDXMLNode.h index 5d49862d56..65980b9599 100644 --- a/Vendor/KissXML/DDXMLNode.h +++ b/Vendor/KissXML/DDXMLNode.h @@ -1,5 +1,10 @@ #import -#import + +#if !(TARGET_IPHONE_SIMULATOR) +@import libxml; +#else +@import libxmlSimu; +#endif @class DDXMLDocument; diff --git a/XMPPFramework.h b/XMPPFramework.h new file mode 100644 index 0000000000..46fc5f559c --- /dev/null +++ b/XMPPFramework.h @@ -0,0 +1 @@ +#import "XMPP.h" diff --git a/XMPPFramework.podspec b/XMPPFramework.podspec new file mode 100644 index 0000000000..3b5f200cad --- /dev/null +++ b/XMPPFramework.podspec @@ -0,0 +1,319 @@ +Pod::Spec.new do |s| +s.name = 'XMPPFramework' +s.version = '3.6.6' + +s.osx.deployment_target = '10.7' +s.ios.deployment_target = '6.0' + +s.platform = :osx, '10.7' +s.platform = :ios, '6.0' + +s.ios.frameworks = 'UIKit', 'Foundation' +s.osx.frameworks = 'Cocoa' + +s.license = { :type => 'BSD', :file => 'copying.txt' } +s.summary = 'An XMPP Framework in Objective-C for the Mac / iOS development community.' +s.homepage = 'https://github.com/processOne/XMPPFramework' +s.author = { 'Robbie Hanson' => 'robbiehanson@deusty.com' } +s.source = { :git => 'https://github.com/processOne/XMPPFramework.git', :tag => s.version } +s.resources = [ '**/*.{xcdatamodel,xcdatamodeld}'] + +s.description = 'XMPPFramework provides a core implementation of RFC-3920 (the xmpp standard), along with +the tools needed to read & write XML. It comes with multiple popular extensions (XEPs), +all built atop a modular architecture, allowing you to plug-in any code needed for the job. +Additionally the framework is massively parallel and thread-safe. Structured using GCD, +this framework performs well regardless of whether it\'s being run on an old iPhone, or +on a 12-core Mac Pro. (And it won\'t block the main thread... at all).' + +s.requires_arc = true + +# XMPPFramework.h is used internally in the framework to let modules know +# what other optional modules are available. Since we don't know yet which +# subspecs have been selected, include all of them wrapped in defines which +# will be set by the relevant subspecs. + +s.prepare_command = <<-'END' +echo '#import "XMPP.h"' > XMPPFramework.h +grep '#define _XMPP_' -r /Extensions \ +| tr '-' '_' \ +| perl -pe 's/Extensions\/([A-z0-9_]*)\/([A-z]*.h).*/\n#ifdef HAVE_XMPP_SUBSPEC_\U\1\n\E#import "\2"\n#endif/' \ +>> XMPPFramework.h +END + +s.preserve_path = 'module/module.modulemap' +#s.module_map = 'module/module.modulemap' + +s.subspec 'Core' do |core| +core.source_files = ['XMPPFramework.h', 'Core/**/*.{h,m}', 'Vendor/libidn/*.h', 'Authentication/**/*.{h,m}', 'Categories/**/*.{h,m}', 'Utilities/**/*.{h,m}'] +core.vendored_libraries = 'Vendor/libidn/libidn.a' +core.libraries = 'xml2', 'resolv' +core.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(inherited) $(SDKROOT)/usr/include/libxml2 $(PODS_ROOT)/XMPPFramework/module $(SDKROOT)/usr/include/libresolv', +'LIBRARY_SEARCH_PATHS' => '"$(PODS_ROOT)/XMPPFramework/Vendor/libidn"', 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES', 'OTHER_LDFLAGS' => '"-lxml2"', 'ENABLE_BITCODE' => 'NO' +} +core.dependency 'CocoaLumberjack','~>1.9' +core.dependency 'CocoaAsyncSocket','~>7.4.1' +core.ios.dependency 'XMPPFramework/KissXML' +end + +s.subspec 'Authentication' do |ss| +ss.dependency 'XMPPFramework/Core' +end + +s.subspec 'Categories' do |ss| +ss.dependency 'XMPPFramework/Core' +end + +s.subspec 'Utilities' do |ss| +ss.dependency 'XMPPFramework/Core' +end + +s.subspec 'KissXML' do |ss| +ss.source_files = ['Vendor/KissXML/**/*.{h,m}', 'module/module.modulemap'] +ss.libraries = 'xml2','resolv' +ss.xcconfig = { +'HEADER_SEARCH_PATHS' => '$(inherited) $(SDKROOT)/usr/include/libxml2 $(PODS_ROOT)/XMPPFramework/module $(SDKROOT)/usr/include/libresolv' +} +end + +s.subspec 'BandwidthMonitor' do |ss| +ss.source_files = 'Extensions/BandwidthMonitor/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'CoreDataStorage' do |ss| +ss.source_files = ['Extensions/CoreDataStorage/**/*.{h,m}', 'Extensions/XEP-0203/NSXMLElement+XEP_0203.h'] +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +ss.framework = 'CoreData' +end + +s.subspec 'GoogleSharedStatus' do |ss| +ss.source_files = 'Extensions/GoogleSharedStatus/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'ProcessOne' do |ss| +ss.source_files = 'Extensions/ProcessOne/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'Reconnect' do |ss| +ss.source_files = 'Extensions/Reconnect/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +ss.framework = 'SystemConfiguration' +end + +s.subspec 'Roster' do |ss| +ss.source_files = 'Extensions/Roster/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.dependency 'XMPPFramework/CoreDataStorage' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'SystemInputActivityMonitor' do |ss| +ss.source_files = ['Extensions/SystemInputActivityMonitor/**/*.{h,m}', 'Utilities/GCDMulticastDelegate.h'] +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0009' do |ss| +ss.source_files = 'Extensions/XEP-0009/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0012' do |ss| +ss.source_files = 'Extensions/XEP-0012/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0016' do |ss| +ss.source_files = 'Extensions/XEP-0016/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0045' do |ss| +ss.source_files = 'Extensions/XEP-0045/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.dependency 'XMPPFramework/CoreDataStorage' +ss.dependency 'XMPPFramework/XEP-0203' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0054' do |ss| +ss.source_files = ['Extensions/XEP-0054/**/*.{h,m}', 'Extensions/XEP-0153/XMPPvCardAvatarModule.h', 'Extensions/XEP-0082/XMPPDateTimeProfiles.h', 'Extensions/XEP-0082/NSDate+XMPPDateTimeProfiles.h'] +ss.dependency 'XMPPFramework/Core' +ss.dependency 'XMPPFramework/Roster' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +ss.framework = 'CoreLocation' +end + +s.subspec 'XEP-0059' do |ss| +ss.source_files = 'Extensions/XEP-0059/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0060' do |ss| +ss.source_files = 'Extensions/XEP-0060/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0065' do |ss| +ss.source_files = 'Extensions/XEP-0065/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0066' do |ss| +ss.source_files = 'Extensions/XEP-0066/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0082' do |ss| +ss.source_files = 'Extensions/XEP-0082/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0085' do |ss| +ss.source_files = 'Extensions/XEP-0085/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0092' do |ss| +ss.source_files = 'Extensions/XEP-0092/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0100' do |ss| +ss.source_files = 'Extensions/XEP-0100/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0106' do |ss| +ss.source_files = 'Extensions/XEP-0106/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0115' do |ss| +ss.source_files = 'Extensions/XEP-0115/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.dependency 'XMPPFramework/CoreDataStorage' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0136' do |ss| +ss.source_files = 'Extensions/XEP-0136/**/*.{h,m}' +ss.dependency 'XMPPFramework/CoreDataStorage' +ss.dependency 'XMPPFramework/XEP-0203' +ss.dependency 'XMPPFramework/XEP-0085' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0153' do |ss| +ss.source_files = ['Extensions/XEP-0153/**/*.{h,m}', 'Extensions/XEP-0082/NSDate+XMPPDateTimeProfiles.h'] +ss.dependency 'XMPPFramework/Core' +ss.dependency 'XMPPFramework/XEP-0054' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0172' do |ss| +ss.source_files = 'Extensions/XEP-0172/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0184' do |ss| +ss.source_files = 'Extensions/XEP-0184/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0191' do |ss| +ss.source_files = 'Extensions/XEP-0191/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0198' do |ss| +ss.source_files = 'Extensions/XEP-0198/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0199' do |ss| +ss.source_files = 'Extensions/XEP-0199/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0202' do |ss| +ss.source_files = 'Extensions/XEP-0202/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.dependency 'XMPPFramework/XEP-0082' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0203' do |ss| +ss.source_files = 'Extensions/XEP-0203/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.dependency 'XMPPFramework/XEP-0082' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0223' do |ss| +ss.source_files = 'Extensions/XEP-0223/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0224' do |ss| +ss.source_files = 'Extensions/XEP-0224/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0280' do |ss| +ss.source_files = ['Extensions/XEP-0280/**/*.{h,m}', 'Extensions/XEP-0297/NSXMLElement+XEP_0297.h'] +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0297' do |ss| +ss.source_files = ['Extensions/XEP-0297/**/*.{h,m}', 'Extensions/XEP-0203/**/*.h'] +ss.dependency 'XMPPFramework/Core' +ss.dependency 'XMPPFramework/XEP-0203' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0308' do |ss| +ss.source_files = 'Extensions/XEP-0308/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0333' do |ss| +ss.source_files = 'Extensions/XEP-0333/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end + +s.subspec 'XEP-0335' do |ss| +ss.source_files = 'Extensions/XEP-0335/**/*.{h,m}' +ss.dependency 'XMPPFramework/Core' +ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" +end +end \ No newline at end of file diff --git a/module/module.modulemap b/module/module.modulemap new file mode 100644 index 0000000000..26af0b9ed7 --- /dev/null +++ b/module/module.modulemap @@ -0,0 +1,19 @@ +module libxml [system] { + header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/tree.h" + export * +} + +module libxmlSimu [system] { + header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/libxml2/libxml/tree.h" + export * +} + +module dnssd [system] { + header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/dns_sd.h" + export * +} + +module dnssdSimu [system] { + header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/dns_sd.h" + export * +} \ No newline at end of file From c19c93be4afad1081fefd0fdb6ba790921ad11ae Mon Sep 17 00:00:00 2001 From: Chris Ballinger Date: Fri, 22 Jan 2016 13:45:24 -0800 Subject: [PATCH 047/356] Attempt to fix Travis build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1bad97a888..e31967d21f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ # * http://www.objc.io/issue-6/travis-ci.html # * https://github.com/supermarin/xcpretty#usage +osx_image: xcode7.2 language: objective-c before_install: - gem install cocoapods --no-rdoc --no-ri --no-document --quiet # Since Travis is not always on latest version From e8976cd8ddd69cbb8a5aea6d3ba1aefc19086f0b Mon Sep 17 00:00:00 2001 From: Chris Ballinger Date: Fri, 22 Jan 2016 14:13:05 -0800 Subject: [PATCH 048/356] Use xctool --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e31967d21f..d19749025a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,5 @@ before_install: install: - gem install xcpretty --no-rdoc --no-ri --no-document --quiet script: -- set -o pipefail && xcodebuild test -workspace Xcode/Testing2/XMPPFrameworkTests.xcworkspace -scheme XMPPFrameworkTests -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=8.1' | xcpretty -c +# - set -o pipefail && xcodebuild test -workspace -scheme XMPPFrameworkTests -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=8.1' | xcpretty -c +- xctool -workspace Xcode/Testing2/XMPPFrameworkTests.xcworkspace -scheme XMPPFrameworkTests -sdk iphonesimulator -arch i386 test \ No newline at end of file From ddb1c4f9213bbd72230c59e47421fbe404ddd514 Mon Sep 17 00:00:00 2001 From: David Chiles Date: Mon, 25 Jan 2016 17:50:57 -0800 Subject: [PATCH 049/356] Able to build project with modified podspec --- Utilities/XMPPSRVResolver.h | 7 +- XMPPFramework.podspec | 14 +- Xcode/Testing2/Podfile.lock | 10 - Xcode/Testing3/.gitignore | 47 ++ Xcode/Testing3/Podfile | 16 + Xcode/Testing3/Podfile.lock | 163 ++++++ .../XMPPFramework.xcodeproj/project.pbxproj | 554 ++++++++++++++++++ .../contents.xcworkspacedata | 10 + Xcode/Testing3/XMPPFramework/AppDelegate.h | 17 + Xcode/Testing3/XMPPFramework/AppDelegate.m | 46 ++ .../AppIcon.appiconset/Contents.json | 68 +++ .../Base.lproj/LaunchScreen.storyboard | 27 + .../XMPPFramework/Base.lproj/Main.storyboard | 25 + Xcode/Testing3/XMPPFramework/Info.plist | 47 ++ Xcode/Testing3/XMPPFramework/ViewController.h | 15 + Xcode/Testing3/XMPPFramework/ViewController.m | 27 + Xcode/Testing3/XMPPFramework/main.m | 16 + Xcode/Testing3/XMPPFrameworkTests/Info.plist | 24 + .../XMPPFrameworkTests/XMPPFrameworkTests.m | 40 ++ 19 files changed, 1146 insertions(+), 27 deletions(-) delete mode 100644 Xcode/Testing2/Podfile.lock create mode 100644 Xcode/Testing3/.gitignore create mode 100644 Xcode/Testing3/Podfile create mode 100644 Xcode/Testing3/Podfile.lock create mode 100644 Xcode/Testing3/XMPPFramework.xcodeproj/project.pbxproj create mode 100644 Xcode/Testing3/XMPPFramework.xcworkspace/contents.xcworkspacedata create mode 100644 Xcode/Testing3/XMPPFramework/AppDelegate.h create mode 100644 Xcode/Testing3/XMPPFramework/AppDelegate.m create mode 100644 Xcode/Testing3/XMPPFramework/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Xcode/Testing3/XMPPFramework/Base.lproj/LaunchScreen.storyboard create mode 100644 Xcode/Testing3/XMPPFramework/Base.lproj/Main.storyboard create mode 100644 Xcode/Testing3/XMPPFramework/Info.plist create mode 100644 Xcode/Testing3/XMPPFramework/ViewController.h create mode 100644 Xcode/Testing3/XMPPFramework/ViewController.m create mode 100644 Xcode/Testing3/XMPPFramework/main.m create mode 100644 Xcode/Testing3/XMPPFrameworkTests/Info.plist create mode 100644 Xcode/Testing3/XMPPFrameworkTests/XMPPFrameworkTests.m diff --git a/Utilities/XMPPSRVResolver.h b/Utilities/XMPPSRVResolver.h index b1411c6b4a..3d9ce0d7ea 100644 --- a/Utilities/XMPPSRVResolver.h +++ b/Utilities/XMPPSRVResolver.h @@ -6,12 +6,7 @@ // #import - -#if !(TARGET_IPHONE_SIMULATOR) -@import dnssd; -#else -@import dnssdSimu; -#endif +#import extern NSString *const XMPPSRVResolverErrorDomain; diff --git a/XMPPFramework.podspec b/XMPPFramework.podspec index 3b5f200cad..c515122a6d 100644 --- a/XMPPFramework.podspec +++ b/XMPPFramework.podspec @@ -39,7 +39,7 @@ grep '#define _XMPP_' -r /Extensions \ | perl -pe 's/Extensions\/([A-z0-9_]*)\/([A-z]*.h).*/\n#ifdef HAVE_XMPP_SUBSPEC_\U\1\n\E#import "\2"\n#endif/' \ >> XMPPFramework.h END - + s.preserve_path = 'module/module.modulemap' #s.module_map = 'module/module.modulemap' @@ -52,7 +52,7 @@ core.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(inherited) $(SDKROOT)/usr/include/ } core.dependency 'CocoaLumberjack','~>1.9' core.dependency 'CocoaAsyncSocket','~>7.4.1' -core.ios.dependency 'XMPPFramework/KissXML' +core.dependency 'KissXML', '~> 5.0' end s.subspec 'Authentication' do |ss| @@ -67,14 +67,6 @@ s.subspec 'Utilities' do |ss| ss.dependency 'XMPPFramework/Core' end -s.subspec 'KissXML' do |ss| -ss.source_files = ['Vendor/KissXML/**/*.{h,m}', 'module/module.modulemap'] -ss.libraries = 'xml2','resolv' -ss.xcconfig = { -'HEADER_SEARCH_PATHS' => '$(inherited) $(SDKROOT)/usr/include/libxml2 $(PODS_ROOT)/XMPPFramework/module $(SDKROOT)/usr/include/libresolv' -} -end - s.subspec 'BandwidthMonitor' do |ss| ss.source_files = 'Extensions/BandwidthMonitor/**/*.{h,m}' ss.dependency 'XMPPFramework/Core' @@ -316,4 +308,4 @@ ss.source_files = 'Extensions/XEP-0335/**/*.{h,m}' ss.dependency 'XMPPFramework/Core' ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}" end -end \ No newline at end of file +end diff --git a/Xcode/Testing2/Podfile.lock b/Xcode/Testing2/Podfile.lock deleted file mode 100644 index 8ba75d67bd..0000000000 --- a/Xcode/Testing2/Podfile.lock +++ /dev/null @@ -1,10 +0,0 @@ -PODS: - - OCMock (3.1.2) - -DEPENDENCIES: - - OCMock (~> 3.1) - -SPEC CHECKSUMS: - OCMock: a10ea9f0a6e921651f96f78b6faee95ebc813b92 - -COCOAPODS: 0.37.2 diff --git a/Xcode/Testing3/.gitignore b/Xcode/Testing3/.gitignore new file mode 100644 index 0000000000..c3a5df543c --- /dev/null +++ b/Xcode/Testing3/.gitignore @@ -0,0 +1,47 @@ +#### joe made this: http://goel.io/joe + +#####=== OSX ===##### +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +#####=== Objective-C ===##### + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +# CocoaPods +Pods/ diff --git a/Xcode/Testing3/Podfile b/Xcode/Testing3/Podfile new file mode 100644 index 0000000000..9c543956bf --- /dev/null +++ b/Xcode/Testing3/Podfile @@ -0,0 +1,16 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '8.0' +# Uncomment this line if you're using Swift +use_frameworks! + +target 'XMPPFramework' do + + pod "XMPPFramework", :path => "../../" + +end + +target 'XMPPFrameworkTests' do + + pod "XMPPFramework", :path => "../../" + +end diff --git a/Xcode/Testing3/Podfile.lock b/Xcode/Testing3/Podfile.lock new file mode 100644 index 0000000000..609b4d2082 --- /dev/null +++ b/Xcode/Testing3/Podfile.lock @@ -0,0 +1,163 @@ +PODS: + - CocoaAsyncSocket (7.4.2) + - CocoaLumberjack (1.9.2): + - CocoaLumberjack/Extensions (= 1.9.2) + - CocoaLumberjack/Core (1.9.2) + - CocoaLumberjack/Extensions (1.9.2): + - CocoaLumberjack/Core + - KissXML (5.0) + - XMPPFramework (3.6.6): + - XMPPFramework/Authentication (= 3.6.6) + - XMPPFramework/BandwidthMonitor (= 3.6.6) + - XMPPFramework/Categories (= 3.6.6) + - XMPPFramework/Core (= 3.6.6) + - XMPPFramework/CoreDataStorage (= 3.6.6) + - XMPPFramework/GoogleSharedStatus (= 3.6.6) + - XMPPFramework/ProcessOne (= 3.6.6) + - XMPPFramework/Reconnect (= 3.6.6) + - XMPPFramework/Roster (= 3.6.6) + - XMPPFramework/SystemInputActivityMonitor (= 3.6.6) + - XMPPFramework/Utilities (= 3.6.6) + - XMPPFramework/XEP-0009 (= 3.6.6) + - XMPPFramework/XEP-0012 (= 3.6.6) + - XMPPFramework/XEP-0016 (= 3.6.6) + - XMPPFramework/XEP-0045 (= 3.6.6) + - XMPPFramework/XEP-0054 (= 3.6.6) + - XMPPFramework/XEP-0059 (= 3.6.6) + - XMPPFramework/XEP-0060 (= 3.6.6) + - XMPPFramework/XEP-0065 (= 3.6.6) + - XMPPFramework/XEP-0066 (= 3.6.6) + - XMPPFramework/XEP-0082 (= 3.6.6) + - XMPPFramework/XEP-0085 (= 3.6.6) + - XMPPFramework/XEP-0092 (= 3.6.6) + - XMPPFramework/XEP-0100 (= 3.6.6) + - XMPPFramework/XEP-0106 (= 3.6.6) + - XMPPFramework/XEP-0115 (= 3.6.6) + - XMPPFramework/XEP-0136 (= 3.6.6) + - XMPPFramework/XEP-0153 (= 3.6.6) + - XMPPFramework/XEP-0172 (= 3.6.6) + - XMPPFramework/XEP-0184 (= 3.6.6) + - XMPPFramework/XEP-0191 (= 3.6.6) + - XMPPFramework/XEP-0198 (= 3.6.6) + - XMPPFramework/XEP-0199 (= 3.6.6) + - XMPPFramework/XEP-0202 (= 3.6.6) + - XMPPFramework/XEP-0203 (= 3.6.6) + - XMPPFramework/XEP-0223 (= 3.6.6) + - XMPPFramework/XEP-0224 (= 3.6.6) + - XMPPFramework/XEP-0280 (= 3.6.6) + - XMPPFramework/XEP-0297 (= 3.6.6) + - XMPPFramework/XEP-0308 (= 3.6.6) + - XMPPFramework/XEP-0333 (= 3.6.6) + - XMPPFramework/XEP-0335 (= 3.6.6) + - XMPPFramework/Authentication (3.6.6): + - XMPPFramework/Core + - XMPPFramework/BandwidthMonitor (3.6.6): + - XMPPFramework/Core + - XMPPFramework/Categories (3.6.6): + - XMPPFramework/Core + - XMPPFramework/Core (3.6.6): + - CocoaAsyncSocket (~> 7.4.1) + - CocoaLumberjack (~> 1.9) + - KissXML (~> 5.0) + - XMPPFramework/CoreDataStorage (3.6.6): + - XMPPFramework/Core + - XMPPFramework/GoogleSharedStatus (3.6.6): + - XMPPFramework/Core + - XMPPFramework/ProcessOne (3.6.6): + - XMPPFramework/Core + - XMPPFramework/Reconnect (3.6.6): + - XMPPFramework/Core + - XMPPFramework/Roster (3.6.6): + - XMPPFramework/Core + - XMPPFramework/CoreDataStorage + - XMPPFramework/SystemInputActivityMonitor (3.6.6): + - XMPPFramework/Core + - XMPPFramework/Utilities (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0009 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0012 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0016 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0045 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/CoreDataStorage + - XMPPFramework/XEP-0203 + - XMPPFramework/XEP-0054 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/Roster + - XMPPFramework/XEP-0059 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0060 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0065 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0066 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0082 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0085 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0092 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0100 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0106 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0115 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/CoreDataStorage + - XMPPFramework/XEP-0136 (3.6.6): + - XMPPFramework/CoreDataStorage + - XMPPFramework/XEP-0085 + - XMPPFramework/XEP-0203 + - XMPPFramework/XEP-0153 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0054 + - XMPPFramework/XEP-0172 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0184 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0191 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0198 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0199 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0202 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0082 + - XMPPFramework/XEP-0203 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0082 + - XMPPFramework/XEP-0223 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0224 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0280 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0297 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0203 + - XMPPFramework/XEP-0308 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0333 (3.6.6): + - XMPPFramework/Core + - XMPPFramework/XEP-0335 (3.6.6): + - XMPPFramework/Core + +DEPENDENCIES: + - XMPPFramework (from `../../`) + +EXTERNAL SOURCES: + XMPPFramework: + :path: ../../ + +SPEC CHECKSUMS: + CocoaAsyncSocket: f5783bdedd232d91b89769bc4b5a1580aed518ad + CocoaLumberjack: 628fca2e88ef06f7cf6817309aa405f325d9a6fa + KissXML: ce643413d618ad69886d0d43c3792b7dedfe476e + XMPPFramework: a46b10e748e0362ded10a517acead156f32536db + +COCOAPODS: 0.39.0 diff --git a/Xcode/Testing3/XMPPFramework.xcodeproj/project.pbxproj b/Xcode/Testing3/XMPPFramework.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..2e2a02f8b8 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework.xcodeproj/project.pbxproj @@ -0,0 +1,554 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 533E30E1F3875E9E77F8B3A5 /* Pods_XMPPFrameworkTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C23E1F52CFC47B8B42254BAB /* Pods_XMPPFrameworkTests.framework */; }; + 63C474B81C506285009262C4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 63C474B71C506285009262C4 /* main.m */; }; + 63C474BB1C506285009262C4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 63C474BA1C506285009262C4 /* AppDelegate.m */; }; + 63C474BE1C506285009262C4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 63C474BD1C506285009262C4 /* ViewController.m */; }; + 63C474C11C506285009262C4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 63C474BF1C506285009262C4 /* Main.storyboard */; }; + 63C474C31C506285009262C4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 63C474C21C506285009262C4 /* Assets.xcassets */; }; + 63C474C61C506285009262C4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 63C474C41C506285009262C4 /* LaunchScreen.storyboard */; }; + 63C474D11C506286009262C4 /* XMPPFrameworkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63C474D01C506286009262C4 /* XMPPFrameworkTests.m */; }; + BD00408A9A7F63DBD52270C2 /* Pods_XMPPFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD69BB24B1ED6EA9F25BD347 /* Pods_XMPPFramework.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 63C474CD1C506286009262C4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 63C474AB1C506285009262C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 63C474B21C506285009262C4; + remoteInfo = XMPPFramework; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0F2C34BA02B0D5002F32FBAF /* Pods-XMPPFrameworkTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFrameworkTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-XMPPFrameworkTests/Pods-XMPPFrameworkTests.debug.xcconfig"; sourceTree = ""; }; + 1D4F2FBA2F4988EC89DD5834 /* Pods-XMPPFramework.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFramework.release.xcconfig"; path = "Pods/Target Support Files/Pods-XMPPFramework/Pods-XMPPFramework.release.xcconfig"; sourceTree = ""; }; + 596BDF1156054499B58DE613 /* Pods-XMPPFramework.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFramework.debug.xcconfig"; path = "Pods/Target Support Files/Pods-XMPPFramework/Pods-XMPPFramework.debug.xcconfig"; sourceTree = ""; }; + 63C474B31C506285009262C4 /* XMPPFramework.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XMPPFramework.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 63C474B71C506285009262C4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 63C474B91C506285009262C4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 63C474BA1C506285009262C4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 63C474BC1C506285009262C4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 63C474BD1C506285009262C4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 63C474C01C506285009262C4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 63C474C21C506285009262C4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 63C474C51C506285009262C4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 63C474C71C506285009262C4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 63C474CC1C506286009262C4 /* XMPPFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XMPPFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 63C474D01C506286009262C4 /* XMPPFrameworkTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XMPPFrameworkTests.m; sourceTree = ""; }; + 63C474D21C506286009262C4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 70AFF6225A28CB83C1C8AA26 /* Pods-XMPPFrameworkTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XMPPFrameworkTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-XMPPFrameworkTests/Pods-XMPPFrameworkTests.release.xcconfig"; sourceTree = ""; }; + BD69BB24B1ED6EA9F25BD347 /* Pods_XMPPFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_XMPPFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C23E1F52CFC47B8B42254BAB /* Pods_XMPPFrameworkTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_XMPPFrameworkTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 63C474B01C506285009262C4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BD00408A9A7F63DBD52270C2 /* Pods_XMPPFramework.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 63C474C91C506286009262C4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 533E30E1F3875E9E77F8B3A5 /* Pods_XMPPFrameworkTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 47131C0DC0AD7161913D2AA5 /* Pods */ = { + isa = PBXGroup; + children = ( + 596BDF1156054499B58DE613 /* Pods-XMPPFramework.debug.xcconfig */, + 1D4F2FBA2F4988EC89DD5834 /* Pods-XMPPFramework.release.xcconfig */, + 0F2C34BA02B0D5002F32FBAF /* Pods-XMPPFrameworkTests.debug.xcconfig */, + 70AFF6225A28CB83C1C8AA26 /* Pods-XMPPFrameworkTests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 63C474AA1C506285009262C4 = { + isa = PBXGroup; + children = ( + 63C474B51C506285009262C4 /* XMPPFramework */, + 63C474CF1C506286009262C4 /* XMPPFrameworkTests */, + 63C474B41C506285009262C4 /* Products */, + 47131C0DC0AD7161913D2AA5 /* Pods */, + ADAF52A70A174F0BD024C0AC /* Frameworks */, + ); + sourceTree = ""; + }; + 63C474B41C506285009262C4 /* Products */ = { + isa = PBXGroup; + children = ( + 63C474B31C506285009262C4 /* XMPPFramework.app */, + 63C474CC1C506286009262C4 /* XMPPFrameworkTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 63C474B51C506285009262C4 /* XMPPFramework */ = { + isa = PBXGroup; + children = ( + 63C474B91C506285009262C4 /* AppDelegate.h */, + 63C474BA1C506285009262C4 /* AppDelegate.m */, + 63C474BC1C506285009262C4 /* ViewController.h */, + 63C474BD1C506285009262C4 /* ViewController.m */, + 63C474BF1C506285009262C4 /* Main.storyboard */, + 63C474C21C506285009262C4 /* Assets.xcassets */, + 63C474C41C506285009262C4 /* LaunchScreen.storyboard */, + 63C474C71C506285009262C4 /* Info.plist */, + 63C474B61C506285009262C4 /* Supporting Files */, + ); + path = XMPPFramework; + sourceTree = ""; + }; + 63C474B61C506285009262C4 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 63C474B71C506285009262C4 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 63C474CF1C506286009262C4 /* XMPPFrameworkTests */ = { + isa = PBXGroup; + children = ( + 63C474D01C506286009262C4 /* XMPPFrameworkTests.m */, + 63C474D21C506286009262C4 /* Info.plist */, + ); + path = XMPPFrameworkTests; + sourceTree = ""; + }; + ADAF52A70A174F0BD024C0AC /* Frameworks */ = { + isa = PBXGroup; + children = ( + BD69BB24B1ED6EA9F25BD347 /* Pods_XMPPFramework.framework */, + C23E1F52CFC47B8B42254BAB /* Pods_XMPPFrameworkTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 63C474B21C506285009262C4 /* XMPPFramework */ = { + isa = PBXNativeTarget; + buildConfigurationList = 63C474D51C506286009262C4 /* Build configuration list for PBXNativeTarget "XMPPFramework" */; + buildPhases = ( + F591309C1643AF82507E3731 /* Check Pods Manifest.lock */, + 63C474AF1C506285009262C4 /* Sources */, + 63C474B01C506285009262C4 /* Frameworks */, + 63C474B11C506285009262C4 /* Resources */, + 14CA7F71743D79E01F7DE478 /* Embed Pods Frameworks */, + 4B381AE91D72F19E7F6C3522 /* Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = XMPPFramework; + productName = XMPPFramework; + productReference = 63C474B31C506285009262C4 /* XMPPFramework.app */; + productType = "com.apple.product-type.application"; + }; + 63C474CB1C506286009262C4 /* XMPPFrameworkTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 63C474D81C506286009262C4 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTests" */; + buildPhases = ( + 7DE7CE2991B663E4B6224C81 /* Check Pods Manifest.lock */, + 63C474C81C506286009262C4 /* Sources */, + 63C474C91C506286009262C4 /* Frameworks */, + 63C474CA1C506286009262C4 /* Resources */, + 11E6975D18DADEF22A7FC6CD /* Embed Pods Frameworks */, + 56C15013392CBB4DBC4A32DB /* Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 63C474CE1C506286009262C4 /* PBXTargetDependency */, + ); + name = XMPPFrameworkTests; + productName = XMPPFrameworkTests; + productReference = 63C474CC1C506286009262C4 /* XMPPFrameworkTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 63C474AB1C506285009262C4 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "David Chiles"; + TargetAttributes = { + 63C474B21C506285009262C4 = { + CreatedOnToolsVersion = 7.2; + }; + 63C474CB1C506286009262C4 = { + CreatedOnToolsVersion = 7.2; + TestTargetID = 63C474B21C506285009262C4; + }; + }; + }; + buildConfigurationList = 63C474AE1C506285009262C4 /* Build configuration list for PBXProject "XMPPFramework" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 63C474AA1C506285009262C4; + productRefGroup = 63C474B41C506285009262C4 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 63C474B21C506285009262C4 /* XMPPFramework */, + 63C474CB1C506286009262C4 /* XMPPFrameworkTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 63C474B11C506285009262C4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 63C474C61C506285009262C4 /* LaunchScreen.storyboard in Resources */, + 63C474C31C506285009262C4 /* Assets.xcassets in Resources */, + 63C474C11C506285009262C4 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 63C474CA1C506286009262C4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 11E6975D18DADEF22A7FC6CD /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XMPPFrameworkTests/Pods-XMPPFrameworkTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 14CA7F71743D79E01F7DE478 /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XMPPFramework/Pods-XMPPFramework-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 4B381AE91D72F19E7F6C3522 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XMPPFramework/Pods-XMPPFramework-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 56C15013392CBB4DBC4A32DB /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XMPPFrameworkTests/Pods-XMPPFrameworkTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 7DE7CE2991B663E4B6224C81 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + F591309C1643AF82507E3731 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 63C474AF1C506285009262C4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 63C474BE1C506285009262C4 /* ViewController.m in Sources */, + 63C474BB1C506285009262C4 /* AppDelegate.m in Sources */, + 63C474B81C506285009262C4 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 63C474C81C506286009262C4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 63C474D11C506286009262C4 /* XMPPFrameworkTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 63C474CE1C506286009262C4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 63C474B21C506285009262C4 /* XMPPFramework */; + targetProxy = 63C474CD1C506286009262C4 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 63C474BF1C506285009262C4 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 63C474C01C506285009262C4 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 63C474C41C506285009262C4 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 63C474C51C506285009262C4 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 63C474D31C506286009262C4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 63C474D41C506286009262C4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 63C474D61C506286009262C4 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 596BDF1156054499B58DE613 /* Pods-XMPPFramework.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = XMPPFramework/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.davidchiles.XMPPFramework; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 63C474D71C506286009262C4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D4F2FBA2F4988EC89DD5834 /* Pods-XMPPFramework.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = XMPPFramework/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.davidchiles.XMPPFramework; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 63C474D91C506286009262C4 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0F2C34BA02B0D5002F32FBAF /* Pods-XMPPFrameworkTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = XMPPFrameworkTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.davidchiles.XMPPFrameworkTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XMPPFramework.app/XMPPFramework"; + }; + name = Debug; + }; + 63C474DA1C506286009262C4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 70AFF6225A28CB83C1C8AA26 /* Pods-XMPPFrameworkTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = XMPPFrameworkTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.davidchiles.XMPPFrameworkTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XMPPFramework.app/XMPPFramework"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 63C474AE1C506285009262C4 /* Build configuration list for PBXProject "XMPPFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 63C474D31C506286009262C4 /* Debug */, + 63C474D41C506286009262C4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 63C474D51C506286009262C4 /* Build configuration list for PBXNativeTarget "XMPPFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 63C474D61C506286009262C4 /* Debug */, + 63C474D71C506286009262C4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 63C474D81C506286009262C4 /* Build configuration list for PBXNativeTarget "XMPPFrameworkTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 63C474D91C506286009262C4 /* Debug */, + 63C474DA1C506286009262C4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 63C474AB1C506285009262C4 /* Project object */; +} diff --git a/Xcode/Testing3/XMPPFramework.xcworkspace/contents.xcworkspacedata b/Xcode/Testing3/XMPPFramework.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..ae1971c405 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Xcode/Testing3/XMPPFramework/AppDelegate.h b/Xcode/Testing3/XMPPFramework/AppDelegate.h new file mode 100644 index 0000000000..83557ca1dc --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// XMPPFramework +// +// Created by David Chiles on 1/20/16. +// Copyright © 2016 David Chiles. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/Xcode/Testing3/XMPPFramework/AppDelegate.m b/Xcode/Testing3/XMPPFramework/AppDelegate.m new file mode 100644 index 0000000000..c771e761c5 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/AppDelegate.m @@ -0,0 +1,46 @@ +// +// AppDelegate.m +// XMPPFramework +// +// Created by David Chiles on 1/20/16. +// Copyright © 2016 David Chiles. All rights reserved. +// + +#import "AppDelegate.h" +@import XMPPFramework; + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/Xcode/Testing3/XMPPFramework/Assets.xcassets/AppIcon.appiconset/Contents.json b/Xcode/Testing3/XMPPFramework/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..36d2c80d88 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Xcode/Testing3/XMPPFramework/Base.lproj/LaunchScreen.storyboard b/Xcode/Testing3/XMPPFramework/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000000..2e721e1833 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Xcode/Testing3/XMPPFramework/Base.lproj/Main.storyboard b/Xcode/Testing3/XMPPFramework/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..f56d2f3bb5 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Xcode/Testing3/XMPPFramework/Info.plist b/Xcode/Testing3/XMPPFramework/Info.plist new file mode 100644 index 0000000000..40c6215d90 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Xcode/Testing3/XMPPFramework/ViewController.h b/Xcode/Testing3/XMPPFramework/ViewController.h new file mode 100644 index 0000000000..f6f75b3497 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/ViewController.h @@ -0,0 +1,15 @@ +// +// ViewController.h +// XMPPFramework +// +// Created by David Chiles on 1/20/16. +// Copyright © 2016 David Chiles. All rights reserved. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/Xcode/Testing3/XMPPFramework/ViewController.m b/Xcode/Testing3/XMPPFramework/ViewController.m new file mode 100644 index 0000000000..7e08d551f5 --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/ViewController.m @@ -0,0 +1,27 @@ +// +// ViewController.m +// XMPPFramework +// +// Created by David Chiles on 1/20/16. +// Copyright © 2016 David Chiles. All rights reserved. +// + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff --git a/Xcode/Testing3/XMPPFramework/main.m b/Xcode/Testing3/XMPPFramework/main.m new file mode 100644 index 0000000000..305188b71e --- /dev/null +++ b/Xcode/Testing3/XMPPFramework/main.m @@ -0,0 +1,16 @@ +// +// main.m +// XMPPFramework +// +// Created by David Chiles on 1/20/16. +// Copyright © 2016 David Chiles. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/Xcode/Testing3/XMPPFrameworkTests/Info.plist b/Xcode/Testing3/XMPPFrameworkTests/Info.plist new file mode 100644 index 0000000000..ba72822e87 --- /dev/null +++ b/Xcode/Testing3/XMPPFrameworkTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Xcode/Testing3/XMPPFrameworkTests/XMPPFrameworkTests.m b/Xcode/Testing3/XMPPFrameworkTests/XMPPFrameworkTests.m new file mode 100644 index 0000000000..9d85717741 --- /dev/null +++ b/Xcode/Testing3/XMPPFrameworkTests/XMPPFrameworkTests.m @@ -0,0 +1,40 @@ +// +// XMPPFrameworkTests.m +// XMPPFrameworkTests +// +// Created by David Chiles on 1/20/16. +// Copyright © 2016 David Chiles. All rights reserved. +// + +#import +@import XMPPFramework; + +@interface XMPPFrameworkTests : XCTestCase + +@end + +@implementation XMPPFrameworkTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end From 12bedbac6a577ff7ddc1a1e1ed32ddc074c0f862 Mon Sep 17 00:00:00 2001 From: David Chiles Date: Fri, 22 Jan 2016 13:59:38 -0800 Subject: [PATCH 050/356] Progress on updating podspec and tests --- Vendor/CocoaAsyncSocket/GCDAsyncSocket.h | 1179 --- Vendor/CocoaAsyncSocket/GCDAsyncSocket.m | 7719 ----------------- Vendor/CocoaLumberjack/DDASLLogger.h | 41 - Vendor/CocoaLumberjack/DDASLLogger.m | 100 - .../DDAbstractDatabaseLogger.h | 102 - .../DDAbstractDatabaseLogger.m | 727 -- Vendor/CocoaLumberjack/DDFileLogger.h | 369 - Vendor/CocoaLumberjack/DDFileLogger.m | 1539 ---- Vendor/CocoaLumberjack/DDLog+LOGV.h | 99 - Vendor/CocoaLumberjack/DDLog.h | 634 -- Vendor/CocoaLumberjack/DDLog.m | 1208 --- Vendor/CocoaLumberjack/DDTTYLogger.h | 181 - Vendor/CocoaLumberjack/DDTTYLogger.m | 1520 ---- .../Extensions/DDContextFilterLogFormatter.h | 63 - .../Extensions/DDContextFilterLogFormatter.m | 191 - .../Extensions/DDDispatchQueueLogFormatter.h | 128 - .../Extensions/DDDispatchQueueLogFormatter.m | 253 - .../Extensions/DDMultiFormatter.h | 30 - .../Extensions/DDMultiFormatter.m | 127 - Vendor/CocoaLumberjack/Extensions/README.txt | 7 - Vendor/KissXML/Categories/NSString+DDXML.h | 18 - Vendor/KissXML/Categories/NSString+DDXML.m | 31 - Vendor/KissXML/DDXML.h | 196 - Vendor/KissXML/DDXMLDocument.h | 84 - Vendor/KissXML/DDXMLDocument.m | 140 - Vendor/KissXML/DDXMLElement.h | 66 - Vendor/KissXML/DDXMLElement.m | 801 -- Vendor/KissXML/DDXMLNode.h | 161 - Vendor/KissXML/DDXMLNode.m | 2905 ------- Vendor/KissXML/Private/DDXMLPrivate.h | 229 - XMPPFramework.podspec | 101 +- Xcode/Testing3/Podfile.lock | 109 +- .../XMPPFramework.xcodeproj/project.pbxproj | 4 + .../XMPPFrameworkTests/XMPPURITests.m | 97 + module/module.modulemap | 9 +- 35 files changed, 244 insertions(+), 20924 deletions(-) delete mode 100644 Vendor/CocoaAsyncSocket/GCDAsyncSocket.h delete mode 100644 Vendor/CocoaAsyncSocket/GCDAsyncSocket.m delete mode 100755 Vendor/CocoaLumberjack/DDASLLogger.h delete mode 100755 Vendor/CocoaLumberjack/DDASLLogger.m delete mode 100755 Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.h delete mode 100755 Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.m delete mode 100755 Vendor/CocoaLumberjack/DDFileLogger.h delete mode 100755 Vendor/CocoaLumberjack/DDFileLogger.m delete mode 100755 Vendor/CocoaLumberjack/DDLog+LOGV.h delete mode 100755 Vendor/CocoaLumberjack/DDLog.h delete mode 100755 Vendor/CocoaLumberjack/DDLog.m delete mode 100755 Vendor/CocoaLumberjack/DDTTYLogger.h delete mode 100755 Vendor/CocoaLumberjack/DDTTYLogger.m delete mode 100755 Vendor/CocoaLumberjack/Extensions/DDContextFilterLogFormatter.h delete mode 100755 Vendor/CocoaLumberjack/Extensions/DDContextFilterLogFormatter.m delete mode 100755 Vendor/CocoaLumberjack/Extensions/DDDispatchQueueLogFormatter.h delete mode 100755 Vendor/CocoaLumberjack/Extensions/DDDispatchQueueLogFormatter.m delete mode 100755 Vendor/CocoaLumberjack/Extensions/DDMultiFormatter.h delete mode 100755 Vendor/CocoaLumberjack/Extensions/DDMultiFormatter.m delete mode 100755 Vendor/CocoaLumberjack/Extensions/README.txt delete mode 100644 Vendor/KissXML/Categories/NSString+DDXML.h delete mode 100644 Vendor/KissXML/Categories/NSString+DDXML.m delete mode 100644 Vendor/KissXML/DDXML.h delete mode 100644 Vendor/KissXML/DDXMLDocument.h delete mode 100644 Vendor/KissXML/DDXMLDocument.m delete mode 100644 Vendor/KissXML/DDXMLElement.h delete mode 100644 Vendor/KissXML/DDXMLElement.m delete mode 100644 Vendor/KissXML/DDXMLNode.h delete mode 100644 Vendor/KissXML/DDXMLNode.m delete mode 100644 Vendor/KissXML/Private/DDXMLPrivate.h create mode 100644 Xcode/Testing3/XMPPFrameworkTests/XMPPURITests.m diff --git a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h b/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h deleted file mode 100644 index 374bcdd89d..0000000000 --- a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h +++ /dev/null @@ -1,1179 +0,0 @@ -// -// GCDAsyncSocket.h -// -// This class is in the public domain. -// Originally created by Robbie Hanson in Q3 2010. -// Updated and maintained by Deusty LLC and the Apple development community. -// -// https://github.com/robbiehanson/CocoaAsyncSocket -// - -#import -#import -#import -#import -#import - -#include // AF_INET, AF_INET6 - -@class GCDAsyncReadPacket; -@class GCDAsyncWritePacket; -@class GCDAsyncSocketPreBuffer; - -extern NSString *const GCDAsyncSocketException; -extern NSString *const GCDAsyncSocketErrorDomain; - -extern NSString *const GCDAsyncSocketQueueName; -extern NSString *const GCDAsyncSocketThreadName; - -extern NSString *const GCDAsyncSocketManuallyEvaluateTrust; -#if TARGET_OS_IPHONE -extern NSString *const GCDAsyncSocketUseCFStreamForTLS; -#endif -#define GCDAsyncSocketSSLPeerName (NSString *)kCFStreamSSLPeerName -#define GCDAsyncSocketSSLCertificates (NSString *)kCFStreamSSLCertificates -#define GCDAsyncSocketSSLIsServer (NSString *)kCFStreamSSLIsServer -extern NSString *const GCDAsyncSocketSSLPeerID; -extern NSString *const GCDAsyncSocketSSLProtocolVersionMin; -extern NSString *const GCDAsyncSocketSSLProtocolVersionMax; -extern NSString *const GCDAsyncSocketSSLSessionOptionFalseStart; -extern NSString *const GCDAsyncSocketSSLSessionOptionSendOneByteRecord; -extern NSString *const GCDAsyncSocketSSLCipherSuites; -#if !TARGET_OS_IPHONE -extern NSString *const GCDAsyncSocketSSLDiffieHellmanParameters; -#endif - -#define GCDAsyncSocketLoggingContext 65535 - - -enum GCDAsyncSocketError -{ - GCDAsyncSocketNoError = 0, // Never used - GCDAsyncSocketBadConfigError, // Invalid configuration - GCDAsyncSocketBadParamError, // Invalid parameter was passed - GCDAsyncSocketConnectTimeoutError, // A connect operation timed out - GCDAsyncSocketReadTimeoutError, // A read operation timed out - GCDAsyncSocketWriteTimeoutError, // A write operation timed out - GCDAsyncSocketReadMaxedOutError, // Reached set maxLength without completing - GCDAsyncSocketClosedError, // The remote peer closed the connection - GCDAsyncSocketOtherError, // Description provided in userInfo -}; -typedef enum GCDAsyncSocketError GCDAsyncSocketError; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -@interface GCDAsyncSocket : NSObject - -/** - * GCDAsyncSocket uses the standard delegate paradigm, - * but executes all delegate callbacks on a given delegate dispatch queue. - * This allows for maximum concurrency, while at the same time providing easy thread safety. - * - * You MUST set a delegate AND delegate dispatch queue before attempting to - * use the socket, or you will get an error. - * - * The socket queue is optional. - * If you pass NULL, GCDAsyncSocket will automatically create it's own socket queue. - * If you choose to provide a socket queue, the socket queue must not be a concurrent queue. - * If you choose to provide a socket queue, and the socket queue has a configured target queue, - * then please see the discussion for the method markSocketQueueTargetQueue. - * - * The delegate queue and socket queue can optionally be the same. -**/ -- (id)init; -- (id)initWithSocketQueue:(dispatch_queue_t)sq; -- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq; -- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq; - -#pragma mark Configuration - -@property (atomic, weak, readwrite) id delegate; -#if OS_OBJECT_USE_OBJC -@property (atomic, strong, readwrite) dispatch_queue_t delegateQueue; -#else -@property (atomic, assign, readwrite) dispatch_queue_t delegateQueue; -#endif - -- (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr; -- (void)setDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; - -/** - * If you are setting the delegate to nil within the delegate's dealloc method, - * you may need to use the synchronous versions below. -**/ -- (void)synchronouslySetDelegate:(id)delegate; -- (void)synchronouslySetDelegateQueue:(dispatch_queue_t)delegateQueue; -- (void)synchronouslySetDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue; - -/** - * By default, both IPv4 and IPv6 are enabled. - * - * For accepting incoming connections, this means GCDAsyncSocket automatically supports both protocols, - * and can simulataneously accept incoming connections on either protocol. - * - * For outgoing connections, this means GCDAsyncSocket can connect to remote hosts running either protocol. - * If a DNS lookup returns only IPv4 results, GCDAsyncSocket will automatically use IPv4. - * If a DNS lookup returns only IPv6 results, GCDAsyncSocket will automatically use IPv6. - * If a DNS lookup returns both IPv4 and IPv6 results, the preferred protocol will be chosen. - * By default, the preferred protocol is IPv4, but may be configured as desired. -**/ - -@property (atomic, assign, readwrite, getter=isIPv4Enabled) BOOL IPv4Enabled; -@property (atomic, assign, readwrite, getter=isIPv6Enabled) BOOL IPv6Enabled; - -@property (atomic, assign, readwrite, getter=isIPv4PreferredOverIPv6) BOOL IPv4PreferredOverIPv6; - -/** - * User data allows you to associate arbitrary information with the socket. - * This data is not used internally by socket in any way. -**/ -@property (atomic, strong, readwrite) id userData; - -#pragma mark Accepting - -/** - * Tells the socket to begin listening and accepting connections on the given port. - * When a connection is accepted, a new instance of GCDAsyncSocket will be spawned to handle it, - * and the socket:didAcceptNewSocket: delegate method will be invoked. - * - * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc) -**/ -- (BOOL)acceptOnPort:(uint16_t)port error:(NSError **)errPtr; - -/** - * This method is the same as acceptOnPort:error: with the - * additional option of specifying which interface to listen on. - * - * For example, you could specify that the socket should only accept connections over ethernet, - * and not other interfaces such as wifi. - * - * The interface may be specified by name (e.g. "en1" or "lo0") or by IP address (e.g. "192.168.4.34"). - * You may also use the special strings "localhost" or "loopback" to specify that - * the socket only accept connections from the local machine. - * - * You can see the list of interfaces via the command line utility "ifconfig", - * or programmatically via the getifaddrs() function. - * - * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method. -**/ -- (BOOL)acceptOnInterface:(NSString *)interface port:(uint16_t)port error:(NSError **)errPtr; - -#pragma mark Connecting - -/** - * Connects to the given host and port. - * - * This method invokes connectToHost:onPort:viaInterface:withTimeout:error: - * and uses the default interface, and no timeout. -**/ -- (BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port error:(NSError **)errPtr; - -/** - * Connects to the given host and port with an optional timeout. - * - * This method invokes connectToHost:onPort:viaInterface:withTimeout:error: and uses the default interface. -**/ -- (BOOL)connectToHost:(NSString *)host - onPort:(uint16_t)port - withTimeout:(NSTimeInterval)timeout - error:(NSError **)errPtr; - -/** - * Connects to the given host & port, via the optional interface, with an optional timeout. - * - * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2"). - * The host may also be the special strings "localhost" or "loopback" to specify connecting - * to a service on the local machine. - * - * The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35"). - * The interface may also be used to specify the local port (see below). - * - * To not time out use a negative time interval. - * - * This method will return NO if an error is detected, and set the error pointer (if one was given). - * Possible errors would be a nil host, invalid interface, or socket is already connected. - * - * If no errors are detected, this method will start a background connect operation and immediately return YES. - * The delegate callbacks are used to notify you when the socket connects, or if the host was unreachable. - * - * Since this class supports queued reads and writes, you can immediately start reading and/or writing. - * All read/write operations will be queued, and upon socket connection, - * the operations will be dequeued and processed in order. - * - * The interface may optionally contain a port number at the end of the string, separated by a colon. - * This allows you to specify the local port that should be used for the outgoing connection. (read paragraph to end) - * To specify both interface and local port: "en1:8082" or "192.168.4.35:2424". - * To specify only local port: ":8082". - * Please note this is an advanced feature, and is somewhat hidden on purpose. - * You should understand that 99.999% of the time you should NOT specify the local port for an outgoing connection. - * If you think you need to, there is a very good chance you have a fundamental misunderstanding somewhere. - * Local ports do NOT need to match remote ports. In fact, they almost never do. - * This feature is here for networking professionals using very advanced techniques. -**/ -- (BOOL)connectToHost:(NSString *)host - onPort:(uint16_t)port - viaInterface:(NSString *)interface - withTimeout:(NSTimeInterval)timeout - error:(NSError **)errPtr; - -/** - * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object. - * For example, a NSData object returned from NSNetService's addresses method. - * - * If you have an existing struct sockaddr you can convert it to a NSData object like so: - * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; - * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; - * - * This method invokes connectToAdd -**/ -- (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; - -/** - * This method is the same as connectToAddress:error: with an additional timeout option. - * To not time out use a negative time interval, or simply use the connectToAddress:error: method. -**/ -- (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr; - -/** - * Connects to the given address, using the specified interface and timeout. - * - * The address is specified as a sockaddr structure wrapped in a NSData object. - * For example, a NSData object returned from NSNetService's addresses method. - * - * If you have an existing struct sockaddr you can convert it to a NSData object like so: - * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; - * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; - * - * The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35"). - * The interface may also be used to specify the local port (see below). - * - * The timeout is optional. To not time out use a negative time interval. - * - * This method will return NO if an error is detected, and set the error pointer (if one was given). - * Possible errors would be a nil host, invalid interface, or socket is already connected. - * - * If no errors are detected, this method will start a background connect operation and immediately return YES. - * The delegate callbacks are used to notify you when the socket connects, or if the host was unreachable. - * - * Since this class supports queued reads and writes, you can immediately start reading and/or writing. - * All read/write operations will be queued, and upon socket connection, - * the operations will be dequeued and processed in order. - * - * The interface may optionally contain a port number at the end of the string, separated by a colon. - * This allows you to specify the local port that should be used for the outgoing connection. (read paragraph to end) - * To specify both interface and local port: "en1:8082" or "192.168.4.35:2424". - * To specify only local port: ":8082". - * Please note this is an advanced feature, and is somewhat hidden on purpose. - * You should understand that 99.999% of the time you should NOT specify the local port for an outgoing connection. - * If you think you need to, there is a very good chance you have a fundamental misunderstanding somewhere. - * Local ports do NOT need to match remote ports. In fact, they almost never do. - * This feature is here for networking professionals using very advanced techniques. -**/ -- (BOOL)connectToAddress:(NSData *)remoteAddr - viaInterface:(NSString *)interface - withTimeout:(NSTimeInterval)timeout - error:(NSError **)errPtr; - -#pragma mark Disconnecting - -/** - * Disconnects immediately (synchronously). Any pending reads or writes are dropped. - * - * If the socket is not already disconnected, an invocation to the socketDidDisconnect:withError: delegate method - * will be queued onto the delegateQueue asynchronously (behind any previously queued delegate methods). - * In other words, the disconnected delegate method will be invoked sometime shortly after this method returns. - * - * Please note the recommended way of releasing a GCDAsyncSocket instance (e.g. in a dealloc method) - * [asyncSocket setDelegate:nil]; - * [asyncSocket disconnect]; - * [asyncSocket release]; - * - * If you plan on disconnecting the socket, and then immediately asking it to connect again, - * you'll likely want to do so like this: - * [asyncSocket setDelegate:nil]; - * [asyncSocket disconnect]; - * [asyncSocket setDelegate:self]; - * [asyncSocket connect...]; -**/ -- (void)disconnect; - -/** - * Disconnects after all pending reads have completed. - * After calling this, the read and write methods will do nothing. - * The socket will disconnect even if there are still pending writes. -**/ -- (void)disconnectAfterReading; - -/** - * Disconnects after all pending writes have completed. - * After calling this, the read and write methods will do nothing. - * The socket will disconnect even if there are still pending reads. -**/ -- (void)disconnectAfterWriting; - -/** - * Disconnects after all pending reads and writes have completed. - * After calling this, the read and write methods will do nothing. -**/ -- (void)disconnectAfterReadingAndWriting; - -#pragma mark Diagnostics - -/** - * Returns whether the socket is disconnected or connected. - * - * A disconnected socket may be recycled. - * That is, it can used again for connecting or listening. - * - * If a socket is in the process of connecting, it may be neither disconnected nor connected. -**/ -@property (atomic, readonly) BOOL isDisconnected; -@property (atomic, readonly) BOOL isConnected; - -/** - * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected. - * The host will be an IP address. -**/ -@property (atomic, readonly) NSString *connectedHost; -@property (atomic, readonly) uint16_t connectedPort; - -@property (atomic, readonly) NSString *localHost; -@property (atomic, readonly) uint16_t localPort; - -/** - * Returns the local or remote address to which this socket is connected, - * specified as a sockaddr structure wrapped in a NSData object. - * - * @seealso connectedHost - * @seealso connectedPort - * @seealso localHost - * @seealso localPort -**/ -@property (atomic, readonly) NSData *connectedAddress; -@property (atomic, readonly) NSData *localAddress; - -/** - * Returns whether the socket is IPv4 or IPv6. - * An accepting socket may be both. -**/ -@property (atomic, readonly) BOOL isIPv4; -@property (atomic, readonly) BOOL isIPv6; - -/** - * Returns whether or not the socket has been secured via SSL/TLS. - * - * See also the startTLS method. -**/ -@property (atomic, readonly) BOOL isSecure; - -#pragma mark Reading - -// The readData and writeData methods won't block (they are asynchronous). -// -// When a read is complete the socket:didReadData:withTag: delegate method is dispatched on the delegateQueue. -// When a write is complete the socket:didWriteDataWithTag: delegate method is dispatched on the delegateQueue. -// -// You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.) -// If a read/write opertion times out, the corresponding "socket:shouldTimeout..." delegate method -// is called to optionally allow you to extend the timeout. -// Upon a timeout, the "socket:didDisconnectWithError:" method is called -// -// The tag is for your convenience. -// You can use it as an array index, step number, state id, pointer, etc. - -/** - * Reads the first available bytes that become available on the socket. - * - * If the timeout value is negative, the read operation will not use a timeout. -**/ -- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag; - -/** - * Reads the first available bytes that become available on the socket. - * The bytes will be appended to the given byte buffer starting at the given offset. - * The given buffer will automatically be increased in size if needed. - * - * If the timeout value is negative, the read operation will not use a timeout. - * If the buffer if nil, the socket will create a buffer for you. - * - * If the bufferOffset is greater than the length of the given buffer, - * the method will do nothing, and the delegate will not be called. - * - * If you pass a buffer, you must not alter it in any way while the socket is using it. - * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. - * That is, it will reference the bytes that were appended to the given buffer via - * the method [NSData dataWithBytesNoCopy:length:freeWhenDone:NO]. -**/ -- (void)readDataWithTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - tag:(long)tag; - -/** - * Reads the first available bytes that become available on the socket. - * The bytes will be appended to the given byte buffer starting at the given offset. - * The given buffer will automatically be increased in size if needed. - * A maximum of length bytes will be read. - * - * If the timeout value is negative, the read operation will not use a timeout. - * If the buffer if nil, a buffer will automatically be created for you. - * If maxLength is zero, no length restriction is enforced. - * - * If the bufferOffset is greater than the length of the given buffer, - * the method will do nothing, and the delegate will not be called. - * - * If you pass a buffer, you must not alter it in any way while the socket is using it. - * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. - * That is, it will reference the bytes that were appended to the given buffer via - * the method [NSData dataWithBytesNoCopy:length:freeWhenDone:NO]. -**/ -- (void)readDataWithTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - maxLength:(NSUInteger)length - tag:(long)tag; - -/** - * Reads the given number of bytes. - * - * If the timeout value is negative, the read operation will not use a timeout. - * - * If the length is 0, this method does nothing and the delegate is not called. -**/ -- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag; - -/** - * Reads the given number of bytes. - * The bytes will be appended to the given byte buffer starting at the given offset. - * The given buffer will automatically be increased in size if needed. - * - * If the timeout value is negative, the read operation will not use a timeout. - * If the buffer if nil, a buffer will automatically be created for you. - * - * If the length is 0, this method does nothing and the delegate is not called. - * If the bufferOffset is greater than the length of the given buffer, - * the method will do nothing, and the delegate will not be called. - * - * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. - * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. - * That is, it will reference the bytes that were appended to the given buffer via - * the method [NSData dataWithBytesNoCopy:length:freeWhenDone:NO]. -**/ -- (void)readDataToLength:(NSUInteger)length - withTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - tag:(long)tag; - -/** - * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. - * - * If the timeout value is negative, the read operation will not use a timeout. - * - * If you pass nil or zero-length data as the "data" parameter, - * the method will do nothing (except maybe print a warning), and the delegate will not be called. - * - * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. - * If you're developing your own custom protocol, be sure your separator can not occur naturally as - * part of the data between separators. - * For example, imagine you want to send several small documents over a socket. - * Using CRLF as a separator is likely unwise, as a CRLF could easily exist within the documents. - * In this particular example, it would be better to use a protocol similar to HTTP with - * a header that includes the length of the document. - * Also be careful that your separator cannot occur naturally as part of the encoding for a character. - * - * The given data (separator) parameter should be immutable. - * For performance reasons, the socket will retain it, not copy it. - * So if it is immutable, don't modify it while the socket is using it. -**/ -- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; - -/** - * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. - * The bytes will be appended to the given byte buffer starting at the given offset. - * The given buffer will automatically be increased in size if needed. - * - * If the timeout value is negative, the read operation will not use a timeout. - * If the buffer if nil, a buffer will automatically be created for you. - * - * If the bufferOffset is greater than the length of the given buffer, - * the method will do nothing (except maybe print a warning), and the delegate will not be called. - * - * If you pass a buffer, you must not alter it in any way while the socket is using it. - * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. - * That is, it will reference the bytes that were appended to the given buffer via - * the method [NSData dataWithBytesNoCopy:length:freeWhenDone:NO]. - * - * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. - * If you're developing your own custom protocol, be sure your separator can not occur naturally as - * part of the data between separators. - * For example, imagine you want to send several small documents over a socket. - * Using CRLF as a separator is likely unwise, as a CRLF could easily exist within the documents. - * In this particular example, it would be better to use a protocol similar to HTTP with - * a header that includes the length of the document. - * Also be careful that your separator cannot occur naturally as part of the encoding for a character. - * - * The given data (separator) parameter should be immutable. - * For performance reasons, the socket will retain it, not copy it. - * So if it is immutable, don't modify it while the socket is using it. -**/ -- (void)readDataToData:(NSData *)data - withTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - tag:(long)tag; - -/** - * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. - * - * If the timeout value is negative, the read operation will not use a timeout. - * - * If maxLength is zero, no length restriction is enforced. - * Otherwise if maxLength bytes are read without completing the read, - * it is treated similarly to a timeout - the socket is closed with a GCDAsyncSocketReadMaxedOutError. - * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. - * - * If you pass nil or zero-length data as the "data" parameter, - * the method will do nothing (except maybe print a warning), and the delegate will not be called. - * If you pass a maxLength parameter that is less than the length of the data parameter, - * the method will do nothing (except maybe print a warning), and the delegate will not be called. - * - * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. - * If you're developing your own custom protocol, be sure your separator can not occur naturally as - * part of the data between separators. - * For example, imagine you want to send several small documents over a socket. - * Using CRLF as a separator is likely unwise, as a CRLF could easily exist within the documents. - * In this particular example, it would be better to use a protocol similar to HTTP with - * a header that includes the length of the document. - * Also be careful that your separator cannot occur naturally as part of the encoding for a character. - * - * The given data (separator) parameter should be immutable. - * For performance reasons, the socket will retain it, not copy it. - * So if it is immutable, don't modify it while the socket is using it. -**/ -- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag; - -/** - * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. - * The bytes will be appended to the given byte buffer starting at the given offset. - * The given buffer will automatically be increased in size if needed. - * - * If the timeout value is negative, the read operation will not use a timeout. - * If the buffer if nil, a buffer will automatically be created for you. - * - * If maxLength is zero, no length restriction is enforced. - * Otherwise if maxLength bytes are read without completing the read, - * it is treated similarly to a timeout - the socket is closed with a GCDAsyncSocketReadMaxedOutError. - * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. - * - * If you pass a maxLength parameter that is less than the length of the data (separator) parameter, - * the method will do nothing (except maybe print a warning), and the delegate will not be called. - * If the bufferOffset is greater than the length of the given buffer, - * the method will do nothing (except maybe print a warning), and the delegate will not be called. - * - * If you pass a buffer, you must not alter it in any way while the socket is using it. - * After completion, the data returned in socket:didReadData:withTag: will be a subset of the given buffer. - * That is, it will reference the bytes that were appended to the given buffer via - * the method [NSData dataWithBytesNoCopy:length:freeWhenDone:NO]. - * - * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. - * If you're developing your own custom protocol, be sure your separator can not occur naturally as - * part of the data between separators. - * For example, imagine you want to send several small documents over a socket. - * Using CRLF as a separator is likely unwise, as a CRLF could easily exist within the documents. - * In this particular example, it would be better to use a protocol similar to HTTP with - * a header that includes the length of the document. - * Also be careful that your separator cannot occur naturally as part of the encoding for a character. - * - * The given data (separator) parameter should be immutable. - * For performance reasons, the socket will retain it, not copy it. - * So if it is immutable, don't modify it while the socket is using it. -**/ -- (void)readDataToData:(NSData *)data - withTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - maxLength:(NSUInteger)length - tag:(long)tag; - -/** - * Returns progress of the current read, from 0.0 to 1.0, or NaN if no current read (use isnan() to check). - * The parameters "tag", "done" and "total" will be filled in if they aren't NULL. -**/ -- (float)progressOfReadReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr; - -#pragma mark Writing - -/** - * Writes data to the socket, and calls the delegate when finished. - * - * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called. - * If the timeout value is negative, the write operation will not use a timeout. - * - * Thread-Safety Note: - * If the given data parameter is mutable (NSMutableData) then you MUST NOT alter the data while - * the socket is writing it. In other words, it's not safe to alter the data until after the delegate method - * socket:didWriteDataWithTag: is invoked signifying that this particular write operation has completed. - * This is due to the fact that GCDAsyncSocket does NOT copy the data. It simply retains it. - * This is for performance reasons. Often times, if NSMutableData is passed, it is because - * a request/response was built up in memory. Copying this data adds an unwanted/unneeded overhead. - * If you need to write data from an immutable buffer, and you need to alter the buffer before the socket - * completes writing the bytes (which is NOT immediately after this method returns, but rather at a later time - * when the delegate method notifies you), then you should first copy the bytes, and pass the copy to this method. -**/ -- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; - -/** - * Returns progress of the current write, from 0.0 to 1.0, or NaN if no current write (use isnan() to check). - * The parameters "tag", "done" and "total" will be filled in if they aren't NULL. -**/ -- (float)progressOfWriteReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr; - -#pragma mark Security - -/** - * Secures the connection using SSL/TLS. - * - * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes - * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing - * the upgrade to TLS at the same time, without having to wait for the write to finish. - * Any reads or writes scheduled after this method is called will occur over the secured connection. - * - * ==== The available TOP-LEVEL KEYS are: - * - * - GCDAsyncSocketManuallyEvaluateTrust - * The value must be of type NSNumber, encapsulating a BOOL value. - * If you set this to YES, then the underlying SecureTransport system will not evaluate the SecTrustRef of the peer. - * Instead it will pause at the moment evaulation would typically occur, - * and allow us to handle the security evaluation however we see fit. - * So GCDAsyncSocket will invoke the delegate method socket:shouldTrustPeer: passing the SecTrustRef. - * - * Note that if you set this option, then all other configuration keys are ignored. - * Evaluation will be completely up to you during the socket:didReceiveTrust:completionHandler: delegate method. - * - * For more information on trust evaluation see: - * Apple's Technical Note TN2232 - HTTPS Server Trust Evaluation - * https://developer.apple.com/library/ios/technotes/tn2232/_index.html - * - * If unspecified, the default value is NO. - * - * - GCDAsyncSocketUseCFStreamForTLS (iOS only) - * The value must be of type NSNumber, encapsulating a BOOL value. - * By default GCDAsyncSocket will use the SecureTransport layer to perform encryption. - * This gives us more control over the security protocol (many more configuration options), - * plus it allows us to optimize things like sys calls and buffer allocation. - * - * However, if you absolutely must, you can instruct GCDAsyncSocket to use the old-fashioned encryption - * technique by going through the CFStream instead. So instead of using SecureTransport, GCDAsyncSocket - * will instead setup a CFRead/CFWriteStream. And then set the kCFStreamPropertySSLSettings property - * (via CFReadStreamSetProperty / CFWriteStreamSetProperty) and will pass the given options to this method. - * - * Thus all the other keys in the given dictionary will be ignored by GCDAsyncSocket, - * and will passed directly CFReadStreamSetProperty / CFWriteStreamSetProperty. - * For more infomation on these keys, please see the documentation for kCFStreamPropertySSLSettings. - * - * If unspecified, the default value is NO. - * - * ==== The available CONFIGURATION KEYS are: - * - * - kCFStreamSSLPeerName - * The value must be of type NSString. - * It should match the name in the X.509 certificate given by the remote party. - * See Apple's documentation for SSLSetPeerDomainName. - * - * - kCFStreamSSLCertificates - * The value must be of type NSArray. - * See Apple's documentation for SSLSetCertificate. - * - * - kCFStreamSSLIsServer - * The value must be of type NSNumber, encapsulationg a BOOL value. - * See Apple's documentation for SSLCreateContext for iOS. - * This is optional for iOS. If not supplied, a NO value is the default. - * This is not needed for Mac OS X, and the value is ignored. - * - * - GCDAsyncSocketSSLPeerID - * The value must be of type NSData. - * You must set this value if you want to use TLS session resumption. - * See Apple's documentation for SSLSetPeerID. - * - * - GCDAsyncSocketSSLProtocolVersionMin - * - GCDAsyncSocketSSLProtocolVersionMax - * The value(s) must be of type NSNumber, encapsulting a SSLProtocol value. - * See Apple's documentation for SSLSetProtocolVersionMin & SSLSetProtocolVersionMax. - * See also the SSLProtocol typedef. - * - * - GCDAsyncSocketSSLSessionOptionFalseStart - * The value must be of type NSNumber, encapsulating a BOOL value. - * See Apple's documentation for kSSLSessionOptionFalseStart. - * - * - GCDAsyncSocketSSLSessionOptionSendOneByteRecord - * The value must be of type NSNumber, encapsulating a BOOL value. - * See Apple's documentation for kSSLSessionOptionSendOneByteRecord. - * - * - GCDAsyncSocketSSLCipherSuites - * The values must be of type NSArray. - * Each item within the array must be a NSNumber, encapsulating - * See Apple's documentation for SSLSetEnabledCiphers. - * See also the SSLCipherSuite typedef. - * - * - GCDAsyncSocketSSLDiffieHellmanParameters (Mac OS X only) - * The value must be of type NSData. - * See Apple's documentation for SSLSetDiffieHellmanParams. - * - * ==== The following UNAVAILABLE KEYS are: (with throw an exception) - * - * - kCFStreamSSLAllowsAnyRoot (UNAVAILABLE) - * You MUST use manual trust evaluation instead (see GCDAsyncSocketManuallyEvaluateTrust). - * Corresponding deprecated method: SSLSetAllowsAnyRoot - * - * - kCFStreamSSLAllowsExpiredRoots (UNAVAILABLE) - * You MUST use manual trust evaluation instead (see GCDAsyncSocketManuallyEvaluateTrust). - * Corresponding deprecated method: SSLSetAllowsExpiredRoots - * - * - kCFStreamSSLAllowsExpiredCertificates (UNAVAILABLE) - * You MUST use manual trust evaluation instead (see GCDAsyncSocketManuallyEvaluateTrust). - * Corresponding deprecated method: SSLSetAllowsExpiredCerts - * - * - kCFStreamSSLValidatesCertificateChain (UNAVAILABLE) - * You MUST use manual trust evaluation instead (see GCDAsyncSocketManuallyEvaluateTrust). - * Corresponding deprecated method: SSLSetEnableCertVerify - * - * - kCFStreamSSLLevel (UNAVAILABLE) - * You MUST use GCDAsyncSocketSSLProtocolVersionMin & GCDAsyncSocketSSLProtocolVersionMin instead. - * Corresponding deprecated method: SSLSetProtocolVersionEnabled - * - * - * Please refer to Apple's documentation for corresponding SSLFunctions. - * - * If you pass in nil or an empty dictionary, the default settings will be used. - * - * IMPORTANT SECURITY NOTE: - * The default settings will check to make sure the remote party's certificate is signed by a - * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired. - * However it will not verify the name on the certificate unless you - * give it a name to verify against via the kCFStreamSSLPeerName key. - * The security implications of this are important to understand. - * Imagine you are attempting to create a secure connection to MySecureServer.com, - * but your socket gets directed to MaliciousServer.com because of a hacked DNS server. - * If you simply use the default settings, and MaliciousServer.com has a valid certificate, - * the default settings will not detect any problems since the certificate is valid. - * To properly secure your connection in this particular scenario you - * should set the kCFStreamSSLPeerName property to "MySecureServer.com". - * - * You can also perform additional validation in socketDidSecure. -**/ -- (void)startTLS:(NSDictionary *)tlsSettings; - -#pragma mark Advanced - -/** - * Traditionally sockets are not closed until the conversation is over. - * However, it is technically possible for the remote enpoint to close its write stream. - * Our socket would then be notified that there is no more data to be read, - * but our socket would still be writeable and the remote endpoint could continue to receive our data. - * - * The argument for this confusing functionality stems from the idea that a client could shut down its - * write stream after sending a request to the server, thus notifying the server there are to be no further requests. - * In practice, however, this technique did little to help server developers. - * - * To make matters worse, from a TCP perspective there is no way to tell the difference from a read stream close - * and a full socket close. They both result in the TCP stack receiving a FIN packet. The only way to tell - * is by continuing to write to the socket. If it was only a read stream close, then writes will continue to work. - * Otherwise an error will be occur shortly (when the remote end sends us a RST packet). - * - * In addition to the technical challenges and confusion, many high level socket/stream API's provide - * no support for dealing with the problem. If the read stream is closed, the API immediately declares the - * socket to be closed, and shuts down the write stream as well. In fact, this is what Apple's CFStream API does. - * It might sound like poor design at first, but in fact it simplifies development. - * - * The vast majority of the time if the read stream is closed it's because the remote endpoint closed its socket. - * Thus it actually makes sense to close the socket at this point. - * And in fact this is what most networking developers want and expect to happen. - * However, if you are writing a server that interacts with a plethora of clients, - * you might encounter a client that uses the discouraged technique of shutting down its write stream. - * If this is the case, you can set this property to NO, - * and make use of the socketDidCloseReadStream delegate method. - * - * The default value is YES. -**/ -@property (atomic, assign, readwrite) BOOL autoDisconnectOnClosedReadStream; - -/** - * GCDAsyncSocket maintains thread safety by using an internal serial dispatch_queue. - * In most cases, the instance creates this queue itself. - * However, to allow for maximum flexibility, the internal queue may be passed in the init method. - * This allows for some advanced options such as controlling socket priority via target queues. - * However, when one begins to use target queues like this, they open the door to some specific deadlock issues. - * - * For example, imagine there are 2 queues: - * dispatch_queue_t socketQueue; - * dispatch_queue_t socketTargetQueue; - * - * If you do this (pseudo-code): - * socketQueue.targetQueue = socketTargetQueue; - * - * Then all socketQueue operations will actually get run on the given socketTargetQueue. - * This is fine and works great in most situations. - * But if you run code directly from within the socketTargetQueue that accesses the socket, - * you could potentially get deadlock. Imagine the following code: - * - * - (BOOL)socketHasSomething - * { - * __block BOOL result = NO; - * dispatch_block_t block = ^{ - * result = [self someInternalMethodToBeRunOnlyOnSocketQueue]; - * } - * if (is_executing_on_queue(socketQueue)) - * block(); - * else - * dispatch_sync(socketQueue, block); - * - * return result; - * } - * - * What happens if you call this method from the socketTargetQueue? The result is deadlock. - * This is because the GCD API offers no mechanism to discover a queue's targetQueue. - * Thus we have no idea if our socketQueue is configured with a targetQueue. - * If we had this information, we could easily avoid deadlock. - * But, since these API's are missing or unfeasible, you'll have to explicitly set it. - * - * IF you pass a socketQueue via the init method, - * AND you've configured the passed socketQueue with a targetQueue, - * THEN you should pass the end queue in the target hierarchy. - * - * For example, consider the following queue hierarchy: - * socketQueue -> ipQueue -> moduleQueue - * - * This example demonstrates priority shaping within some server. - * All incoming client connections from the same IP address are executed on the same target queue. - * And all connections for a particular module are executed on the same target queue. - * Thus, the priority of all networking for the entire module can be changed on the fly. - * Additionally, networking traffic from a single IP cannot monopolize the module. - * - * Here's how you would accomplish something like that: - * - (dispatch_queue_t)newSocketQueueForConnectionFromAddress:(NSData *)address onSocket:(GCDAsyncSocket *)sock - * { - * dispatch_queue_t socketQueue = dispatch_queue_create("", NULL); - * dispatch_queue_t ipQueue = [self ipQueueForAddress:address]; - * - * dispatch_set_target_queue(socketQueue, ipQueue); - * dispatch_set_target_queue(iqQueue, moduleQueue); - * - * return socketQueue; - * } - * - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket - * { - * [clientConnections addObject:newSocket]; - * [newSocket markSocketQueueTargetQueue:moduleQueue]; - * } - * - * Note: This workaround is ONLY needed if you intend to execute code directly on the ipQueue or moduleQueue. - * This is often NOT the case, as such queues are used solely for execution shaping. -**/ -- (void)markSocketQueueTargetQueue:(dispatch_queue_t)socketQueuesPreConfiguredTargetQueue; -- (void)unmarkSocketQueueTargetQueue:(dispatch_queue_t)socketQueuesPreviouslyConfiguredTargetQueue; - -/** - * It's not thread-safe to access certain variables from outside the socket's internal queue. - * - * For example, the socket file descriptor. - * File descriptors are simply integers which reference an index in the per-process file table. - * However, when one requests a new file descriptor (by opening a file or socket), - * the file descriptor returned is guaranteed to be the lowest numbered unused descriptor. - * So if we're not careful, the following could be possible: - * - * - Thread A invokes a method which returns the socket's file descriptor. - * - The socket is closed via the socket's internal queue on thread B. - * - Thread C opens a file, and subsequently receives the file descriptor that was previously the socket's FD. - * - Thread A is now accessing/altering the file instead of the socket. - * - * In addition to this, other variables are not actually objects, - * and thus cannot be retained/released or even autoreleased. - * An example is the sslContext, of type SSLContextRef, which is actually a malloc'd struct. - * - * Although there are internal variables that make it difficult to maintain thread-safety, - * it is important to provide access to these variables - * to ensure this class can be used in a wide array of environments. - * This method helps to accomplish this by invoking the current block on the socket's internal queue. - * The methods below can be invoked from within the block to access - * those generally thread-unsafe internal variables in a thread-safe manner. - * The given block will be invoked synchronously on the socket's internal queue. - * - * If you save references to any protected variables and use them outside the block, you do so at your own peril. -**/ -- (void)performBlock:(dispatch_block_t)block; - -/** - * These methods are only available from within the context of a performBlock: invocation. - * See the documentation for the performBlock: method above. - * - * Provides access to the socket's file descriptor(s). - * If the socket is a server socket (is accepting incoming connections), - * it might actually have multiple internal socket file descriptors - one for IPv4 and one for IPv6. -**/ -- (int)socketFD; -- (int)socket4FD; -- (int)socket6FD; - -#if TARGET_OS_IPHONE - -/** - * These methods are only available from within the context of a performBlock: invocation. - * See the documentation for the performBlock: method above. - * - * Provides access to the socket's internal CFReadStream/CFWriteStream. - * - * These streams are only used as workarounds for specific iOS shortcomings: - * - * - Apple has decided to keep the SecureTransport framework private is iOS. - * This means the only supplied way to do SSL/TLS is via CFStream or some other API layered on top of it. - * Thus, in order to provide SSL/TLS support on iOS we are forced to rely on CFStream, - * instead of the preferred and faster and more powerful SecureTransport. - * - * - If a socket doesn't have backgrounding enabled, and that socket is closed while the app is backgrounded, - * Apple only bothers to notify us via the CFStream API. - * The faster and more powerful GCD API isn't notified properly in this case. - * - * See also: (BOOL)enableBackgroundingOnSocket -**/ -- (CFReadStreamRef)readStream; -- (CFWriteStreamRef)writeStream; - -/** - * This method is only available from within the context of a performBlock: invocation. - * See the documentation for the performBlock: method above. - * - * Configures the socket to allow it to operate when the iOS application has been backgrounded. - * In other words, this method creates a read & write stream, and invokes: - * - * CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); - * CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); - * - * Returns YES if successful, NO otherwise. - * - * Note: Apple does not officially support backgrounding server sockets. - * That is, if your socket is accepting incoming connections, Apple does not officially support - * allowing iOS applications to accept incoming connections while an app is backgrounded. - * - * Example usage: - * - * - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port - * { - * [asyncSocket performBlock:^{ - * [asyncSocket enableBackgroundingOnSocket]; - * }]; - * } -**/ -- (BOOL)enableBackgroundingOnSocket; - -#endif - -/** - * This method is only available from within the context of a performBlock: invocation. - * See the documentation for the performBlock: method above. - * - * Provides access to the socket's SSLContext, if SSL/TLS has been started on the socket. -**/ -- (SSLContextRef)sslContext; - -#pragma mark Utilities - -/** - * The address lookup utility used by the class. - * This method is synchronous, so it's recommended you use it on a background thread/queue. - * - * The special strings "localhost" and "loopback" return the loopback address for IPv4 and IPv6. - * - * @returns - * A mutable array with all IPv4 and IPv6 addresses returned by getaddrinfo. - * The addresses are specifically for TCP connections. - * You can filter the addresses, if needed, using the other utility methods provided by the class. -**/ -+ (NSMutableArray *)lookupHost:(NSString *)host port:(uint16_t)port error:(NSError **)errPtr; - -/** - * Extracting host and port information from raw address data. -**/ - -+ (NSString *)hostFromAddress:(NSData *)address; -+ (uint16_t)portFromAddress:(NSData *)address; - -+ (BOOL)isIPv4Address:(NSData *)address; -+ (BOOL)isIPv6Address:(NSData *)address; - -+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address; - -+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr family:(sa_family_t *)afPtr fromAddress:(NSData *)address; - -/** - * A few common line separators, for use with the readDataToData:... methods. -**/ -+ (NSData *)CRLFData; // 0x0D0A -+ (NSData *)CRData; // 0x0D -+ (NSData *)LFData; // 0x0A -+ (NSData *)ZeroData; // 0x00 - -@end - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -@protocol GCDAsyncSocketDelegate -@optional - -/** - * This method is called immediately prior to socket:didAcceptNewSocket:. - * It optionally allows a listening socket to specify the socketQueue for a new accepted socket. - * If this method is not implemented, or returns NULL, the new accepted socket will create its own default queue. - * - * Since you cannot autorelease a dispatch_queue, - * this method uses the "new" prefix in its name to specify that the returned queue has been retained. - * - * Thus you could do something like this in the implementation: - * return dispatch_queue_create("MyQueue", NULL); - * - * If you are placing multiple sockets on the same queue, - * then care should be taken to increment the retain count each time this method is invoked. - * - * For example, your implementation might look something like this: - * dispatch_retain(myExistingQueue); - * return myExistingQueue; -**/ -- (dispatch_queue_t)newSocketQueueForConnectionFromAddress:(NSData *)address onSocket:(GCDAsyncSocket *)sock; - -/** - * Called when a socket accepts a connection. - * Another socket is automatically spawned to handle it. - * - * You must retain the newSocket if you wish to handle the connection. - * Otherwise the newSocket instance will be released and the spawned connection will be closed. - * - * By default the new socket will have the same delegate and delegateQueue. - * You may, of course, change this at any time. -**/ -- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket; - -/** - * Called when a socket connects and is ready for reading and writing. - * The host parameter will be an IP address, not a DNS name. -**/ -- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port; - -/** - * Called when a socket has completed reading the requested data into memory. - * Not called if there is an error. -**/ -- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag; - -/** - * Called when a socket has read in data, but has not yet completed the read. - * This would occur if using readToData: or readToLength: methods. - * It may be used to for things such as updating progress bars. -**/ -- (void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; - -/** - * Called when a socket has completed writing the requested data. Not called if there is an error. -**/ -- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag; - -/** - * Called when a socket has written some data, but has not yet completed the entire write. - * It may be used to for things such as updating progress bars. -**/ -- (void)socket:(GCDAsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; - -/** - * Called if a read operation has reached its timeout without completing. - * This method allows you to optionally extend the timeout. - * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount. - * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual. - * - * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. - * The length parameter is the number of bytes that have been read so far for the read operation. - * - * Note that this method may be called multiple times for a single read if you return positive numbers. -**/ -- (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag - elapsed:(NSTimeInterval)elapsed - bytesDone:(NSUInteger)length; - -/** - * Called if a write operation has reached its timeout without completing. - * This method allows you to optionally extend the timeout. - * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount. - * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual. - * - * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. - * The length parameter is the number of bytes that have been written so far for the write operation. - * - * Note that this method may be called multiple times for a single write if you return positive numbers. -**/ -- (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag - elapsed:(NSTimeInterval)elapsed - bytesDone:(NSUInteger)length; - -/** - * Conditionally called if the read stream closes, but the write stream may still be writeable. - * - * This delegate method is only called if autoDisconnectOnClosedReadStream has been set to NO. - * See the discussion on the autoDisconnectOnClosedReadStream method for more information. -**/ -- (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock; - -/** - * Called when a socket disconnects with or without error. - * - * If you call the disconnect method, and the socket wasn't already disconnected, - * then an invocation of this delegate method will be enqueued on the delegateQueue - * before the disconnect method returns. - * - * Note: If the GCDAsyncSocket instance is deallocated while it is still connected, - * and the delegate is not also deallocated, then this method will be invoked, - * but the sock parameter will be nil. (It must necessarily be nil since it is no longer available.) - * This is a generally rare, but is possible if one writes code like this: - * - * asyncSocket = nil; // I'm implicitly disconnecting the socket - * - * In this case it may preferrable to nil the delegate beforehand, like this: - * - * asyncSocket.delegate = nil; // Don't invoke my delegate method - * asyncSocket = nil; // I'm implicitly disconnecting the socket - * - * Of course, this depends on how your state machine is configured. -**/ -- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err; - -/** - * Called after the socket has successfully completed SSL/TLS negotiation. - * This method is not called unless you use the provided startTLS method. - * - * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close, - * and the socketDidDisconnect:withError: delegate method will be called with the specific SSL error code. -**/ -- (void)socketDidSecure:(GCDAsyncSocket *)sock; - -/** - * Allows a socket delegate to hook into the TLS handshake and manually validate the peer it's connecting to. - * - * This is only called if startTLS is invoked with options that include: - * - GCDAsyncSocketManuallyEvaluateTrust == YES - * - * Typically the delegate will use SecTrustEvaluate (and related functions) to properly validate the peer. - * - * Note from Apple's documentation: - * Because [SecTrustEvaluate] might look on the network for certificates in the certificate chain, - * [it] might block while attempting network access. You should never call it from your main thread; - * call it only from within a function running on a dispatch queue or on a separate thread. - * - * Thus this method uses a completionHandler block rather than a normal return value. - * The completionHandler block is thread-safe, and may be invoked from a background queue/thread. - * It is safe to invoke the completionHandler block even if the socket has been closed. -**/ -- (void)socket:(GCDAsyncSocket *)sock didReceiveTrust:(SecTrustRef)trust - completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler; - -@end diff --git a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m b/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m deleted file mode 100644 index 531a29d86c..0000000000 --- a/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +++ /dev/null @@ -1,7719 +0,0 @@ -// -// GCDAsyncSocket.m -// -// This class is in the public domain. -// Originally created by Robbie Hanson in Q4 2010. -// Updated and maintained by Deusty LLC and the Apple development community. -// -// https://github.com/robbiehanson/CocoaAsyncSocket -// - -#import "GCDAsyncSocket.h" - -#if TARGET_OS_IPHONE -#import -#endif - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#if ! __has_feature(objc_arc) -#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). -// For more information see: https://github.com/robbiehanson/CocoaAsyncSocket/wiki/ARC -#endif - - -#ifndef GCDAsyncSocketLoggingEnabled -#define GCDAsyncSocketLoggingEnabled 0 -#endif - -#if GCDAsyncSocketLoggingEnabled - -// Logging Enabled - See log level below - -// Logging uses the CocoaLumberjack framework (which is also GCD based). -// https://github.com/robbiehanson/CocoaLumberjack -// -// It allows us to do a lot of logging without significantly slowing down the code. -#import "DDLog.h" - -#define LogAsync YES -#define LogContext GCDAsyncSocketLoggingContext - -#define LogObjc(flg, frmt, ...) LOG_OBJC_MAYBE(LogAsync, logLevel, flg, LogContext, frmt, ##__VA_ARGS__) -#define LogC(flg, frmt, ...) LOG_C_MAYBE(LogAsync, logLevel, flg, LogContext, frmt, ##__VA_ARGS__) - -#define LogError(frmt, ...) LogObjc(LOG_FLAG_ERROR, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__) -#define LogWarn(frmt, ...) LogObjc(LOG_FLAG_WARN, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__) -#define LogInfo(frmt, ...) LogObjc(LOG_FLAG_INFO, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__) -#define LogVerbose(frmt, ...) LogObjc(LOG_FLAG_VERBOSE, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__) - -#define LogCError(frmt, ...) LogC(LOG_FLAG_ERROR, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__) -#define LogCWarn(frmt, ...) LogC(LOG_FLAG_WARN, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__) -#define LogCInfo(frmt, ...) LogC(LOG_FLAG_INFO, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__) -#define LogCVerbose(frmt, ...) LogC(LOG_FLAG_VERBOSE, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__) - -#define LogTrace() LogObjc(LOG_FLAG_VERBOSE, @"%@: %@", THIS_FILE, THIS_METHOD) -#define LogCTrace() LogC(LOG_FLAG_VERBOSE, @"%@: %s", THIS_FILE, __FUNCTION__) - -#ifndef GCDAsyncSocketLogLevel -#define GCDAsyncSocketLogLevel LOG_LEVEL_VERBOSE -#endif - -// Log levels : off, error, warn, info, verbose -static const int logLevel = GCDAsyncSocketLogLevel; - -#else - -// Logging Disabled - -#define LogError(frmt, ...) {} -#define LogWarn(frmt, ...) {} -#define LogInfo(frmt, ...) {} -#define LogVerbose(frmt, ...) {} - -#define LogCError(frmt, ...) {} -#define LogCWarn(frmt, ...) {} -#define LogCInfo(frmt, ...) {} -#define LogCVerbose(frmt, ...) {} - -#define LogTrace() {} -#define LogCTrace(frmt, ...) {} - -#endif - -/** - * Seeing a return statements within an inner block - * can sometimes be mistaken for a return point of the enclosing method. - * This makes inline blocks a bit easier to read. -**/ -#define return_from_block return - -/** - * A socket file descriptor is really just an integer. - * It represents the index of the socket within the kernel. - * This makes invalid file descriptor comparisons easier to read. -**/ -#define SOCKET_NULL -1 - - -NSString *const GCDAsyncSocketException = @"GCDAsyncSocketException"; -NSString *const GCDAsyncSocketErrorDomain = @"GCDAsyncSocketErrorDomain"; - -NSString *const GCDAsyncSocketQueueName = @"GCDAsyncSocket"; -NSString *const GCDAsyncSocketThreadName = @"GCDAsyncSocket-CFStream"; - -NSString *const GCDAsyncSocketManuallyEvaluateTrust = @"GCDAsyncSocketManuallyEvaluateTrust"; -#if TARGET_OS_IPHONE -NSString *const GCDAsyncSocketUseCFStreamForTLS = @"GCDAsyncSocketUseCFStreamForTLS"; -#endif -NSString *const GCDAsyncSocketSSLPeerID = @"GCDAsyncSocketSSLPeerID"; -NSString *const GCDAsyncSocketSSLProtocolVersionMin = @"GCDAsyncSocketSSLProtocolVersionMin"; -NSString *const GCDAsyncSocketSSLProtocolVersionMax = @"GCDAsyncSocketSSLProtocolVersionMax"; -NSString *const GCDAsyncSocketSSLSessionOptionFalseStart = @"GCDAsyncSocketSSLSessionOptionFalseStart"; -NSString *const GCDAsyncSocketSSLSessionOptionSendOneByteRecord = @"GCDAsyncSocketSSLSessionOptionSendOneByteRecord"; -NSString *const GCDAsyncSocketSSLCipherSuites = @"GCDAsyncSocketSSLCipherSuites"; -#if !TARGET_OS_IPHONE -NSString *const GCDAsyncSocketSSLDiffieHellmanParameters = @"GCDAsyncSocketSSLDiffieHellmanParameters"; -#endif - -enum GCDAsyncSocketFlags -{ - kSocketStarted = 1 << 0, // If set, socket has been started (accepting/connecting) - kConnected = 1 << 1, // If set, the socket is connected - kForbidReadsWrites = 1 << 2, // If set, no new reads or writes are allowed - kReadsPaused = 1 << 3, // If set, reads are paused due to possible timeout - kWritesPaused = 1 << 4, // If set, writes are paused due to possible timeout - kDisconnectAfterReads = 1 << 5, // If set, disconnect after no more reads are queued - kDisconnectAfterWrites = 1 << 6, // If set, disconnect after no more writes are queued - kSocketCanAcceptBytes = 1 << 7, // If set, we know socket can accept bytes. If unset, it's unknown. - kReadSourceSuspended = 1 << 8, // If set, the read source is suspended - kWriteSourceSuspended = 1 << 9, // If set, the write source is suspended - kQueuedTLS = 1 << 10, // If set, we've queued an upgrade to TLS - kStartingReadTLS = 1 << 11, // If set, we're waiting for TLS negotiation to complete - kStartingWriteTLS = 1 << 12, // If set, we're waiting for TLS negotiation to complete - kSocketSecure = 1 << 13, // If set, socket is using secure communication via SSL/TLS - kSocketHasReadEOF = 1 << 14, // If set, we have read EOF from socket - kReadStreamClosed = 1 << 15, // If set, we've read EOF plus prebuffer has been drained - kDealloc = 1 << 16, // If set, the socket is being deallocated -#if TARGET_OS_IPHONE - kAddedStreamsToRunLoop = 1 << 17, // If set, CFStreams have been added to listener thread - kUsingCFStreamForTLS = 1 << 18, // If set, we're forced to use CFStream instead of SecureTransport - kSecureSocketHasBytesAvailable = 1 << 19, // If set, CFReadStream has notified us of bytes available -#endif -}; - -enum GCDAsyncSocketConfig -{ - kIPv4Disabled = 1 << 0, // If set, IPv4 is disabled - kIPv6Disabled = 1 << 1, // If set, IPv6 is disabled - kPreferIPv6 = 1 << 2, // If set, IPv6 is preferred over IPv4 - kAllowHalfDuplexConnection = 1 << 3, // If set, the socket will stay open even if the read stream closes -}; - -#if TARGET_OS_IPHONE - static NSThread *cfstreamThread; // Used for CFStreams - - static uint64_t cfstreamThreadRetainCount; // setup & teardown - static dispatch_queue_t cfstreamThreadSetupQueue; // setup & teardown -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * A PreBuffer is used when there is more data available on the socket - * than is being requested by current read request. - * In this case we slurp up all data from the socket (to minimize sys calls), - * and store additional yet unread data in a "prebuffer". - * - * The prebuffer is entirely drained before we read from the socket again. - * In other words, a large chunk of data is written is written to the prebuffer. - * The prebuffer is then drained via a series of one or more reads (for subsequent read request(s)). - * - * A ring buffer was once used for this purpose. - * But a ring buffer takes up twice as much memory as needed (double the size for mirroring). - * In fact, it generally takes up more than twice the needed size as everything has to be rounded up to vm_page_size. - * And since the prebuffer is always completely drained after being written to, a full ring buffer isn't needed. - * - * The current design is very simple and straight-forward, while also keeping memory requirements lower. -**/ - -@interface GCDAsyncSocketPreBuffer : NSObject -{ - uint8_t *preBuffer; - size_t preBufferSize; - - uint8_t *readPointer; - uint8_t *writePointer; -} - -- (id)initWithCapacity:(size_t)numBytes; - -- (void)ensureCapacityForWrite:(size_t)numBytes; - -- (size_t)availableBytes; -- (uint8_t *)readBuffer; - -- (void)getReadBuffer:(uint8_t **)bufferPtr availableBytes:(size_t *)availableBytesPtr; - -- (size_t)availableSpace; -- (uint8_t *)writeBuffer; - -- (void)getWriteBuffer:(uint8_t **)bufferPtr availableSpace:(size_t *)availableSpacePtr; - -- (void)didRead:(size_t)bytesRead; -- (void)didWrite:(size_t)bytesWritten; - -- (void)reset; - -@end - -@implementation GCDAsyncSocketPreBuffer - -- (id)initWithCapacity:(size_t)numBytes -{ - if ((self = [super init])) - { - preBufferSize = numBytes; - preBuffer = malloc(preBufferSize); - - readPointer = preBuffer; - writePointer = preBuffer; - } - return self; -} - -- (void)dealloc -{ - if (preBuffer) - free(preBuffer); -} - -- (void)ensureCapacityForWrite:(size_t)numBytes -{ - size_t availableSpace = [self availableSpace]; - - if (numBytes > availableSpace) - { - size_t additionalBytes = numBytes - availableSpace; - - size_t newPreBufferSize = preBufferSize + additionalBytes; - uint8_t *newPreBuffer = realloc(preBuffer, newPreBufferSize); - - size_t readPointerOffset = readPointer - preBuffer; - size_t writePointerOffset = writePointer - preBuffer; - - preBuffer = newPreBuffer; - preBufferSize = newPreBufferSize; - - readPointer = preBuffer + readPointerOffset; - writePointer = preBuffer + writePointerOffset; - } -} - -- (size_t)availableBytes -{ - return writePointer - readPointer; -} - -- (uint8_t *)readBuffer -{ - return readPointer; -} - -- (void)getReadBuffer:(uint8_t **)bufferPtr availableBytes:(size_t *)availableBytesPtr -{ - if (bufferPtr) *bufferPtr = readPointer; - if (availableBytesPtr) *availableBytesPtr = [self availableBytes]; -} - -- (void)didRead:(size_t)bytesRead -{ - readPointer += bytesRead; - - if (readPointer == writePointer) - { - // The prebuffer has been drained. Reset pointers. - readPointer = preBuffer; - writePointer = preBuffer; - } -} - -- (size_t)availableSpace -{ - return preBufferSize - (writePointer - preBuffer); -} - -- (uint8_t *)writeBuffer -{ - return writePointer; -} - -- (void)getWriteBuffer:(uint8_t **)bufferPtr availableSpace:(size_t *)availableSpacePtr -{ - if (bufferPtr) *bufferPtr = writePointer; - if (availableSpacePtr) *availableSpacePtr = [self availableSpace]; -} - -- (void)didWrite:(size_t)bytesWritten -{ - writePointer += bytesWritten; -} - -- (void)reset -{ - readPointer = preBuffer; - writePointer = preBuffer; -} - -@end - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * The GCDAsyncReadPacket encompasses the instructions for any given read. - * The content of a read packet allows the code to determine if we're: - * - reading to a certain length - * - reading to a certain separator - * - or simply reading the first chunk of available data -**/ -@interface GCDAsyncReadPacket : NSObject -{ - @public - NSMutableData *buffer; - NSUInteger startOffset; - NSUInteger bytesDone; - NSUInteger maxLength; - NSTimeInterval timeout; - NSUInteger readLength; - NSData *term; - BOOL bufferOwner; - NSUInteger originalBufferLength; - long tag; -} -- (id)initWithData:(NSMutableData *)d - startOffset:(NSUInteger)s - maxLength:(NSUInteger)m - timeout:(NSTimeInterval)t - readLength:(NSUInteger)l - terminator:(NSData *)e - tag:(long)i; - -- (void)ensureCapacityForAdditionalDataOfLength:(NSUInteger)bytesToRead; - -- (NSUInteger)optimalReadLengthWithDefault:(NSUInteger)defaultValue shouldPreBuffer:(BOOL *)shouldPreBufferPtr; - -- (NSUInteger)readLengthForNonTermWithHint:(NSUInteger)bytesAvailable; -- (NSUInteger)readLengthForTermWithHint:(NSUInteger)bytesAvailable shouldPreBuffer:(BOOL *)shouldPreBufferPtr; -- (NSUInteger)readLengthForTermWithPreBuffer:(GCDAsyncSocketPreBuffer *)preBuffer found:(BOOL *)foundPtr; - -- (NSInteger)searchForTermAfterPreBuffering:(ssize_t)numBytes; - -@end - -@implementation GCDAsyncReadPacket - -- (id)initWithData:(NSMutableData *)d - startOffset:(NSUInteger)s - maxLength:(NSUInteger)m - timeout:(NSTimeInterval)t - readLength:(NSUInteger)l - terminator:(NSData *)e - tag:(long)i -{ - if((self = [super init])) - { - bytesDone = 0; - maxLength = m; - timeout = t; - readLength = l; - term = [e copy]; - tag = i; - - if (d) - { - buffer = d; - startOffset = s; - bufferOwner = NO; - originalBufferLength = [d length]; - } - else - { - if (readLength > 0) - buffer = [[NSMutableData alloc] initWithLength:readLength]; - else - buffer = [[NSMutableData alloc] initWithLength:0]; - - startOffset = 0; - bufferOwner = YES; - originalBufferLength = 0; - } - } - return self; -} - -/** - * Increases the length of the buffer (if needed) to ensure a read of the given size will fit. -**/ -- (void)ensureCapacityForAdditionalDataOfLength:(NSUInteger)bytesToRead -{ - NSUInteger buffSize = [buffer length]; - NSUInteger buffUsed = startOffset + bytesDone; - - NSUInteger buffSpace = buffSize - buffUsed; - - if (bytesToRead > buffSpace) - { - NSUInteger buffInc = bytesToRead - buffSpace; - - [buffer increaseLengthBy:buffInc]; - } -} - -/** - * This method is used when we do NOT know how much data is available to be read from the socket. - * This method returns the default value unless it exceeds the specified readLength or maxLength. - * - * Furthermore, the shouldPreBuffer decision is based upon the packet type, - * and whether the returned value would fit in the current buffer without requiring a resize of the buffer. -**/ -- (NSUInteger)optimalReadLengthWithDefault:(NSUInteger)defaultValue shouldPreBuffer:(BOOL *)shouldPreBufferPtr -{ - NSUInteger result; - - if (readLength > 0) - { - // Read a specific length of data - - result = MIN(defaultValue, (readLength - bytesDone)); - - // There is no need to prebuffer since we know exactly how much data we need to read. - // Even if the buffer isn't currently big enough to fit this amount of data, - // it would have to be resized eventually anyway. - - if (shouldPreBufferPtr) - *shouldPreBufferPtr = NO; - } - else - { - // Either reading until we find a specified terminator, - // or we're simply reading all available data. - // - // In other words, one of: - // - // - readDataToData packet - // - readDataWithTimeout packet - - if (maxLength > 0) - result = MIN(defaultValue, (maxLength - bytesDone)); - else - result = defaultValue; - - // Since we don't know the size of the read in advance, - // the shouldPreBuffer decision is based upon whether the returned value would fit - // in the current buffer without requiring a resize of the buffer. - // - // This is because, in all likelyhood, the amount read from the socket will be less than the default value. - // Thus we should avoid over-allocating the read buffer when we can simply use the pre-buffer instead. - - if (shouldPreBufferPtr) - { - NSUInteger buffSize = [buffer length]; - NSUInteger buffUsed = startOffset + bytesDone; - - NSUInteger buffSpace = buffSize - buffUsed; - - if (buffSpace >= result) - *shouldPreBufferPtr = NO; - else - *shouldPreBufferPtr = YES; - } - } - - return result; -} - -/** - * For read packets without a set terminator, returns the amount of data - * that can be read without exceeding the readLength or maxLength. - * - * The given parameter indicates the number of bytes estimated to be available on the socket, - * which is taken into consideration during the calculation. - * - * The given hint MUST be greater than zero. -**/ -- (NSUInteger)readLengthForNonTermWithHint:(NSUInteger)bytesAvailable -{ - NSAssert(term == nil, @"This method does not apply to term reads"); - NSAssert(bytesAvailable > 0, @"Invalid parameter: bytesAvailable"); - - if (readLength > 0) - { - // Read a specific length of data - - return MIN(bytesAvailable, (readLength - bytesDone)); - - // No need to avoid resizing the buffer. - // If the user provided their own buffer, - // and told us to read a certain length of data that exceeds the size of the buffer, - // then it is clear that our code will resize the buffer during the read operation. - // - // This method does not actually do any resizing. - // The resizing will happen elsewhere if needed. - } - else - { - // Read all available data - - NSUInteger result = bytesAvailable; - - if (maxLength > 0) - { - result = MIN(result, (maxLength - bytesDone)); - } - - // No need to avoid resizing the buffer. - // If the user provided their own buffer, - // and told us to read all available data without giving us a maxLength, - // then it is clear that our code might resize the buffer during the read operation. - // - // This method does not actually do any resizing. - // The resizing will happen elsewhere if needed. - - return result; - } -} - -/** - * For read packets with a set terminator, returns the amount of data - * that can be read without exceeding the maxLength. - * - * The given parameter indicates the number of bytes estimated to be available on the socket, - * which is taken into consideration during the calculation. - * - * To optimize memory allocations, mem copies, and mem moves - * the shouldPreBuffer boolean value will indicate if the data should be read into a prebuffer first, - * or if the data can be read directly into the read packet's buffer. -**/ -- (NSUInteger)readLengthForTermWithHint:(NSUInteger)bytesAvailable shouldPreBuffer:(BOOL *)shouldPreBufferPtr -{ - NSAssert(term != nil, @"This method does not apply to non-term reads"); - NSAssert(bytesAvailable > 0, @"Invalid parameter: bytesAvailable"); - - - NSUInteger result = bytesAvailable; - - if (maxLength > 0) - { - result = MIN(result, (maxLength - bytesDone)); - } - - // Should the data be read into the read packet's buffer, or into a pre-buffer first? - // - // One would imagine the preferred option is the faster one. - // So which one is faster? - // - // Reading directly into the packet's buffer requires: - // 1. Possibly resizing packet buffer (malloc/realloc) - // 2. Filling buffer (read) - // 3. Searching for term (memcmp) - // 4. Possibly copying overflow into prebuffer (malloc/realloc, memcpy) - // - // Reading into prebuffer first: - // 1. Possibly resizing prebuffer (malloc/realloc) - // 2. Filling buffer (read) - // 3. Searching for term (memcmp) - // 4. Copying underflow into packet buffer (malloc/realloc, memcpy) - // 5. Removing underflow from prebuffer (memmove) - // - // Comparing the performance of the two we can see that reading - // data into the prebuffer first is slower due to the extra memove. - // - // However: - // The implementation of NSMutableData is open source via core foundation's CFMutableData. - // Decreasing the length of a mutable data object doesn't cause a realloc. - // In other words, the capacity of a mutable data object can grow, but doesn't shrink. - // - // This means the prebuffer will rarely need a realloc. - // The packet buffer, on the other hand, may often need a realloc. - // This is especially true if we are the buffer owner. - // Furthermore, if we are constantly realloc'ing the packet buffer, - // and then moving the overflow into the prebuffer, - // then we're consistently over-allocating memory for each term read. - // And now we get into a bit of a tradeoff between speed and memory utilization. - // - // The end result is that the two perform very similarly. - // And we can answer the original question very simply by another means. - // - // If we can read all the data directly into the packet's buffer without resizing it first, - // then we do so. Otherwise we use the prebuffer. - - if (shouldPreBufferPtr) - { - NSUInteger buffSize = [buffer length]; - NSUInteger buffUsed = startOffset + bytesDone; - - if ((buffSize - buffUsed) >= result) - *shouldPreBufferPtr = NO; - else - *shouldPreBufferPtr = YES; - } - - return result; -} - -/** - * For read packets with a set terminator, - * returns the amount of data that can be read from the given preBuffer, - * without going over a terminator or the maxLength. - * - * It is assumed the terminator has not already been read. -**/ -- (NSUInteger)readLengthForTermWithPreBuffer:(GCDAsyncSocketPreBuffer *)preBuffer found:(BOOL *)foundPtr -{ - NSAssert(term != nil, @"This method does not apply to non-term reads"); - NSAssert([preBuffer availableBytes] > 0, @"Invoked with empty pre buffer!"); - - // We know that the terminator, as a whole, doesn't exist in our own buffer. - // But it is possible that a _portion_ of it exists in our buffer. - // So we're going to look for the terminator starting with a portion of our own buffer. - // - // Example: - // - // term length = 3 bytes - // bytesDone = 5 bytes - // preBuffer length = 5 bytes - // - // If we append the preBuffer to our buffer, - // it would look like this: - // - // --------------------- - // |B|B|B|B|B|P|P|P|P|P| - // --------------------- - // - // So we start our search here: - // - // --------------------- - // |B|B|B|B|B|P|P|P|P|P| - // -------^-^-^--------- - // - // And move forwards... - // - // --------------------- - // |B|B|B|B|B|P|P|P|P|P| - // ---------^-^-^------- - // - // Until we find the terminator or reach the end. - // - // --------------------- - // |B|B|B|B|B|P|P|P|P|P| - // ---------------^-^-^- - - BOOL found = NO; - - NSUInteger termLength = [term length]; - NSUInteger preBufferLength = [preBuffer availableBytes]; - - if ((bytesDone + preBufferLength) < termLength) - { - // Not enough data for a full term sequence yet - return preBufferLength; - } - - NSUInteger maxPreBufferLength; - if (maxLength > 0) { - maxPreBufferLength = MIN(preBufferLength, (maxLength - bytesDone)); - - // Note: maxLength >= termLength - } - else { - maxPreBufferLength = preBufferLength; - } - - uint8_t seq[termLength]; - const void *termBuf = [term bytes]; - - NSUInteger bufLen = MIN(bytesDone, (termLength - 1)); - uint8_t *buf = (uint8_t *)[buffer mutableBytes] + startOffset + bytesDone - bufLen; - - NSUInteger preLen = termLength - bufLen; - const uint8_t *pre = [preBuffer readBuffer]; - - NSUInteger loopCount = bufLen + maxPreBufferLength - termLength + 1; // Plus one. See example above. - - NSUInteger result = maxPreBufferLength; - - NSUInteger i; - for (i = 0; i < loopCount; i++) - { - if (bufLen > 0) - { - // Combining bytes from buffer and preBuffer - - memcpy(seq, buf, bufLen); - memcpy(seq + bufLen, pre, preLen); - - if (memcmp(seq, termBuf, termLength) == 0) - { - result = preLen; - found = YES; - break; - } - - buf++; - bufLen--; - preLen++; - } - else - { - // Comparing directly from preBuffer - - if (memcmp(pre, termBuf, termLength) == 0) - { - NSUInteger preOffset = pre - [preBuffer readBuffer]; // pointer arithmetic - - result = preOffset + termLength; - found = YES; - break; - } - - pre++; - } - } - - // There is no need to avoid resizing the buffer in this particular situation. - - if (foundPtr) *foundPtr = found; - return result; -} - -/** - * For read packets with a set terminator, scans the packet buffer for the term. - * It is assumed the terminator had not been fully read prior to the new bytes. - * - * If the term is found, the number of excess bytes after the term are returned. - * If the term is not found, this method will return -1. - * - * Note: A return value of zero means the term was found at the very end. - * - * Prerequisites: - * The given number of bytes have been added to the end of our buffer. - * Our bytesDone variable has NOT been changed due to the prebuffered bytes. -**/ -- (NSInteger)searchForTermAfterPreBuffering:(ssize_t)numBytes -{ - NSAssert(term != nil, @"This method does not apply to non-term reads"); - - // The implementation of this method is very similar to the above method. - // See the above method for a discussion of the algorithm used here. - - uint8_t *buff = [buffer mutableBytes]; - NSUInteger buffLength = bytesDone + numBytes; - - const void *termBuff = [term bytes]; - NSUInteger termLength = [term length]; - - // Note: We are dealing with unsigned integers, - // so make sure the math doesn't go below zero. - - NSUInteger i = ((buffLength - numBytes) >= termLength) ? (buffLength - numBytes - termLength + 1) : 0; - - while (i + termLength <= buffLength) - { - uint8_t *subBuffer = buff + startOffset + i; - - if (memcmp(subBuffer, termBuff, termLength) == 0) - { - return buffLength - (i + termLength); - } - - i++; - } - - return -1; -} - - -@end - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * The GCDAsyncWritePacket encompasses the instructions for any given write. -**/ -@interface GCDAsyncWritePacket : NSObject -{ - @public - NSData *buffer; - NSUInteger bytesDone; - long tag; - NSTimeInterval timeout; -} -- (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i; -@end - -@implementation GCDAsyncWritePacket - -- (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i -{ - if((self = [super init])) - { - buffer = d; // Retain not copy. For performance as documented in header file. - bytesDone = 0; - timeout = t; - tag = i; - } - return self; -} - - -@end - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * The GCDAsyncSpecialPacket encompasses special instructions for interruptions in the read/write queues. - * This class my be altered to support more than just TLS in the future. -**/ -@interface GCDAsyncSpecialPacket : NSObject -{ - @public - NSDictionary *tlsSettings; -} -- (id)initWithTLSSettings:(NSDictionary *)settings; -@end - -@implementation GCDAsyncSpecialPacket - -- (id)initWithTLSSettings:(NSDictionary *)settings -{ - if((self = [super init])) - { - tlsSettings = [settings copy]; - } - return self; -} - - -@end - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -@implementation GCDAsyncSocket -{ - uint32_t flags; - uint16_t config; - - __weak id delegate; - dispatch_queue_t delegateQueue; - - int socket4FD; - int socket6FD; - int stateIndex; - NSData * connectInterface4; - NSData * connectInterface6; - - dispatch_queue_t socketQueue; - - dispatch_source_t accept4Source; - dispatch_source_t accept6Source; - dispatch_source_t connectTimer; - dispatch_source_t readSource; - dispatch_source_t writeSource; - dispatch_source_t readTimer; - dispatch_source_t writeTimer; - - NSMutableArray *readQueue; - NSMutableArray *writeQueue; - - GCDAsyncReadPacket *currentRead; - GCDAsyncWritePacket *currentWrite; - - unsigned long socketFDBytesAvailable; - - GCDAsyncSocketPreBuffer *preBuffer; - -#if TARGET_OS_IPHONE - CFStreamClientContext streamContext; - CFReadStreamRef readStream; - CFWriteStreamRef writeStream; -#endif - SSLContextRef sslContext; - GCDAsyncSocketPreBuffer *sslPreBuffer; - size_t sslWriteCachedLength; - OSStatus sslErrCode; - - void *IsOnSocketQueueOrTargetQueueKey; - - id userData; -} - -- (id)init -{ - return [self initWithDelegate:nil delegateQueue:NULL socketQueue:NULL]; -} - -- (id)initWithSocketQueue:(dispatch_queue_t)sq -{ - return [self initWithDelegate:nil delegateQueue:NULL socketQueue:sq]; -} - -- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq -{ - return [self initWithDelegate:aDelegate delegateQueue:dq socketQueue:NULL]; -} - -- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq -{ - if((self = [super init])) - { - delegate = aDelegate; - delegateQueue = dq; - - #if !OS_OBJECT_USE_OBJC - if (dq) dispatch_retain(dq); - #endif - - socket4FD = SOCKET_NULL; - socket6FD = SOCKET_NULL; - stateIndex = 0; - - if (sq) - { - NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), - @"The given socketQueue parameter must not be a concurrent queue."); - NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), - @"The given socketQueue parameter must not be a concurrent queue."); - NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - @"The given socketQueue parameter must not be a concurrent queue."); - - socketQueue = sq; - #if !OS_OBJECT_USE_OBJC - dispatch_retain(sq); - #endif - } - else - { - socketQueue = dispatch_queue_create([GCDAsyncSocketQueueName UTF8String], NULL); - } - - // The dispatch_queue_set_specific() and dispatch_get_specific() functions take a "void *key" parameter. - // From the documentation: - // - // > Keys are only compared as pointers and are never dereferenced. - // > Thus, you can use a pointer to a static variable for a specific subsystem or - // > any other value that allows you to identify the value uniquely. - // - // We're just going to use the memory address of an ivar. - // Specifically an ivar that is explicitly named for our purpose to make the code more readable. - // - // However, it feels tedious (and less readable) to include the "&" all the time: - // dispatch_get_specific(&IsOnSocketQueueOrTargetQueueKey) - // - // So we're going to make it so it doesn't matter if we use the '&' or not, - // by assigning the value of the ivar to the address of the ivar. - // Thus: IsOnSocketQueueOrTargetQueueKey == &IsOnSocketQueueOrTargetQueueKey; - - IsOnSocketQueueOrTargetQueueKey = &IsOnSocketQueueOrTargetQueueKey; - - void *nonNullUnusedPointer = (__bridge void *)self; - dispatch_queue_set_specific(socketQueue, IsOnSocketQueueOrTargetQueueKey, nonNullUnusedPointer, NULL); - - readQueue = [[NSMutableArray alloc] initWithCapacity:5]; - currentRead = nil; - - writeQueue = [[NSMutableArray alloc] initWithCapacity:5]; - currentWrite = nil; - - preBuffer = [[GCDAsyncSocketPreBuffer alloc] initWithCapacity:(1024 * 4)]; - } - return self; -} - -- (void)dealloc -{ - LogInfo(@"%@ - %@ (start)", THIS_METHOD, self); - - // Set dealloc flag. - // This is used by closeWithError to ensure we don't accidentally retain ourself. - flags |= kDealloc; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - [self closeWithError:nil]; - } - else - { - dispatch_sync(socketQueue, ^{ - [self closeWithError:nil]; - }); - } - - delegate = nil; - - #if !OS_OBJECT_USE_OBJC - if (delegateQueue) dispatch_release(delegateQueue); - #endif - delegateQueue = NULL; - - #if !OS_OBJECT_USE_OBJC - if (socketQueue) dispatch_release(socketQueue); - #endif - socketQueue = NULL; - - LogInfo(@"%@ - %@ (finish)", THIS_METHOD, self); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Configuration -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (id)delegate -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return delegate; - } - else - { - __block id result; - - dispatch_sync(socketQueue, ^{ - result = delegate; - }); - - return result; - } -} - -- (void)setDelegate:(id)newDelegate synchronously:(BOOL)synchronously -{ - dispatch_block_t block = ^{ - delegate = newDelegate; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) { - block(); - } - else { - if (synchronously) - dispatch_sync(socketQueue, block); - else - dispatch_async(socketQueue, block); - } -} - -- (void)setDelegate:(id)newDelegate -{ - [self setDelegate:newDelegate synchronously:NO]; -} - -- (void)synchronouslySetDelegate:(id)newDelegate -{ - [self setDelegate:newDelegate synchronously:YES]; -} - -- (dispatch_queue_t)delegateQueue -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return delegateQueue; - } - else - { - __block dispatch_queue_t result; - - dispatch_sync(socketQueue, ^{ - result = delegateQueue; - }); - - return result; - } -} - -- (void)setDelegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously -{ - dispatch_block_t block = ^{ - - #if !OS_OBJECT_USE_OBJC - if (delegateQueue) dispatch_release(delegateQueue); - if (newDelegateQueue) dispatch_retain(newDelegateQueue); - #endif - - delegateQueue = newDelegateQueue; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) { - block(); - } - else { - if (synchronously) - dispatch_sync(socketQueue, block); - else - dispatch_async(socketQueue, block); - } -} - -- (void)setDelegateQueue:(dispatch_queue_t)newDelegateQueue -{ - [self setDelegateQueue:newDelegateQueue synchronously:NO]; -} - -- (void)synchronouslySetDelegateQueue:(dispatch_queue_t)newDelegateQueue -{ - [self setDelegateQueue:newDelegateQueue synchronously:YES]; -} - -- (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - if (delegatePtr) *delegatePtr = delegate; - if (delegateQueuePtr) *delegateQueuePtr = delegateQueue; - } - else - { - __block id dPtr = NULL; - __block dispatch_queue_t dqPtr = NULL; - - dispatch_sync(socketQueue, ^{ - dPtr = delegate; - dqPtr = delegateQueue; - }); - - if (delegatePtr) *delegatePtr = dPtr; - if (delegateQueuePtr) *delegateQueuePtr = dqPtr; - } -} - -- (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously -{ - dispatch_block_t block = ^{ - - delegate = newDelegate; - - #if !OS_OBJECT_USE_OBJC - if (delegateQueue) dispatch_release(delegateQueue); - if (newDelegateQueue) dispatch_retain(newDelegateQueue); - #endif - - delegateQueue = newDelegateQueue; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) { - block(); - } - else { - if (synchronously) - dispatch_sync(socketQueue, block); - else - dispatch_async(socketQueue, block); - } -} - -- (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue -{ - [self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:NO]; -} - -- (void)synchronouslySetDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue -{ - [self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:YES]; -} - -- (BOOL)isIPv4Enabled -{ - // Note: YES means kIPv4Disabled is OFF - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return ((config & kIPv4Disabled) == 0); - } - else - { - __block BOOL result; - - dispatch_sync(socketQueue, ^{ - result = ((config & kIPv4Disabled) == 0); - }); - - return result; - } -} - -- (void)setIPv4Enabled:(BOOL)flag -{ - // Note: YES means kIPv4Disabled is OFF - - dispatch_block_t block = ^{ - - if (flag) - config &= ~kIPv4Disabled; - else - config |= kIPv4Disabled; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_async(socketQueue, block); -} - -- (BOOL)isIPv6Enabled -{ - // Note: YES means kIPv6Disabled is OFF - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return ((config & kIPv6Disabled) == 0); - } - else - { - __block BOOL result; - - dispatch_sync(socketQueue, ^{ - result = ((config & kIPv6Disabled) == 0); - }); - - return result; - } -} - -- (void)setIPv6Enabled:(BOOL)flag -{ - // Note: YES means kIPv6Disabled is OFF - - dispatch_block_t block = ^{ - - if (flag) - config &= ~kIPv6Disabled; - else - config |= kIPv6Disabled; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_async(socketQueue, block); -} - -- (BOOL)isIPv4PreferredOverIPv6 -{ - // Note: YES means kPreferIPv6 is OFF - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return ((config & kPreferIPv6) == 0); - } - else - { - __block BOOL result; - - dispatch_sync(socketQueue, ^{ - result = ((config & kPreferIPv6) == 0); - }); - - return result; - } -} - -- (void)setIPv4PreferredOverIPv6:(BOOL)flag -{ - // Note: YES means kPreferIPv6 is OFF - - dispatch_block_t block = ^{ - - if (flag) - config &= ~kPreferIPv6; - else - config |= kPreferIPv6; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_async(socketQueue, block); -} - -- (id)userData -{ - __block id result = nil; - - dispatch_block_t block = ^{ - - result = userData; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - return result; -} - -- (void)setUserData:(id)arbitraryUserData -{ - dispatch_block_t block = ^{ - - if (userData != arbitraryUserData) - { - userData = arbitraryUserData; - } - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_async(socketQueue, block); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Accepting -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (BOOL)acceptOnPort:(uint16_t)port error:(NSError **)errPtr -{ - return [self acceptOnInterface:nil port:port error:errPtr]; -} - -- (BOOL)acceptOnInterface:(NSString *)inInterface port:(uint16_t)port error:(NSError **)errPtr -{ - LogTrace(); - - // Just in-case interface parameter is immutable. - NSString *interface = [inInterface copy]; - - __block BOOL result = NO; - __block NSError *err = nil; - - // CreateSocket Block - // This block will be invoked within the dispatch block below. - - int(^createSocket)(int, NSData*) = ^int (int domain, NSData *interfaceAddr) { - - int socketFD = socket(domain, SOCK_STREAM, 0); - - if (socketFD == SOCKET_NULL) - { - NSString *reason = @"Error in socket() function"; - err = [self errnoErrorWithReason:reason]; - - return SOCKET_NULL; - } - - int status; - - // Set socket options - - status = fcntl(socketFD, F_SETFL, O_NONBLOCK); - if (status == -1) - { - NSString *reason = @"Error enabling non-blocking IO on socket (fcntl)"; - err = [self errnoErrorWithReason:reason]; - - LogVerbose(@"close(socketFD)"); - close(socketFD); - return SOCKET_NULL; - } - - int reuseOn = 1; - status = setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn)); - if (status == -1) - { - NSString *reason = @"Error enabling address reuse (setsockopt)"; - err = [self errnoErrorWithReason:reason]; - - LogVerbose(@"close(socketFD)"); - close(socketFD); - return SOCKET_NULL; - } - - // Bind socket - - status = bind(socketFD, (const struct sockaddr *)[interfaceAddr bytes], (socklen_t)[interfaceAddr length]); - if (status == -1) - { - NSString *reason = @"Error in bind() function"; - err = [self errnoErrorWithReason:reason]; - - LogVerbose(@"close(socketFD)"); - close(socketFD); - return SOCKET_NULL; - } - - // Listen - - status = listen(socketFD, 1024); - if (status == -1) - { - NSString *reason = @"Error in listen() function"; - err = [self errnoErrorWithReason:reason]; - - LogVerbose(@"close(socketFD)"); - close(socketFD); - return SOCKET_NULL; - } - - return socketFD; - }; - - // Create dispatch block and run on socketQueue - - dispatch_block_t block = ^{ @autoreleasepool { - - if (delegate == nil) // Must have delegate set - { - NSString *msg = @"Attempting to accept without a delegate. Set a delegate first."; - err = [self badConfigError:msg]; - - return_from_block; - } - - if (delegateQueue == NULL) // Must have delegate queue set - { - NSString *msg = @"Attempting to accept without a delegate queue. Set a delegate queue first."; - err = [self badConfigError:msg]; - - return_from_block; - } - - BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO; - BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO; - - if (isIPv4Disabled && isIPv6Disabled) // Must have IPv4 or IPv6 enabled - { - NSString *msg = @"Both IPv4 and IPv6 have been disabled. Must enable at least one protocol first."; - err = [self badConfigError:msg]; - - return_from_block; - } - - if (![self isDisconnected]) // Must be disconnected - { - NSString *msg = @"Attempting to accept while connected or accepting connections. Disconnect first."; - err = [self badConfigError:msg]; - - return_from_block; - } - - // Clear queues (spurious read/write requests post disconnect) - [readQueue removeAllObjects]; - [writeQueue removeAllObjects]; - - // Resolve interface from description - - NSMutableData *interface4 = nil; - NSMutableData *interface6 = nil; - - [self getInterfaceAddress4:&interface4 address6:&interface6 fromDescription:interface port:port]; - - if ((interface4 == nil) && (interface6 == nil)) - { - NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address."; - err = [self badParamError:msg]; - - return_from_block; - } - - if (isIPv4Disabled && (interface6 == nil)) - { - NSString *msg = @"IPv4 has been disabled and specified interface doesn't support IPv6."; - err = [self badParamError:msg]; - - return_from_block; - } - - if (isIPv6Disabled && (interface4 == nil)) - { - NSString *msg = @"IPv6 has been disabled and specified interface doesn't support IPv4."; - err = [self badParamError:msg]; - - return_from_block; - } - - BOOL enableIPv4 = !isIPv4Disabled && (interface4 != nil); - BOOL enableIPv6 = !isIPv6Disabled && (interface6 != nil); - - // Create sockets, configure, bind, and listen - - if (enableIPv4) - { - LogVerbose(@"Creating IPv4 socket"); - socket4FD = createSocket(AF_INET, interface4); - - if (socket4FD == SOCKET_NULL) - { - return_from_block; - } - } - - if (enableIPv6) - { - LogVerbose(@"Creating IPv6 socket"); - - if (enableIPv4 && (port == 0)) - { - // No specific port was specified, so we allowed the OS to pick an available port for us. - // Now we need to make sure the IPv6 socket listens on the same port as the IPv4 socket. - - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)[interface6 mutableBytes]; - addr6->sin6_port = htons([self localPort4]); - } - - socket6FD = createSocket(AF_INET6, interface6); - - if (socket6FD == SOCKET_NULL) - { - if (socket4FD != SOCKET_NULL) - { - LogVerbose(@"close(socket4FD)"); - close(socket4FD); - } - - return_from_block; - } - } - - // Create accept sources - - if (enableIPv4) - { - accept4Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket4FD, 0, socketQueue); - - int socketFD = socket4FD; - dispatch_source_t acceptSource = accept4Source; - - __weak GCDAsyncSocket *weakSelf = self; - - dispatch_source_set_event_handler(accept4Source, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - LogVerbose(@"event4Block"); - - unsigned long i = 0; - unsigned long numPendingConnections = dispatch_source_get_data(acceptSource); - - LogVerbose(@"numPendingConnections: %lu", numPendingConnections); - - while ([strongSelf doAccept:socketFD] && (++i < numPendingConnections)); - - #pragma clang diagnostic pop - }}); - - - dispatch_source_set_cancel_handler(accept4Source, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - #if !OS_OBJECT_USE_OBJC - LogVerbose(@"dispatch_release(accept4Source)"); - dispatch_release(acceptSource); - #endif - - LogVerbose(@"close(socket4FD)"); - close(socketFD); - - #pragma clang diagnostic pop - }); - - LogVerbose(@"dispatch_resume(accept4Source)"); - dispatch_resume(accept4Source); - } - - if (enableIPv6) - { - accept6Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket6FD, 0, socketQueue); - - int socketFD = socket6FD; - dispatch_source_t acceptSource = accept6Source; - - __weak GCDAsyncSocket *weakSelf = self; - - dispatch_source_set_event_handler(accept6Source, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - LogVerbose(@"event6Block"); - - unsigned long i = 0; - unsigned long numPendingConnections = dispatch_source_get_data(acceptSource); - - LogVerbose(@"numPendingConnections: %lu", numPendingConnections); - - while ([strongSelf doAccept:socketFD] && (++i < numPendingConnections)); - - #pragma clang diagnostic pop - }}); - - dispatch_source_set_cancel_handler(accept6Source, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - #if !OS_OBJECT_USE_OBJC - LogVerbose(@"dispatch_release(accept6Source)"); - dispatch_release(acceptSource); - #endif - - LogVerbose(@"close(socket6FD)"); - close(socketFD); - - #pragma clang diagnostic pop - }); - - LogVerbose(@"dispatch_resume(accept6Source)"); - dispatch_resume(accept6Source); - } - - flags |= kSocketStarted; - - result = YES; - }}; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - if (result == NO) - { - LogInfo(@"Error in accept: %@", err); - - if (errPtr) - *errPtr = err; - } - - return result; -} - -- (BOOL)doAccept:(int)parentSocketFD -{ - LogTrace(); - - BOOL isIPv4; - int childSocketFD; - NSData *childSocketAddress; - - if (parentSocketFD == socket4FD) - { - isIPv4 = YES; - - struct sockaddr_in addr; - socklen_t addrLen = sizeof(addr); - - childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen); - - if (childSocketFD == -1) - { - LogWarn(@"Accept failed with error: %@", [self errnoError]); - return NO; - } - - childSocketAddress = [NSData dataWithBytes:&addr length:addrLen]; - } - else // if (parentSocketFD == socket6FD) - { - isIPv4 = NO; - - struct sockaddr_in6 addr; - socklen_t addrLen = sizeof(addr); - - childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen); - - if (childSocketFD == -1) - { - LogWarn(@"Accept failed with error: %@", [self errnoError]); - return NO; - } - - childSocketAddress = [NSData dataWithBytes:&addr length:addrLen]; - } - - // Enable non-blocking IO on the socket - - int result = fcntl(childSocketFD, F_SETFL, O_NONBLOCK); - if (result == -1) - { - LogWarn(@"Error enabling non-blocking IO on accepted socket (fcntl)"); - return NO; - } - - // Prevent SIGPIPE signals - - int nosigpipe = 1; - setsockopt(childSocketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe)); - - // Notify delegate - - if (delegateQueue) - { - __strong id theDelegate = delegate; - - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - // Query delegate for custom socket queue - - dispatch_queue_t childSocketQueue = NULL; - - if ([theDelegate respondsToSelector:@selector(newSocketQueueForConnectionFromAddress:onSocket:)]) - { - childSocketQueue = [theDelegate newSocketQueueForConnectionFromAddress:childSocketAddress - onSocket:self]; - } - - // Create GCDAsyncSocket instance for accepted socket - - GCDAsyncSocket *acceptedSocket = [[GCDAsyncSocket alloc] initWithDelegate:theDelegate - delegateQueue:delegateQueue - socketQueue:childSocketQueue]; - - if (isIPv4) - acceptedSocket->socket4FD = childSocketFD; - else - acceptedSocket->socket6FD = childSocketFD; - - acceptedSocket->flags = (kSocketStarted | kConnected); - - // Setup read and write sources for accepted socket - - dispatch_async(acceptedSocket->socketQueue, ^{ @autoreleasepool { - - [acceptedSocket setupReadAndWriteSourcesForNewlyConnectedSocket:childSocketFD]; - }}); - - // Notify delegate - - if ([theDelegate respondsToSelector:@selector(socket:didAcceptNewSocket:)]) - { - [theDelegate socket:self didAcceptNewSocket:acceptedSocket]; - } - - // Release the socket queue returned from the delegate (it was retained by acceptedSocket) - #if !OS_OBJECT_USE_OBJC - if (childSocketQueue) dispatch_release(childSocketQueue); - #endif - - // The accepted socket should have been retained by the delegate. - // Otherwise it gets properly released when exiting the block. - }}); - } - - return YES; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Connecting -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * This method runs through the various checks required prior to a connection attempt. - * It is shared between the connectToHost and connectToAddress methods. - * -**/ -- (BOOL)preConnectWithInterface:(NSString *)interface error:(NSError **)errPtr -{ - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - if (delegate == nil) // Must have delegate set - { - if (errPtr) - { - NSString *msg = @"Attempting to connect without a delegate. Set a delegate first."; - *errPtr = [self badConfigError:msg]; - } - return NO; - } - - if (delegateQueue == NULL) // Must have delegate queue set - { - if (errPtr) - { - NSString *msg = @"Attempting to connect without a delegate queue. Set a delegate queue first."; - *errPtr = [self badConfigError:msg]; - } - return NO; - } - - if (![self isDisconnected]) // Must be disconnected - { - if (errPtr) - { - NSString *msg = @"Attempting to connect while connected or accepting connections. Disconnect first."; - *errPtr = [self badConfigError:msg]; - } - return NO; - } - - BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO; - BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO; - - if (isIPv4Disabled && isIPv6Disabled) // Must have IPv4 or IPv6 enabled - { - if (errPtr) - { - NSString *msg = @"Both IPv4 and IPv6 have been disabled. Must enable at least one protocol first."; - *errPtr = [self badConfigError:msg]; - } - return NO; - } - - if (interface) - { - NSMutableData *interface4 = nil; - NSMutableData *interface6 = nil; - - [self getInterfaceAddress4:&interface4 address6:&interface6 fromDescription:interface port:0]; - - if ((interface4 == nil) && (interface6 == nil)) - { - if (errPtr) - { - NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address."; - *errPtr = [self badParamError:msg]; - } - return NO; - } - - if (isIPv4Disabled && (interface6 == nil)) - { - if (errPtr) - { - NSString *msg = @"IPv4 has been disabled and specified interface doesn't support IPv6."; - *errPtr = [self badParamError:msg]; - } - return NO; - } - - if (isIPv6Disabled && (interface4 == nil)) - { - if (errPtr) - { - NSString *msg = @"IPv6 has been disabled and specified interface doesn't support IPv4."; - *errPtr = [self badParamError:msg]; - } - return NO; - } - - connectInterface4 = interface4; - connectInterface6 = interface6; - } - - // Clear queues (spurious read/write requests post disconnect) - [readQueue removeAllObjects]; - [writeQueue removeAllObjects]; - - return YES; -} - -- (BOOL)connectToHost:(NSString*)host onPort:(uint16_t)port error:(NSError **)errPtr -{ - return [self connectToHost:host onPort:port withTimeout:-1 error:errPtr]; -} - -- (BOOL)connectToHost:(NSString *)host - onPort:(uint16_t)port - withTimeout:(NSTimeInterval)timeout - error:(NSError **)errPtr -{ - return [self connectToHost:host onPort:port viaInterface:nil withTimeout:timeout error:errPtr]; -} - -- (BOOL)connectToHost:(NSString *)inHost - onPort:(uint16_t)port - viaInterface:(NSString *)inInterface - withTimeout:(NSTimeInterval)timeout - error:(NSError **)errPtr -{ - LogTrace(); - - // Just in case immutable objects were passed - NSString *host = [inHost copy]; - NSString *interface = [inInterface copy]; - - __block BOOL result = NO; - __block NSError *preConnectErr = nil; - - dispatch_block_t block = ^{ @autoreleasepool { - - // Check for problems with host parameter - - if ([host length] == 0) - { - NSString *msg = @"Invalid host parameter (nil or \"\"). Should be a domain name or IP address string."; - preConnectErr = [self badParamError:msg]; - - return_from_block; - } - - // Run through standard pre-connect checks - - if (![self preConnectWithInterface:interface error:&preConnectErr]) - { - return_from_block; - } - - // We've made it past all the checks. - // It's time to start the connection process. - - flags |= kSocketStarted; - - LogVerbose(@"Dispatching DNS lookup..."); - - // It's possible that the given host parameter is actually a NSMutableString. - // So we want to copy it now, within this block that will be executed synchronously. - // This way the asynchronous lookup block below doesn't have to worry about it changing. - - NSString *hostCpy = [host copy]; - - int aStateIndex = stateIndex; - __weak GCDAsyncSocket *weakSelf = self; - - dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_async(globalConcurrentQueue, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - NSError *lookupErr = nil; - NSMutableArray *addresses = [GCDAsyncSocket lookupHost:hostCpy port:port error:&lookupErr]; - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - if (lookupErr) - { - dispatch_async(strongSelf->socketQueue, ^{ @autoreleasepool { - - [strongSelf lookup:aStateIndex didFail:lookupErr]; - }}); - } - else - { - NSData *address4 = nil; - NSData *address6 = nil; - - for (NSData *address in addresses) - { - if (!address4 && [GCDAsyncSocket isIPv4Address:address]) - { - address4 = address; - } - else if (!address6 && [GCDAsyncSocket isIPv6Address:address]) - { - address6 = address; - } - } - - dispatch_async(strongSelf->socketQueue, ^{ @autoreleasepool { - - [strongSelf lookup:aStateIndex didSucceedWithAddress4:address4 address6:address6]; - }}); - } - - #pragma clang diagnostic pop - }}); - - [self startConnectTimeout:timeout]; - - result = YES; - }}; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - - if (errPtr) *errPtr = preConnectErr; - return result; -} - -- (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr -{ - return [self connectToAddress:remoteAddr viaInterface:nil withTimeout:-1 error:errPtr]; -} - -- (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr -{ - return [self connectToAddress:remoteAddr viaInterface:nil withTimeout:timeout error:errPtr]; -} - -- (BOOL)connectToAddress:(NSData *)inRemoteAddr - viaInterface:(NSString *)inInterface - withTimeout:(NSTimeInterval)timeout - error:(NSError **)errPtr -{ - LogTrace(); - - // Just in case immutable objects were passed - NSData *remoteAddr = [inRemoteAddr copy]; - NSString *interface = [inInterface copy]; - - __block BOOL result = NO; - __block NSError *err = nil; - - dispatch_block_t block = ^{ @autoreleasepool { - - // Check for problems with remoteAddr parameter - - NSData *address4 = nil; - NSData *address6 = nil; - - if ([remoteAddr length] >= sizeof(struct sockaddr)) - { - const struct sockaddr *sockaddr = (const struct sockaddr *)[remoteAddr bytes]; - - if (sockaddr->sa_family == AF_INET) - { - if ([remoteAddr length] == sizeof(struct sockaddr_in)) - { - address4 = remoteAddr; - } - } - else if (sockaddr->sa_family == AF_INET6) - { - if ([remoteAddr length] == sizeof(struct sockaddr_in6)) - { - address6 = remoteAddr; - } - } - } - - if ((address4 == nil) && (address6 == nil)) - { - NSString *msg = @"A valid IPv4 or IPv6 address was not given"; - err = [self badParamError:msg]; - - return_from_block; - } - - BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO; - BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO; - - if (isIPv4Disabled && (address4 != nil)) - { - NSString *msg = @"IPv4 has been disabled and an IPv4 address was passed."; - err = [self badParamError:msg]; - - return_from_block; - } - - if (isIPv6Disabled && (address6 != nil)) - { - NSString *msg = @"IPv6 has been disabled and an IPv6 address was passed."; - err = [self badParamError:msg]; - - return_from_block; - } - - // Run through standard pre-connect checks - - if (![self preConnectWithInterface:interface error:&err]) - { - return_from_block; - } - - // We've made it past all the checks. - // It's time to start the connection process. - - if (![self connectWithAddress4:address4 address6:address6 error:&err]) - { - return_from_block; - } - - flags |= kSocketStarted; - - [self startConnectTimeout:timeout]; - - result = YES; - }}; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - if (result == NO) - { - if (errPtr) - *errPtr = err; - } - - return result; -} - -- (void)lookup:(int)aStateIndex didSucceedWithAddress4:(NSData *)address4 address6:(NSData *)address6 -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - NSAssert(address4 || address6, @"Expected at least one valid address"); - - if (aStateIndex != stateIndex) - { - LogInfo(@"Ignoring lookupDidSucceed, already disconnected"); - - // The connect operation has been cancelled. - // That is, socket was disconnected, or connection has already timed out. - return; - } - - // Check for problems - - BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO; - BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO; - - if (isIPv4Disabled && (address6 == nil)) - { - NSString *msg = @"IPv4 has been disabled and DNS lookup found no IPv6 address."; - - [self closeWithError:[self otherError:msg]]; - return; - } - - if (isIPv6Disabled && (address4 == nil)) - { - NSString *msg = @"IPv6 has been disabled and DNS lookup found no IPv4 address."; - - [self closeWithError:[self otherError:msg]]; - return; - } - - // Start the normal connection process - - NSError *err = nil; - if (![self connectWithAddress4:address4 address6:address6 error:&err]) - { - [self closeWithError:err]; - } -} - -/** - * This method is called if the DNS lookup fails. - * This method is executed on the socketQueue. - * - * Since the DNS lookup executed synchronously on a global concurrent queue, - * the original connection request may have already been cancelled or timed-out by the time this method is invoked. - * The lookupIndex tells us whether the lookup is still valid or not. -**/ -- (void)lookup:(int)aStateIndex didFail:(NSError *)error -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - - if (aStateIndex != stateIndex) - { - LogInfo(@"Ignoring lookup:didFail: - already disconnected"); - - // The connect operation has been cancelled. - // That is, socket was disconnected, or connection has already timed out. - return; - } - - [self endConnectTimeout]; - [self closeWithError:error]; -} - -- (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - LogVerbose(@"IPv4: %@:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]); - LogVerbose(@"IPv6: %@:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]); - - // Determine socket type - - BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO; - - BOOL useIPv6 = ((preferIPv6 && address6) || (address4 == nil)); - - // Create the socket - - int socketFD; - NSData *address; - NSData *connectInterface; - - if (useIPv6) - { - LogVerbose(@"Creating IPv6 socket"); - - socket6FD = socket(AF_INET6, SOCK_STREAM, 0); - - socketFD = socket6FD; - address = address6; - connectInterface = connectInterface6; - } - else - { - LogVerbose(@"Creating IPv4 socket"); - - socket4FD = socket(AF_INET, SOCK_STREAM, 0); - - socketFD = socket4FD; - address = address4; - connectInterface = connectInterface4; - } - - if (socketFD == SOCKET_NULL) - { - if (errPtr) - *errPtr = [self errnoErrorWithReason:@"Error in socket() function"]; - - return NO; - } - - // Bind the socket to the desired interface (if needed) - - if (connectInterface) - { - LogVerbose(@"Binding socket..."); - - if ([[self class] portFromAddress:connectInterface] > 0) - { - // Since we're going to be binding to a specific port, - // we should turn on reuseaddr to allow us to override sockets in time_wait. - - int reuseOn = 1; - setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn)); - } - - const struct sockaddr *interfaceAddr = (const struct sockaddr *)[connectInterface bytes]; - - int result = bind(socketFD, interfaceAddr, (socklen_t)[connectInterface length]); - if (result != 0) - { - if (errPtr) - *errPtr = [self errnoErrorWithReason:@"Error in bind() function"]; - - return NO; - } - } - - // Prevent SIGPIPE signals - - int nosigpipe = 1; - setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe)); - - // Start the connection process in a background queue - - int aStateIndex = stateIndex; - __weak GCDAsyncSocket *weakSelf = self; - - dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_async(globalConcurrentQueue, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]); - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - if (result == 0) - { - dispatch_async(strongSelf->socketQueue, ^{ @autoreleasepool { - - [strongSelf didConnect:aStateIndex]; - }}); - } - else - { - NSError *error = [strongSelf errnoErrorWithReason:@"Error in connect() function"]; - - dispatch_async(strongSelf->socketQueue, ^{ @autoreleasepool { - - [strongSelf didNotConnect:aStateIndex error:error]; - }}); - } - - #pragma clang diagnostic pop - }); - - LogVerbose(@"Connecting..."); - - return YES; -} - -- (void)didConnect:(int)aStateIndex -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - - if (aStateIndex != stateIndex) - { - LogInfo(@"Ignoring didConnect, already disconnected"); - - // The connect operation has been cancelled. - // That is, socket was disconnected, or connection has already timed out. - return; - } - - flags |= kConnected; - - [self endConnectTimeout]; - - #if TARGET_OS_IPHONE - // The endConnectTimeout method executed above incremented the stateIndex. - aStateIndex = stateIndex; - #endif - - // Setup read/write streams (as workaround for specific shortcomings in the iOS platform) - // - // Note: - // There may be configuration options that must be set by the delegate before opening the streams. - // The primary example is the kCFStreamNetworkServiceTypeVoIP flag, which only works on an unopened stream. - // - // Thus we wait until after the socket:didConnectToHost:port: delegate method has completed. - // This gives the delegate time to properly configure the streams if needed. - - dispatch_block_t SetupStreamsPart1 = ^{ - #if TARGET_OS_IPHONE - - if (![self createReadAndWriteStream]) - { - [self closeWithError:[self otherError:@"Error creating CFStreams"]]; - return; - } - - if (![self registerForStreamCallbacksIncludingReadWrite:NO]) - { - [self closeWithError:[self otherError:@"Error in CFStreamSetClient"]]; - return; - } - - #endif - }; - dispatch_block_t SetupStreamsPart2 = ^{ - #if TARGET_OS_IPHONE - - if (aStateIndex != stateIndex) - { - // The socket has been disconnected. - return; - } - - if (![self addStreamsToRunLoop]) - { - [self closeWithError:[self otherError:@"Error in CFStreamScheduleWithRunLoop"]]; - return; - } - - if (![self openStreams]) - { - [self closeWithError:[self otherError:@"Error creating CFStreams"]]; - return; - } - - #endif - }; - - // Notify delegate - - NSString *host = [self connectedHost]; - uint16_t port = [self connectedPort]; - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:didConnectToHost:port:)]) - { - SetupStreamsPart1(); - - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socket:self didConnectToHost:host port:port]; - - dispatch_async(socketQueue, ^{ @autoreleasepool { - - SetupStreamsPart2(); - }}); - }}); - } - else - { - SetupStreamsPart1(); - SetupStreamsPart2(); - } - - // Get the connected socket - - int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : socket6FD; - - // Enable non-blocking IO on the socket - - int result = fcntl(socketFD, F_SETFL, O_NONBLOCK); - if (result == -1) - { - NSString *errMsg = @"Error enabling non-blocking IO on socket (fcntl)"; - [self closeWithError:[self otherError:errMsg]]; - - return; - } - - // Setup our read/write sources - - [self setupReadAndWriteSourcesForNewlyConnectedSocket:socketFD]; - - // Dequeue any pending read/write requests - - [self maybeDequeueRead]; - [self maybeDequeueWrite]; -} - -- (void)didNotConnect:(int)aStateIndex error:(NSError *)error -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - - if (aStateIndex != stateIndex) - { - LogInfo(@"Ignoring didNotConnect, already disconnected"); - - // The connect operation has been cancelled. - // That is, socket was disconnected, or connection has already timed out. - return; - } - - [self closeWithError:error]; -} - -- (void)startConnectTimeout:(NSTimeInterval)timeout -{ - if (timeout >= 0.0) - { - connectTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue); - - __weak GCDAsyncSocket *weakSelf = self; - - dispatch_source_set_event_handler(connectTimer, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - [strongSelf doConnectTimeout]; - - #pragma clang diagnostic pop - }}); - - #if !OS_OBJECT_USE_OBJC - dispatch_source_t theConnectTimer = connectTimer; - dispatch_source_set_cancel_handler(connectTimer, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - LogVerbose(@"dispatch_release(connectTimer)"); - dispatch_release(theConnectTimer); - - #pragma clang diagnostic pop - }); - #endif - - dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)); - dispatch_source_set_timer(connectTimer, tt, DISPATCH_TIME_FOREVER, 0); - - dispatch_resume(connectTimer); - } -} - -- (void)endConnectTimeout -{ - LogTrace(); - - if (connectTimer) - { - dispatch_source_cancel(connectTimer); - connectTimer = NULL; - } - - // Increment stateIndex. - // This will prevent us from processing results from any related background asynchronous operations. - // - // Note: This should be called from close method even if connectTimer is NULL. - // This is because one might disconnect a socket prior to a successful connection which had no timeout. - - stateIndex++; - - if (connectInterface4) - { - connectInterface4 = nil; - } - if (connectInterface6) - { - connectInterface6 = nil; - } -} - -- (void)doConnectTimeout -{ - LogTrace(); - - [self endConnectTimeout]; - [self closeWithError:[self connectTimeoutError]]; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Disconnecting -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (void)closeWithError:(NSError *)error -{ - LogTrace(); - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - [self endConnectTimeout]; - - if (currentRead != nil) [self endCurrentRead]; - if (currentWrite != nil) [self endCurrentWrite]; - - [readQueue removeAllObjects]; - [writeQueue removeAllObjects]; - - [preBuffer reset]; - - #if TARGET_OS_IPHONE - { - if (readStream || writeStream) - { - [self removeStreamsFromRunLoop]; - - if (readStream) - { - CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL); - CFReadStreamClose(readStream); - CFRelease(readStream); - readStream = NULL; - } - if (writeStream) - { - CFWriteStreamSetClient(writeStream, kCFStreamEventNone, NULL, NULL); - CFWriteStreamClose(writeStream); - CFRelease(writeStream); - writeStream = NULL; - } - } - } - #endif - - [sslPreBuffer reset]; - sslErrCode = noErr; - - if (sslContext) - { - // Getting a linker error here about the SSLx() functions? - // You need to add the Security Framework to your application. - - SSLClose(sslContext); - - #if TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) - CFRelease(sslContext); - #else - SSLDisposeContext(sslContext); - #endif - - sslContext = NULL; - } - - // For some crazy reason (in my opinion), cancelling a dispatch source doesn't - // invoke the cancel handler if the dispatch source is paused. - // So we have to unpause the source if needed. - // This allows the cancel handler to be run, which in turn releases the source and closes the socket. - - if (!accept4Source && !accept6Source && !readSource && !writeSource) - { - LogVerbose(@"manually closing close"); - - if (socket4FD != SOCKET_NULL) - { - LogVerbose(@"close(socket4FD)"); - close(socket4FD); - socket4FD = SOCKET_NULL; - } - - if (socket6FD != SOCKET_NULL) - { - LogVerbose(@"close(socket6FD)"); - close(socket6FD); - socket6FD = SOCKET_NULL; - } - } - else - { - if (accept4Source) - { - LogVerbose(@"dispatch_source_cancel(accept4Source)"); - dispatch_source_cancel(accept4Source); - - // We never suspend accept4Source - - accept4Source = NULL; - } - - if (accept6Source) - { - LogVerbose(@"dispatch_source_cancel(accept6Source)"); - dispatch_source_cancel(accept6Source); - - // We never suspend accept6Source - - accept6Source = NULL; - } - - if (readSource) - { - LogVerbose(@"dispatch_source_cancel(readSource)"); - dispatch_source_cancel(readSource); - - [self resumeReadSource]; - - readSource = NULL; - } - - if (writeSource) - { - LogVerbose(@"dispatch_source_cancel(writeSource)"); - dispatch_source_cancel(writeSource); - - [self resumeWriteSource]; - - writeSource = NULL; - } - - // The sockets will be closed by the cancel handlers of the corresponding source - - socket4FD = SOCKET_NULL; - socket6FD = SOCKET_NULL; - } - - // If the client has passed the connect/accept method, then the connection has at least begun. - // Notify delegate that it is now ending. - BOOL shouldCallDelegate = (flags & kSocketStarted) ? YES : NO; - BOOL isDeallocating = (flags & kDealloc) ? YES : NO; - - // Clear stored socket info and all flags (config remains as is) - socketFDBytesAvailable = 0; - flags = 0; - - if (shouldCallDelegate) - { - __strong id theDelegate = delegate; - __strong id theSelf = isDeallocating ? nil : self; - - if (delegateQueue && [theDelegate respondsToSelector: @selector(socketDidDisconnect:withError:)]) - { - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socketDidDisconnect:theSelf withError:error]; - }}); - } - } -} - -- (void)disconnect -{ - dispatch_block_t block = ^{ @autoreleasepool { - - if (flags & kSocketStarted) - { - [self closeWithError:nil]; - } - }}; - - // Synchronous disconnection, as documented in the header file - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); -} - -- (void)disconnectAfterReading -{ - dispatch_async(socketQueue, ^{ @autoreleasepool { - - if (flags & kSocketStarted) - { - flags |= (kForbidReadsWrites | kDisconnectAfterReads); - [self maybeClose]; - } - }}); -} - -- (void)disconnectAfterWriting -{ - dispatch_async(socketQueue, ^{ @autoreleasepool { - - if (flags & kSocketStarted) - { - flags |= (kForbidReadsWrites | kDisconnectAfterWrites); - [self maybeClose]; - } - }}); -} - -- (void)disconnectAfterReadingAndWriting -{ - dispatch_async(socketQueue, ^{ @autoreleasepool { - - if (flags & kSocketStarted) - { - flags |= (kForbidReadsWrites | kDisconnectAfterReads | kDisconnectAfterWrites); - [self maybeClose]; - } - }}); -} - -/** - * Closes the socket if possible. - * That is, if all writes have completed, and we're set to disconnect after writing, - * or if all reads have completed, and we're set to disconnect after reading. -**/ -- (void)maybeClose -{ - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - BOOL shouldClose = NO; - - if (flags & kDisconnectAfterReads) - { - if (([readQueue count] == 0) && (currentRead == nil)) - { - if (flags & kDisconnectAfterWrites) - { - if (([writeQueue count] == 0) && (currentWrite == nil)) - { - shouldClose = YES; - } - } - else - { - shouldClose = YES; - } - } - } - else if (flags & kDisconnectAfterWrites) - { - if (([writeQueue count] == 0) && (currentWrite == nil)) - { - shouldClose = YES; - } - } - - if (shouldClose) - { - [self closeWithError:nil]; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Errors -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (NSError *)badConfigError:(NSString *)errMsg -{ - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketBadConfigError userInfo:userInfo]; -} - -- (NSError *)badParamError:(NSString *)errMsg -{ - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketBadParamError userInfo:userInfo]; -} - -+ (NSError *)gaiError:(int)gai_error -{ - NSString *errMsg = [NSString stringWithCString:gai_strerror(gai_error) encoding:NSASCIIStringEncoding]; - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:@"kCFStreamErrorDomainNetDB" code:gai_error userInfo:userInfo]; -} - -- (NSError *)errnoErrorWithReason:(NSString *)reason -{ - NSString *errMsg = [NSString stringWithUTF8String:strerror(errno)]; - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:errMsg, NSLocalizedDescriptionKey, - reason, NSLocalizedFailureReasonErrorKey, nil]; - - return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo]; -} - -- (NSError *)errnoError -{ - NSString *errMsg = [NSString stringWithUTF8String:strerror(errno)]; - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo]; -} - -- (NSError *)sslError:(OSStatus)ssl_error -{ - NSString *msg = @"Error code definition can be found in Apple's SecureTransport.h"; - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:msg forKey:NSLocalizedRecoverySuggestionErrorKey]; - - return [NSError errorWithDomain:@"kCFStreamErrorDomainSSL" code:ssl_error userInfo:userInfo]; -} - -- (NSError *)connectTimeoutError -{ - NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketConnectTimeoutError", - @"GCDAsyncSocket", [NSBundle mainBundle], - @"Attempt to connect to host timed out", nil); - - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketConnectTimeoutError userInfo:userInfo]; -} - -/** - * Returns a standard AsyncSocket maxed out error. -**/ -- (NSError *)readMaxedOutError -{ - NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketReadMaxedOutError", - @"GCDAsyncSocket", [NSBundle mainBundle], - @"Read operation reached set maximum length", nil); - - NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketReadMaxedOutError userInfo:info]; -} - -/** - * Returns a standard AsyncSocket write timeout error. -**/ -- (NSError *)readTimeoutError -{ - NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketReadTimeoutError", - @"GCDAsyncSocket", [NSBundle mainBundle], - @"Read operation timed out", nil); - - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketReadTimeoutError userInfo:userInfo]; -} - -/** - * Returns a standard AsyncSocket write timeout error. -**/ -- (NSError *)writeTimeoutError -{ - NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketWriteTimeoutError", - @"GCDAsyncSocket", [NSBundle mainBundle], - @"Write operation timed out", nil); - - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketWriteTimeoutError userInfo:userInfo]; -} - -- (NSError *)connectionClosedError -{ - NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketClosedError", - @"GCDAsyncSocket", [NSBundle mainBundle], - @"Socket closed by remote peer", nil); - - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketClosedError userInfo:userInfo]; -} - -- (NSError *)otherError:(NSString *)errMsg -{ - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; - - return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketOtherError userInfo:userInfo]; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Diagnostics -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (BOOL)isDisconnected -{ - __block BOOL result = NO; - - dispatch_block_t block = ^{ - result = (flags & kSocketStarted) ? NO : YES; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - return result; -} - -- (BOOL)isConnected -{ - __block BOOL result = NO; - - dispatch_block_t block = ^{ - result = (flags & kConnected) ? YES : NO; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - return result; -} - -- (NSString *)connectedHost -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - if (socket4FD != SOCKET_NULL) - return [self connectedHostFromSocket4:socket4FD]; - if (socket6FD != SOCKET_NULL) - return [self connectedHostFromSocket6:socket6FD]; - - return nil; - } - else - { - __block NSString *result = nil; - - dispatch_sync(socketQueue, ^{ @autoreleasepool { - - if (socket4FD != SOCKET_NULL) - result = [self connectedHostFromSocket4:socket4FD]; - else if (socket6FD != SOCKET_NULL) - result = [self connectedHostFromSocket6:socket6FD]; - }}); - - return result; - } -} - -- (uint16_t)connectedPort -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - if (socket4FD != SOCKET_NULL) - return [self connectedPortFromSocket4:socket4FD]; - if (socket6FD != SOCKET_NULL) - return [self connectedPortFromSocket6:socket6FD]; - - return 0; - } - else - { - __block uint16_t result = 0; - - dispatch_sync(socketQueue, ^{ - // No need for autorelease pool - - if (socket4FD != SOCKET_NULL) - result = [self connectedPortFromSocket4:socket4FD]; - else if (socket6FD != SOCKET_NULL) - result = [self connectedPortFromSocket6:socket6FD]; - }); - - return result; - } -} - -- (NSString *)localHost -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - if (socket4FD != SOCKET_NULL) - return [self localHostFromSocket4:socket4FD]; - if (socket6FD != SOCKET_NULL) - return [self localHostFromSocket6:socket6FD]; - - return nil; - } - else - { - __block NSString *result = nil; - - dispatch_sync(socketQueue, ^{ @autoreleasepool { - - if (socket4FD != SOCKET_NULL) - result = [self localHostFromSocket4:socket4FD]; - else if (socket6FD != SOCKET_NULL) - result = [self localHostFromSocket6:socket6FD]; - }}); - - return result; - } -} - -- (uint16_t)localPort -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - if (socket4FD != SOCKET_NULL) - return [self localPortFromSocket4:socket4FD]; - if (socket6FD != SOCKET_NULL) - return [self localPortFromSocket6:socket6FD]; - - return 0; - } - else - { - __block uint16_t result = 0; - - dispatch_sync(socketQueue, ^{ - // No need for autorelease pool - - if (socket4FD != SOCKET_NULL) - result = [self localPortFromSocket4:socket4FD]; - else if (socket6FD != SOCKET_NULL) - result = [self localPortFromSocket6:socket6FD]; - }); - - return result; - } -} - -- (NSString *)connectedHost4 -{ - if (socket4FD != SOCKET_NULL) - return [self connectedHostFromSocket4:socket4FD]; - - return nil; -} - -- (NSString *)connectedHost6 -{ - if (socket6FD != SOCKET_NULL) - return [self connectedHostFromSocket6:socket6FD]; - - return nil; -} - -- (uint16_t)connectedPort4 -{ - if (socket4FD != SOCKET_NULL) - return [self connectedPortFromSocket4:socket4FD]; - - return 0; -} - -- (uint16_t)connectedPort6 -{ - if (socket6FD != SOCKET_NULL) - return [self connectedPortFromSocket6:socket6FD]; - - return 0; -} - -- (NSString *)localHost4 -{ - if (socket4FD != SOCKET_NULL) - return [self localHostFromSocket4:socket4FD]; - - return nil; -} - -- (NSString *)localHost6 -{ - if (socket6FD != SOCKET_NULL) - return [self localHostFromSocket6:socket6FD]; - - return nil; -} - -- (uint16_t)localPort4 -{ - if (socket4FD != SOCKET_NULL) - return [self localPortFromSocket4:socket4FD]; - - return 0; -} - -- (uint16_t)localPort6 -{ - if (socket6FD != SOCKET_NULL) - return [self localPortFromSocket6:socket6FD]; - - return 0; -} - -- (NSString *)connectedHostFromSocket4:(int)socketFD -{ - struct sockaddr_in sockaddr4; - socklen_t sockaddr4len = sizeof(sockaddr4); - - if (getpeername(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0) - { - return nil; - } - return [[self class] hostFromSockaddr4:&sockaddr4]; -} - -- (NSString *)connectedHostFromSocket6:(int)socketFD -{ - struct sockaddr_in6 sockaddr6; - socklen_t sockaddr6len = sizeof(sockaddr6); - - if (getpeername(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0) - { - return nil; - } - return [[self class] hostFromSockaddr6:&sockaddr6]; -} - -- (uint16_t)connectedPortFromSocket4:(int)socketFD -{ - struct sockaddr_in sockaddr4; - socklen_t sockaddr4len = sizeof(sockaddr4); - - if (getpeername(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0) - { - return 0; - } - return [[self class] portFromSockaddr4:&sockaddr4]; -} - -- (uint16_t)connectedPortFromSocket6:(int)socketFD -{ - struct sockaddr_in6 sockaddr6; - socklen_t sockaddr6len = sizeof(sockaddr6); - - if (getpeername(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0) - { - return 0; - } - return [[self class] portFromSockaddr6:&sockaddr6]; -} - -- (NSString *)localHostFromSocket4:(int)socketFD -{ - struct sockaddr_in sockaddr4; - socklen_t sockaddr4len = sizeof(sockaddr4); - - if (getsockname(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0) - { - return nil; - } - return [[self class] hostFromSockaddr4:&sockaddr4]; -} - -- (NSString *)localHostFromSocket6:(int)socketFD -{ - struct sockaddr_in6 sockaddr6; - socklen_t sockaddr6len = sizeof(sockaddr6); - - if (getsockname(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0) - { - return nil; - } - return [[self class] hostFromSockaddr6:&sockaddr6]; -} - -- (uint16_t)localPortFromSocket4:(int)socketFD -{ - struct sockaddr_in sockaddr4; - socklen_t sockaddr4len = sizeof(sockaddr4); - - if (getsockname(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0) - { - return 0; - } - return [[self class] portFromSockaddr4:&sockaddr4]; -} - -- (uint16_t)localPortFromSocket6:(int)socketFD -{ - struct sockaddr_in6 sockaddr6; - socklen_t sockaddr6len = sizeof(sockaddr6); - - if (getsockname(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0) - { - return 0; - } - return [[self class] portFromSockaddr6:&sockaddr6]; -} - -- (NSData *)connectedAddress -{ - __block NSData *result = nil; - - dispatch_block_t block = ^{ - if (socket4FD != SOCKET_NULL) - { - struct sockaddr_in sockaddr4; - socklen_t sockaddr4len = sizeof(sockaddr4); - - if (getpeername(socket4FD, (struct sockaddr *)&sockaddr4, &sockaddr4len) == 0) - { - result = [[NSData alloc] initWithBytes:&sockaddr4 length:sockaddr4len]; - } - } - - if (socket6FD != SOCKET_NULL) - { - struct sockaddr_in6 sockaddr6; - socklen_t sockaddr6len = sizeof(sockaddr6); - - if (getpeername(socket6FD, (struct sockaddr *)&sockaddr6, &sockaddr6len) == 0) - { - result = [[NSData alloc] initWithBytes:&sockaddr6 length:sockaddr6len]; - } - } - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - return result; -} - -- (NSData *)localAddress -{ - __block NSData *result = nil; - - dispatch_block_t block = ^{ - if (socket4FD != SOCKET_NULL) - { - struct sockaddr_in sockaddr4; - socklen_t sockaddr4len = sizeof(sockaddr4); - - if (getsockname(socket4FD, (struct sockaddr *)&sockaddr4, &sockaddr4len) == 0) - { - result = [[NSData alloc] initWithBytes:&sockaddr4 length:sockaddr4len]; - } - } - - if (socket6FD != SOCKET_NULL) - { - struct sockaddr_in6 sockaddr6; - socklen_t sockaddr6len = sizeof(sockaddr6); - - if (getsockname(socket6FD, (struct sockaddr *)&sockaddr6, &sockaddr6len) == 0) - { - result = [[NSData alloc] initWithBytes:&sockaddr6 length:sockaddr6len]; - } - } - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - return result; -} - -- (BOOL)isIPv4 -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return (socket4FD != SOCKET_NULL); - } - else - { - __block BOOL result = NO; - - dispatch_sync(socketQueue, ^{ - result = (socket4FD != SOCKET_NULL); - }); - - return result; - } -} - -- (BOOL)isIPv6 -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return (socket6FD != SOCKET_NULL); - } - else - { - __block BOOL result = NO; - - dispatch_sync(socketQueue, ^{ - result = (socket6FD != SOCKET_NULL); - }); - - return result; - } -} - -- (BOOL)isSecure -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return (flags & kSocketSecure) ? YES : NO; - } - else - { - __block BOOL result; - - dispatch_sync(socketQueue, ^{ - result = (flags & kSocketSecure) ? YES : NO; - }); - - return result; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Utilities -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Finds the address of an interface description. - * An inteface description may be an interface name (en0, en1, lo0) or corresponding IP (192.168.4.34). - * - * The interface description may optionally contain a port number at the end, separated by a colon. - * If a non-zero port parameter is provided, any port number in the interface description is ignored. - * - * The returned value is a 'struct sockaddr' wrapped in an NSMutableData object. -**/ -- (void)getInterfaceAddress4:(NSMutableData **)interfaceAddr4Ptr - address6:(NSMutableData **)interfaceAddr6Ptr - fromDescription:(NSString *)interfaceDescription - port:(uint16_t)port -{ - NSMutableData *addr4 = nil; - NSMutableData *addr6 = nil; - - NSString *interface = nil; - - NSArray *components = [interfaceDescription componentsSeparatedByString:@":"]; - if ([components count] > 0) - { - NSString *temp = [components objectAtIndex:0]; - if ([temp length] > 0) - { - interface = temp; - } - } - if ([components count] > 1 && port == 0) - { - long portL = strtol([[components objectAtIndex:1] UTF8String], NULL, 10); - - if (portL > 0 && portL <= UINT16_MAX) - { - port = (uint16_t)portL; - } - } - - if (interface == nil) - { - // ANY address - - struct sockaddr_in sockaddr4; - memset(&sockaddr4, 0, sizeof(sockaddr4)); - - sockaddr4.sin_len = sizeof(sockaddr4); - sockaddr4.sin_family = AF_INET; - sockaddr4.sin_port = htons(port); - sockaddr4.sin_addr.s_addr = htonl(INADDR_ANY); - - struct sockaddr_in6 sockaddr6; - memset(&sockaddr6, 0, sizeof(sockaddr6)); - - sockaddr6.sin6_len = sizeof(sockaddr6); - sockaddr6.sin6_family = AF_INET6; - sockaddr6.sin6_port = htons(port); - sockaddr6.sin6_addr = in6addr_any; - - addr4 = [NSMutableData dataWithBytes:&sockaddr4 length:sizeof(sockaddr4)]; - addr6 = [NSMutableData dataWithBytes:&sockaddr6 length:sizeof(sockaddr6)]; - } - else if ([interface isEqualToString:@"localhost"] || [interface isEqualToString:@"loopback"]) - { - // LOOPBACK address - - struct sockaddr_in sockaddr4; - memset(&sockaddr4, 0, sizeof(sockaddr4)); - - sockaddr4.sin_len = sizeof(sockaddr4); - sockaddr4.sin_family = AF_INET; - sockaddr4.sin_port = htons(port); - sockaddr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - struct sockaddr_in6 sockaddr6; - memset(&sockaddr6, 0, sizeof(sockaddr6)); - - sockaddr6.sin6_len = sizeof(sockaddr6); - sockaddr6.sin6_family = AF_INET6; - sockaddr6.sin6_port = htons(port); - sockaddr6.sin6_addr = in6addr_loopback; - - addr4 = [NSMutableData dataWithBytes:&sockaddr4 length:sizeof(sockaddr4)]; - addr6 = [NSMutableData dataWithBytes:&sockaddr6 length:sizeof(sockaddr6)]; - } - else - { - const char *iface = [interface UTF8String]; - - struct ifaddrs *addrs; - const struct ifaddrs *cursor; - - if ((getifaddrs(&addrs) == 0)) - { - cursor = addrs; - while (cursor != NULL) - { - if ((addr4 == nil) && (cursor->ifa_addr->sa_family == AF_INET)) - { - // IPv4 - - struct sockaddr_in nativeAddr4; - memcpy(&nativeAddr4, cursor->ifa_addr, sizeof(nativeAddr4)); - - if (strcmp(cursor->ifa_name, iface) == 0) - { - // Name match - - nativeAddr4.sin_port = htons(port); - - addr4 = [NSMutableData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)]; - } - else - { - char ip[INET_ADDRSTRLEN]; - - const char *conversion = inet_ntop(AF_INET, &nativeAddr4.sin_addr, ip, sizeof(ip)); - - if ((conversion != NULL) && (strcmp(ip, iface) == 0)) - { - // IP match - - nativeAddr4.sin_port = htons(port); - - addr4 = [NSMutableData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)]; - } - } - } - else if ((addr6 == nil) && (cursor->ifa_addr->sa_family == AF_INET6)) - { - // IPv6 - - struct sockaddr_in6 nativeAddr6; - memcpy(&nativeAddr6, cursor->ifa_addr, sizeof(nativeAddr6)); - - if (strcmp(cursor->ifa_name, iface) == 0) - { - // Name match - - nativeAddr6.sin6_port = htons(port); - - addr6 = [NSMutableData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)]; - } - else - { - char ip[INET6_ADDRSTRLEN]; - - const char *conversion = inet_ntop(AF_INET6, &nativeAddr6.sin6_addr, ip, sizeof(ip)); - - if ((conversion != NULL) && (strcmp(ip, iface) == 0)) - { - // IP match - - nativeAddr6.sin6_port = htons(port); - - addr6 = [NSMutableData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)]; - } - } - } - - cursor = cursor->ifa_next; - } - - freeifaddrs(addrs); - } - } - - if (interfaceAddr4Ptr) *interfaceAddr4Ptr = addr4; - if (interfaceAddr6Ptr) *interfaceAddr6Ptr = addr6; -} - -- (void)setupReadAndWriteSourcesForNewlyConnectedSocket:(int)socketFD -{ - readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socketFD, 0, socketQueue); - writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, socketFD, 0, socketQueue); - - // Setup event handlers - - __weak GCDAsyncSocket *weakSelf = self; - - dispatch_source_set_event_handler(readSource, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - LogVerbose(@"readEventBlock"); - - strongSelf->socketFDBytesAvailable = dispatch_source_get_data(strongSelf->readSource); - LogVerbose(@"socketFDBytesAvailable: %lu", strongSelf->socketFDBytesAvailable); - - if (strongSelf->socketFDBytesAvailable > 0) - [strongSelf doReadData]; - else - [strongSelf doReadEOF]; - - #pragma clang diagnostic pop - }}); - - dispatch_source_set_event_handler(writeSource, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - LogVerbose(@"writeEventBlock"); - - strongSelf->flags |= kSocketCanAcceptBytes; - [strongSelf doWriteData]; - - #pragma clang diagnostic pop - }}); - - // Setup cancel handlers - - __block int socketFDRefCount = 2; - - #if !OS_OBJECT_USE_OBJC - dispatch_source_t theReadSource = readSource; - dispatch_source_t theWriteSource = writeSource; - #endif - - dispatch_source_set_cancel_handler(readSource, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - LogVerbose(@"readCancelBlock"); - - #if !OS_OBJECT_USE_OBJC - LogVerbose(@"dispatch_release(readSource)"); - dispatch_release(theReadSource); - #endif - - if (--socketFDRefCount == 0) - { - LogVerbose(@"close(socketFD)"); - close(socketFD); - } - - #pragma clang diagnostic pop - }); - - dispatch_source_set_cancel_handler(writeSource, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - LogVerbose(@"writeCancelBlock"); - - #if !OS_OBJECT_USE_OBJC - LogVerbose(@"dispatch_release(writeSource)"); - dispatch_release(theWriteSource); - #endif - - if (--socketFDRefCount == 0) - { - LogVerbose(@"close(socketFD)"); - close(socketFD); - } - - #pragma clang diagnostic pop - }); - - // We will not be able to read until data arrives. - // But we should be able to write immediately. - - socketFDBytesAvailable = 0; - flags &= ~kReadSourceSuspended; - - LogVerbose(@"dispatch_resume(readSource)"); - dispatch_resume(readSource); - - flags |= kSocketCanAcceptBytes; - flags |= kWriteSourceSuspended; -} - -- (BOOL)usingCFStreamForTLS -{ - #if TARGET_OS_IPHONE - - if ((flags & kSocketSecure) && (flags & kUsingCFStreamForTLS)) - { - // The startTLS method was given the GCDAsyncSocketUseCFStreamForTLS flag. - - return YES; - } - - #endif - - return NO; -} - -- (BOOL)usingSecureTransportForTLS -{ - // Invoking this method is equivalent to ![self usingCFStreamForTLS] (just more readable) - - #if TARGET_OS_IPHONE - - if ((flags & kSocketSecure) && (flags & kUsingCFStreamForTLS)) - { - // The startTLS method was given the GCDAsyncSocketUseCFStreamForTLS flag. - - return NO; - } - - #endif - - return YES; -} - -- (void)suspendReadSource -{ - if (!(flags & kReadSourceSuspended)) - { - LogVerbose(@"dispatch_suspend(readSource)"); - - dispatch_suspend(readSource); - flags |= kReadSourceSuspended; - } -} - -- (void)resumeReadSource -{ - if (flags & kReadSourceSuspended) - { - LogVerbose(@"dispatch_resume(readSource)"); - - dispatch_resume(readSource); - flags &= ~kReadSourceSuspended; - } -} - -- (void)suspendWriteSource -{ - if (!(flags & kWriteSourceSuspended)) - { - LogVerbose(@"dispatch_suspend(writeSource)"); - - dispatch_suspend(writeSource); - flags |= kWriteSourceSuspended; - } -} - -- (void)resumeWriteSource -{ - if (flags & kWriteSourceSuspended) - { - LogVerbose(@"dispatch_resume(writeSource)"); - - dispatch_resume(writeSource); - flags &= ~kWriteSourceSuspended; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Reading -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag -{ - [self readDataWithTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag]; -} - -- (void)readDataWithTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - tag:(long)tag -{ - [self readDataWithTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag]; -} - -- (void)readDataWithTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - maxLength:(NSUInteger)length - tag:(long)tag -{ - if (offset > [buffer length]) { - LogWarn(@"Cannot read: offset > [buffer length]"); - return; - } - - GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer - startOffset:offset - maxLength:length - timeout:timeout - readLength:0 - terminator:nil - tag:tag]; - - dispatch_async(socketQueue, ^{ @autoreleasepool { - - LogTrace(); - - if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites)) - { - [readQueue addObject:packet]; - [self maybeDequeueRead]; - } - }}); - - // Do not rely on the block being run in order to release the packet, - // as the queue might get released without the block completing. -} - -- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag -{ - [self readDataToLength:length withTimeout:timeout buffer:nil bufferOffset:0 tag:tag]; -} - -- (void)readDataToLength:(NSUInteger)length - withTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - tag:(long)tag -{ - if (length == 0) { - LogWarn(@"Cannot read: length == 0"); - return; - } - if (offset > [buffer length]) { - LogWarn(@"Cannot read: offset > [buffer length]"); - return; - } - - GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer - startOffset:offset - maxLength:0 - timeout:timeout - readLength:length - terminator:nil - tag:tag]; - - dispatch_async(socketQueue, ^{ @autoreleasepool { - - LogTrace(); - - if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites)) - { - [readQueue addObject:packet]; - [self maybeDequeueRead]; - } - }}); - - // Do not rely on the block being run in order to release the packet, - // as the queue might get released without the block completing. -} - -- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag -{ - [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag]; -} - -- (void)readDataToData:(NSData *)data - withTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - tag:(long)tag -{ - [self readDataToData:data withTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag]; -} - -- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag -{ - [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:length tag:tag]; -} - -- (void)readDataToData:(NSData *)data - withTimeout:(NSTimeInterval)timeout - buffer:(NSMutableData *)buffer - bufferOffset:(NSUInteger)offset - maxLength:(NSUInteger)maxLength - tag:(long)tag -{ - if ([data length] == 0) { - LogWarn(@"Cannot read: [data length] == 0"); - return; - } - if (offset > [buffer length]) { - LogWarn(@"Cannot read: offset > [buffer length]"); - return; - } - if (maxLength > 0 && maxLength < [data length]) { - LogWarn(@"Cannot read: maxLength > 0 && maxLength < [data length]"); - return; - } - - GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer - startOffset:offset - maxLength:maxLength - timeout:timeout - readLength:0 - terminator:data - tag:tag]; - - dispatch_async(socketQueue, ^{ @autoreleasepool { - - LogTrace(); - - if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites)) - { - [readQueue addObject:packet]; - [self maybeDequeueRead]; - } - }}); - - // Do not rely on the block being run in order to release the packet, - // as the queue might get released without the block completing. -} - -- (float)progressOfReadReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr -{ - __block float result = 0.0F; - - dispatch_block_t block = ^{ - - if (!currentRead || ![currentRead isKindOfClass:[GCDAsyncReadPacket class]]) - { - // We're not reading anything right now. - - if (tagPtr != NULL) *tagPtr = 0; - if (donePtr != NULL) *donePtr = 0; - if (totalPtr != NULL) *totalPtr = 0; - - result = NAN; - } - else - { - // It's only possible to know the progress of our read if we're reading to a certain length. - // If we're reading to data, we of course have no idea when the data will arrive. - // If we're reading to timeout, then we have no idea when the next chunk of data will arrive. - - NSUInteger done = currentRead->bytesDone; - NSUInteger total = currentRead->readLength; - - if (tagPtr != NULL) *tagPtr = currentRead->tag; - if (donePtr != NULL) *donePtr = done; - if (totalPtr != NULL) *totalPtr = total; - - if (total > 0) - result = (float)done / (float)total; - else - result = 1.0F; - } - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - return result; -} - -/** - * This method starts a new read, if needed. - * - * It is called when: - * - a user requests a read - * - after a read request has finished (to handle the next request) - * - immediately after the socket opens to handle any pending requests - * - * This method also handles auto-disconnect post read/write completion. -**/ -- (void)maybeDequeueRead -{ - LogTrace(); - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - // If we're not currently processing a read AND we have an available read stream - if ((currentRead == nil) && (flags & kConnected)) - { - if ([readQueue count] > 0) - { - // Dequeue the next object in the write queue - currentRead = [readQueue objectAtIndex:0]; - [readQueue removeObjectAtIndex:0]; - - - if ([currentRead isKindOfClass:[GCDAsyncSpecialPacket class]]) - { - LogVerbose(@"Dequeued GCDAsyncSpecialPacket"); - - // Attempt to start TLS - flags |= kStartingReadTLS; - - // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set - [self maybeStartTLS]; - } - else - { - LogVerbose(@"Dequeued GCDAsyncReadPacket"); - - // Setup read timer (if needed) - [self setupReadTimerWithTimeout:currentRead->timeout]; - - // Immediately read, if possible - [self doReadData]; - } - } - else if (flags & kDisconnectAfterReads) - { - if (flags & kDisconnectAfterWrites) - { - if (([writeQueue count] == 0) && (currentWrite == nil)) - { - [self closeWithError:nil]; - } - } - else - { - [self closeWithError:nil]; - } - } - else if (flags & kSocketSecure) - { - [self flushSSLBuffers]; - - // Edge case: - // - // We just drained all data from the ssl buffers, - // and all known data from the socket (socketFDBytesAvailable). - // - // If we didn't get any data from this process, - // then we may have reached the end of the TCP stream. - // - // Be sure callbacks are enabled so we're notified about a disconnection. - - if ([preBuffer availableBytes] == 0) - { - if ([self usingCFStreamForTLS]) { - // Callbacks never disabled - } - else { - [self resumeReadSource]; - } - } - } - } -} - -- (void)flushSSLBuffers -{ - LogTrace(); - - NSAssert((flags & kSocketSecure), @"Cannot flush ssl buffers on non-secure socket"); - - if ([preBuffer availableBytes] > 0) - { - // Only flush the ssl buffers if the prebuffer is empty. - // This is to avoid growing the prebuffer inifinitely large. - - return; - } - - #if TARGET_OS_IPHONE - - if ([self usingCFStreamForTLS]) - { - if ((flags & kSecureSocketHasBytesAvailable) && CFReadStreamHasBytesAvailable(readStream)) - { - LogVerbose(@"%@ - Flushing ssl buffers into prebuffer...", THIS_METHOD); - - CFIndex defaultBytesToRead = (1024 * 4); - - [preBuffer ensureCapacityForWrite:defaultBytesToRead]; - - uint8_t *buffer = [preBuffer writeBuffer]; - - CFIndex result = CFReadStreamRead(readStream, buffer, defaultBytesToRead); - LogVerbose(@"%@ - CFReadStreamRead(): result = %i", THIS_METHOD, (int)result); - - if (result > 0) - { - [preBuffer didWrite:result]; - } - - flags &= ~kSecureSocketHasBytesAvailable; - } - - return; - } - - #endif - - __block NSUInteger estimatedBytesAvailable = 0; - - dispatch_block_t updateEstimatedBytesAvailable = ^{ - - // Figure out if there is any data available to be read - // - // socketFDBytesAvailable <- Number of encrypted bytes we haven't read from the bsd socket - // [sslPreBuffer availableBytes] <- Number of encrypted bytes we've buffered from bsd socket - // sslInternalBufSize <- Number of decrypted bytes SecureTransport has buffered - // - // We call the variable "estimated" because we don't know how many decrypted bytes we'll get - // from the encrypted bytes in the sslPreBuffer. - // However, we do know this is an upper bound on the estimation. - - estimatedBytesAvailable = socketFDBytesAvailable + [sslPreBuffer availableBytes]; - - size_t sslInternalBufSize = 0; - SSLGetBufferedReadSize(sslContext, &sslInternalBufSize); - - estimatedBytesAvailable += sslInternalBufSize; - }; - - updateEstimatedBytesAvailable(); - - if (estimatedBytesAvailable > 0) - { - LogVerbose(@"%@ - Flushing ssl buffers into prebuffer...", THIS_METHOD); - - BOOL done = NO; - do - { - LogVerbose(@"%@ - estimatedBytesAvailable = %lu", THIS_METHOD, (unsigned long)estimatedBytesAvailable); - - // Make sure there's enough room in the prebuffer - - [preBuffer ensureCapacityForWrite:estimatedBytesAvailable]; - - // Read data into prebuffer - - uint8_t *buffer = [preBuffer writeBuffer]; - size_t bytesRead = 0; - - OSStatus result = SSLRead(sslContext, buffer, (size_t)estimatedBytesAvailable, &bytesRead); - LogVerbose(@"%@ - read from secure socket = %u", THIS_METHOD, (unsigned)bytesRead); - - if (bytesRead > 0) - { - [preBuffer didWrite:bytesRead]; - } - - LogVerbose(@"%@ - prebuffer.length = %zu", THIS_METHOD, [preBuffer availableBytes]); - - if (result != noErr) - { - done = YES; - } - else - { - updateEstimatedBytesAvailable(); - } - - } while (!done && estimatedBytesAvailable > 0); - } -} - -- (void)doReadData -{ - LogTrace(); - - // This method is called on the socketQueue. - // It might be called directly, or via the readSource when data is available to be read. - - if ((currentRead == nil) || (flags & kReadsPaused)) - { - LogVerbose(@"No currentRead or kReadsPaused"); - - // Unable to read at this time - - if (flags & kSocketSecure) - { - // Here's the situation: - // - // We have an established secure connection. - // There may not be a currentRead, but there might be encrypted data sitting around for us. - // When the user does get around to issuing a read, that encrypted data will need to be decrypted. - // - // So why make the user wait? - // We might as well get a head start on decrypting some data now. - // - // The other reason we do this has to do with detecting a socket disconnection. - // The SSL/TLS protocol has it's own disconnection handshake. - // So when a secure socket is closed, a "goodbye" packet comes across the wire. - // We want to make sure we read the "goodbye" packet so we can properly detect the TCP disconnection. - - [self flushSSLBuffers]; - } - - if ([self usingCFStreamForTLS]) - { - // CFReadStream only fires once when there is available data. - // It won't fire again until we've invoked CFReadStreamRead. - } - else - { - // If the readSource is firing, we need to pause it - // or else it will continue to fire over and over again. - // - // If the readSource is not firing, - // we want it to continue monitoring the socket. - - if (socketFDBytesAvailable > 0) - { - [self suspendReadSource]; - } - } - return; - } - - BOOL hasBytesAvailable = NO; - unsigned long estimatedBytesAvailable = 0; - - if ([self usingCFStreamForTLS]) - { - #if TARGET_OS_IPHONE - - // Requested CFStream, rather than SecureTransport, for TLS (via GCDAsyncSocketUseCFStreamForTLS) - - estimatedBytesAvailable = 0; - if ((flags & kSecureSocketHasBytesAvailable) && CFReadStreamHasBytesAvailable(readStream)) - hasBytesAvailable = YES; - else - hasBytesAvailable = NO; - - #endif - } - else - { - estimatedBytesAvailable = socketFDBytesAvailable; - - if (flags & kSocketSecure) - { - // There are 2 buffers to be aware of here. - // - // We are using SecureTransport, a TLS/SSL security layer which sits atop TCP. - // We issue a read to the SecureTranport API, which in turn issues a read to our SSLReadFunction. - // Our SSLReadFunction then reads from the BSD socket and returns the encrypted data to SecureTransport. - // SecureTransport then decrypts the data, and finally returns the decrypted data back to us. - // - // The first buffer is one we create. - // SecureTransport often requests small amounts of data. - // This has to do with the encypted packets that are coming across the TCP stream. - // But it's non-optimal to do a bunch of small reads from the BSD socket. - // So our SSLReadFunction reads all available data from the socket (optimizing the sys call) - // and may store excess in the sslPreBuffer. - - estimatedBytesAvailable += [sslPreBuffer availableBytes]; - - // The second buffer is within SecureTransport. - // As mentioned earlier, there are encrypted packets coming across the TCP stream. - // SecureTransport needs the entire packet to decrypt it. - // But if the entire packet produces X bytes of decrypted data, - // and we only asked SecureTransport for X/2 bytes of data, - // it must store the extra X/2 bytes of decrypted data for the next read. - // - // The SSLGetBufferedReadSize function will tell us the size of this internal buffer. - // From the documentation: - // - // "This function does not block or cause any low-level read operations to occur." - - size_t sslInternalBufSize = 0; - SSLGetBufferedReadSize(sslContext, &sslInternalBufSize); - - estimatedBytesAvailable += sslInternalBufSize; - } - - hasBytesAvailable = (estimatedBytesAvailable > 0); - } - - if ((hasBytesAvailable == NO) && ([preBuffer availableBytes] == 0)) - { - LogVerbose(@"No data available to read..."); - - // No data available to read. - - if (![self usingCFStreamForTLS]) - { - // Need to wait for readSource to fire and notify us of - // available data in the socket's internal read buffer. - - [self resumeReadSource]; - } - return; - } - - if (flags & kStartingReadTLS) - { - LogVerbose(@"Waiting for SSL/TLS handshake to complete"); - - // The readQueue is waiting for SSL/TLS handshake to complete. - - if (flags & kStartingWriteTLS) - { - if ([self usingSecureTransportForTLS]) - { - // We are in the process of a SSL Handshake. - // We were waiting for incoming data which has just arrived. - - [self ssl_continueSSLHandshake]; - } - } - else - { - // We are still waiting for the writeQueue to drain and start the SSL/TLS process. - // We now know data is available to read. - - if (![self usingCFStreamForTLS]) - { - // Suspend the read source or else it will continue to fire nonstop. - - [self suspendReadSource]; - } - } - - return; - } - - BOOL done = NO; // Completed read operation - NSError *error = nil; // Error occured - - NSUInteger totalBytesReadForCurrentRead = 0; - - // - // STEP 1 - READ FROM PREBUFFER - // - - if ([preBuffer availableBytes] > 0) - { - // There are 3 types of read packets: - // - // 1) Read all available data. - // 2) Read a specific length of data. - // 3) Read up to a particular terminator. - - NSUInteger bytesToCopy; - - if (currentRead->term != nil) - { - // Read type #3 - read up to a terminator - - bytesToCopy = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done]; - } - else - { - // Read type #1 or #2 - - bytesToCopy = [currentRead readLengthForNonTermWithHint:[preBuffer availableBytes]]; - } - - // Make sure we have enough room in the buffer for our read. - - [currentRead ensureCapacityForAdditionalDataOfLength:bytesToCopy]; - - // Copy bytes from prebuffer into packet buffer - - uint8_t *buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset + - currentRead->bytesDone; - - memcpy(buffer, [preBuffer readBuffer], bytesToCopy); - - // Remove the copied bytes from the preBuffer - [preBuffer didRead:bytesToCopy]; - - LogVerbose(@"copied(%lu) preBufferLength(%zu)", (unsigned long)bytesToCopy, [preBuffer availableBytes]); - - // Update totals - - currentRead->bytesDone += bytesToCopy; - totalBytesReadForCurrentRead += bytesToCopy; - - // Check to see if the read operation is done - - if (currentRead->readLength > 0) - { - // Read type #2 - read a specific length of data - - done = (currentRead->bytesDone == currentRead->readLength); - } - else if (currentRead->term != nil) - { - // Read type #3 - read up to a terminator - - // Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method - - if (!done && currentRead->maxLength > 0) - { - // We're not done and there's a set maxLength. - // Have we reached that maxLength yet? - - if (currentRead->bytesDone >= currentRead->maxLength) - { - error = [self readMaxedOutError]; - } - } - } - else - { - // Read type #1 - read all available data - // - // We're done as soon as - // - we've read all available data (in prebuffer and socket) - // - we've read the maxLength of read packet. - - done = ((currentRead->maxLength > 0) && (currentRead->bytesDone == currentRead->maxLength)); - } - - } - - // - // STEP 2 - READ FROM SOCKET - // - - BOOL socketEOF = (flags & kSocketHasReadEOF) ? YES : NO; // Nothing more to read via socket (end of file) - BOOL waiting = !done && !error && !socketEOF && !hasBytesAvailable; // Ran out of data, waiting for more - - if (!done && !error && !socketEOF && hasBytesAvailable) - { - NSAssert(([preBuffer availableBytes] == 0), @"Invalid logic"); - - BOOL readIntoPreBuffer = NO; - uint8_t *buffer = NULL; - size_t bytesRead = 0; - - if (flags & kSocketSecure) - { - if ([self usingCFStreamForTLS]) - { - #if TARGET_OS_IPHONE - - // Using CFStream, rather than SecureTransport, for TLS - - NSUInteger defaultReadLength = (1024 * 32); - - NSUInteger bytesToRead = [currentRead optimalReadLengthWithDefault:defaultReadLength - shouldPreBuffer:&readIntoPreBuffer]; - - // Make sure we have enough room in the buffer for our read. - // - // We are either reading directly into the currentRead->buffer, - // or we're reading into the temporary preBuffer. - - if (readIntoPreBuffer) - { - [preBuffer ensureCapacityForWrite:bytesToRead]; - - buffer = [preBuffer writeBuffer]; - } - else - { - [currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead]; - - buffer = (uint8_t *)[currentRead->buffer mutableBytes] - + currentRead->startOffset - + currentRead->bytesDone; - } - - // Read data into buffer - - CFIndex result = CFReadStreamRead(readStream, buffer, (CFIndex)bytesToRead); - LogVerbose(@"CFReadStreamRead(): result = %i", (int)result); - - if (result < 0) - { - error = (__bridge_transfer NSError *)CFReadStreamCopyError(readStream); - } - else if (result == 0) - { - socketEOF = YES; - } - else - { - waiting = YES; - bytesRead = (size_t)result; - } - - // We only know how many decrypted bytes were read. - // The actual number of bytes read was likely more due to the overhead of the encryption. - // So we reset our flag, and rely on the next callback to alert us of more data. - flags &= ~kSecureSocketHasBytesAvailable; - - #endif - } - else - { - // Using SecureTransport for TLS - // - // We know: - // - how many bytes are available on the socket - // - how many encrypted bytes are sitting in the sslPreBuffer - // - how many decypted bytes are sitting in the sslContext - // - // But we do NOT know: - // - how many encypted bytes are sitting in the sslContext - // - // So we play the regular game of using an upper bound instead. - - NSUInteger defaultReadLength = (1024 * 32); - - if (defaultReadLength < estimatedBytesAvailable) { - defaultReadLength = estimatedBytesAvailable + (1024 * 16); - } - - NSUInteger bytesToRead = [currentRead optimalReadLengthWithDefault:defaultReadLength - shouldPreBuffer:&readIntoPreBuffer]; - - if (bytesToRead > SIZE_MAX) { // NSUInteger may be bigger than size_t - bytesToRead = SIZE_MAX; - } - - // Make sure we have enough room in the buffer for our read. - // - // We are either reading directly into the currentRead->buffer, - // or we're reading into the temporary preBuffer. - - if (readIntoPreBuffer) - { - [preBuffer ensureCapacityForWrite:bytesToRead]; - - buffer = [preBuffer writeBuffer]; - } - else - { - [currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead]; - - buffer = (uint8_t *)[currentRead->buffer mutableBytes] - + currentRead->startOffset - + currentRead->bytesDone; - } - - // The documentation from Apple states: - // - // "a read operation might return errSSLWouldBlock, - // indicating that less data than requested was actually transferred" - // - // However, starting around 10.7, the function will sometimes return noErr, - // even if it didn't read as much data as requested. So we need to watch out for that. - - OSStatus result; - do - { - void *loop_buffer = buffer + bytesRead; - size_t loop_bytesToRead = (size_t)bytesToRead - bytesRead; - size_t loop_bytesRead = 0; - - result = SSLRead(sslContext, loop_buffer, loop_bytesToRead, &loop_bytesRead); - LogVerbose(@"read from secure socket = %u", (unsigned)loop_bytesRead); - - bytesRead += loop_bytesRead; - - } while ((result == noErr) && (bytesRead < bytesToRead)); - - - if (result != noErr) - { - if (result == errSSLWouldBlock) - waiting = YES; - else - { - if (result == errSSLClosedGraceful || result == errSSLClosedAbort) - { - // We've reached the end of the stream. - // Handle this the same way we would an EOF from the socket. - socketEOF = YES; - sslErrCode = result; - } - else - { - error = [self sslError:result]; - } - } - // It's possible that bytesRead > 0, even if the result was errSSLWouldBlock. - // This happens when the SSLRead function is able to read some data, - // but not the entire amount we requested. - - if (bytesRead <= 0) - { - bytesRead = 0; - } - } - - // Do not modify socketFDBytesAvailable. - // It will be updated via the SSLReadFunction(). - } - } - else - { - // Normal socket operation - - NSUInteger bytesToRead; - - // There are 3 types of read packets: - // - // 1) Read all available data. - // 2) Read a specific length of data. - // 3) Read up to a particular terminator. - - if (currentRead->term != nil) - { - // Read type #3 - read up to a terminator - - bytesToRead = [currentRead readLengthForTermWithHint:estimatedBytesAvailable - shouldPreBuffer:&readIntoPreBuffer]; - } - else - { - // Read type #1 or #2 - - bytesToRead = [currentRead readLengthForNonTermWithHint:estimatedBytesAvailable]; - } - - if (bytesToRead > SIZE_MAX) { // NSUInteger may be bigger than size_t (read param 3) - bytesToRead = SIZE_MAX; - } - - // Make sure we have enough room in the buffer for our read. - // - // We are either reading directly into the currentRead->buffer, - // or we're reading into the temporary preBuffer. - - if (readIntoPreBuffer) - { - [preBuffer ensureCapacityForWrite:bytesToRead]; - - buffer = [preBuffer writeBuffer]; - } - else - { - [currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead]; - - buffer = (uint8_t *)[currentRead->buffer mutableBytes] - + currentRead->startOffset - + currentRead->bytesDone; - } - - // Read data into buffer - - int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD; - - ssize_t result = read(socketFD, buffer, (size_t)bytesToRead); - LogVerbose(@"read from socket = %i", (int)result); - - if (result < 0) - { - if (errno == EWOULDBLOCK) - waiting = YES; - else - error = [self errnoErrorWithReason:@"Error in read() function"]; - - socketFDBytesAvailable = 0; - } - else if (result == 0) - { - socketEOF = YES; - socketFDBytesAvailable = 0; - } - else - { - bytesRead = result; - - if (bytesRead < bytesToRead) - { - // The read returned less data than requested. - // This means socketFDBytesAvailable was a bit off due to timing, - // because we read from the socket right when the readSource event was firing. - socketFDBytesAvailable = 0; - } - else - { - if (socketFDBytesAvailable <= bytesRead) - socketFDBytesAvailable = 0; - else - socketFDBytesAvailable -= bytesRead; - } - - if (socketFDBytesAvailable == 0) - { - waiting = YES; - } - } - } - - if (bytesRead > 0) - { - // Check to see if the read operation is done - - if (currentRead->readLength > 0) - { - // Read type #2 - read a specific length of data - // - // Note: We should never be using a prebuffer when we're reading a specific length of data. - - NSAssert(readIntoPreBuffer == NO, @"Invalid logic"); - - currentRead->bytesDone += bytesRead; - totalBytesReadForCurrentRead += bytesRead; - - done = (currentRead->bytesDone == currentRead->readLength); - } - else if (currentRead->term != nil) - { - // Read type #3 - read up to a terminator - - if (readIntoPreBuffer) - { - // We just read a big chunk of data into the preBuffer - - [preBuffer didWrite:bytesRead]; - LogVerbose(@"read data into preBuffer - preBuffer.length = %zu", [preBuffer availableBytes]); - - // Search for the terminating sequence - - NSUInteger bytesToCopy = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done]; - LogVerbose(@"copying %lu bytes from preBuffer", (unsigned long)bytesToCopy); - - // Ensure there's room on the read packet's buffer - - [currentRead ensureCapacityForAdditionalDataOfLength:bytesToCopy]; - - // Copy bytes from prebuffer into read buffer - - uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset - + currentRead->bytesDone; - - memcpy(readBuf, [preBuffer readBuffer], bytesToCopy); - - // Remove the copied bytes from the prebuffer - [preBuffer didRead:bytesToCopy]; - LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]); - - // Update totals - currentRead->bytesDone += bytesToCopy; - totalBytesReadForCurrentRead += bytesToCopy; - - // Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method above - } - else - { - // We just read a big chunk of data directly into the packet's buffer. - // We need to move any overflow into the prebuffer. - - NSInteger overflow = [currentRead searchForTermAfterPreBuffering:bytesRead]; - - if (overflow == 0) - { - // Perfect match! - // Every byte we read stays in the read buffer, - // and the last byte we read was the last byte of the term. - - currentRead->bytesDone += bytesRead; - totalBytesReadForCurrentRead += bytesRead; - done = YES; - } - else if (overflow > 0) - { - // The term was found within the data that we read, - // and there are extra bytes that extend past the end of the term. - // We need to move these excess bytes out of the read packet and into the prebuffer. - - NSInteger underflow = bytesRead - overflow; - - // Copy excess data into preBuffer - - LogVerbose(@"copying %ld overflow bytes into preBuffer", (long)overflow); - [preBuffer ensureCapacityForWrite:overflow]; - - uint8_t *overflowBuffer = buffer + underflow; - memcpy([preBuffer writeBuffer], overflowBuffer, overflow); - - [preBuffer didWrite:overflow]; - LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]); - - // Note: The completeCurrentRead method will trim the buffer for us. - - currentRead->bytesDone += underflow; - totalBytesReadForCurrentRead += underflow; - done = YES; - } - else - { - // The term was not found within the data that we read. - - currentRead->bytesDone += bytesRead; - totalBytesReadForCurrentRead += bytesRead; - done = NO; - } - } - - if (!done && currentRead->maxLength > 0) - { - // We're not done and there's a set maxLength. - // Have we reached that maxLength yet? - - if (currentRead->bytesDone >= currentRead->maxLength) - { - error = [self readMaxedOutError]; - } - } - } - else - { - // Read type #1 - read all available data - - if (readIntoPreBuffer) - { - // We just read a chunk of data into the preBuffer - - [preBuffer didWrite:bytesRead]; - - // Now copy the data into the read packet. - // - // Recall that we didn't read directly into the packet's buffer to avoid - // over-allocating memory since we had no clue how much data was available to be read. - // - // Ensure there's room on the read packet's buffer - - [currentRead ensureCapacityForAdditionalDataOfLength:bytesRead]; - - // Copy bytes from prebuffer into read buffer - - uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset - + currentRead->bytesDone; - - memcpy(readBuf, [preBuffer readBuffer], bytesRead); - - // Remove the copied bytes from the prebuffer - [preBuffer didRead:bytesRead]; - - // Update totals - currentRead->bytesDone += bytesRead; - totalBytesReadForCurrentRead += bytesRead; - } - else - { - currentRead->bytesDone += bytesRead; - totalBytesReadForCurrentRead += bytesRead; - } - - done = YES; - } - - } // if (bytesRead > 0) - - } // if (!done && !error && !socketEOF && hasBytesAvailable) - - - if (!done && currentRead->readLength == 0 && currentRead->term == nil) - { - // Read type #1 - read all available data - // - // We might arrive here if we read data from the prebuffer but not from the socket. - - done = (totalBytesReadForCurrentRead > 0); - } - - // Check to see if we're done, or if we've made progress - - if (done) - { - [self completeCurrentRead]; - - if (!error && (!socketEOF || [preBuffer availableBytes] > 0)) - { - [self maybeDequeueRead]; - } - } - else if (totalBytesReadForCurrentRead > 0) - { - // We're not done read type #2 or #3 yet, but we have read in some bytes - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:didReadPartialDataOfLength:tag:)]) - { - long theReadTag = currentRead->tag; - - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socket:self didReadPartialDataOfLength:totalBytesReadForCurrentRead tag:theReadTag]; - }}); - } - } - - // Check for errors - - if (error) - { - [self closeWithError:error]; - } - else if (socketEOF) - { - [self doReadEOF]; - } - else if (waiting) - { - if (![self usingCFStreamForTLS]) - { - // Monitor the socket for readability (if we're not already doing so) - [self resumeReadSource]; - } - } - - // Do not add any code here without first adding return statements in the error cases above. -} - -- (void)doReadEOF -{ - LogTrace(); - - // This method may be called more than once. - // If the EOF is read while there is still data in the preBuffer, - // then this method may be called continually after invocations of doReadData to see if it's time to disconnect. - - flags |= kSocketHasReadEOF; - - if (flags & kSocketSecure) - { - // If the SSL layer has any buffered data, flush it into the preBuffer now. - - [self flushSSLBuffers]; - } - - BOOL shouldDisconnect = NO; - NSError *error = nil; - - if ((flags & kStartingReadTLS) || (flags & kStartingWriteTLS)) - { - // We received an EOF during or prior to startTLS. - // The SSL/TLS handshake is now impossible, so this is an unrecoverable situation. - - shouldDisconnect = YES; - - if ([self usingSecureTransportForTLS]) - { - error = [self sslError:errSSLClosedAbort]; - } - } - else if (flags & kReadStreamClosed) - { - // The preBuffer has already been drained. - // The config allows half-duplex connections. - // We've previously checked the socket, and it appeared writeable. - // So we marked the read stream as closed and notified the delegate. - // - // As per the half-duplex contract, the socket will be closed when a write fails, - // or when the socket is manually closed. - - shouldDisconnect = NO; - } - else if ([preBuffer availableBytes] > 0) - { - LogVerbose(@"Socket reached EOF, but there is still data available in prebuffer"); - - // Although we won't be able to read any more data from the socket, - // there is existing data that has been prebuffered that we can read. - - shouldDisconnect = NO; - } - else if (config & kAllowHalfDuplexConnection) - { - // We just received an EOF (end of file) from the socket's read stream. - // This means the remote end of the socket (the peer we're connected to) - // has explicitly stated that it will not be sending us any more data. - // - // Query the socket to see if it is still writeable. (Perhaps the peer will continue reading data from us) - - int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD; - - struct pollfd pfd[1]; - pfd[0].fd = socketFD; - pfd[0].events = POLLOUT; - pfd[0].revents = 0; - - poll(pfd, 1, 0); - - if (pfd[0].revents & POLLOUT) - { - // Socket appears to still be writeable - - shouldDisconnect = NO; - flags |= kReadStreamClosed; - - // Notify the delegate that we're going half-duplex - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socketDidCloseReadStream:)]) - { - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socketDidCloseReadStream:self]; - }}); - } - } - else - { - shouldDisconnect = YES; - } - } - else - { - shouldDisconnect = YES; - } - - - if (shouldDisconnect) - { - if (error == nil) - { - if ([self usingSecureTransportForTLS]) - { - if (sslErrCode != noErr && sslErrCode != errSSLClosedGraceful) - { - error = [self sslError:sslErrCode]; - } - else - { - error = [self connectionClosedError]; - } - } - else - { - error = [self connectionClosedError]; - } - } - [self closeWithError:error]; - } - else - { - if (![self usingCFStreamForTLS]) - { - // Suspend the read source (if needed) - - [self suspendReadSource]; - } - } -} - -- (void)completeCurrentRead -{ - LogTrace(); - - NSAssert(currentRead, @"Trying to complete current read when there is no current read."); - - - NSData *result = nil; - - if (currentRead->bufferOwner) - { - // We created the buffer on behalf of the user. - // Trim our buffer to be the proper size. - [currentRead->buffer setLength:currentRead->bytesDone]; - - result = currentRead->buffer; - } - else - { - // We did NOT create the buffer. - // The buffer is owned by the caller. - // Only trim the buffer if we had to increase its size. - - if ([currentRead->buffer length] > currentRead->originalBufferLength) - { - NSUInteger readSize = currentRead->startOffset + currentRead->bytesDone; - NSUInteger origSize = currentRead->originalBufferLength; - - NSUInteger buffSize = MAX(readSize, origSize); - - [currentRead->buffer setLength:buffSize]; - } - - uint8_t *buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset; - - result = [NSData dataWithBytesNoCopy:buffer length:currentRead->bytesDone freeWhenDone:NO]; - } - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:didReadData:withTag:)]) - { - GCDAsyncReadPacket *theRead = currentRead; // Ensure currentRead retained since result may not own buffer - - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socket:self didReadData:result withTag:theRead->tag]; - }}); - } - - [self endCurrentRead]; -} - -- (void)endCurrentRead -{ - if (readTimer) - { - dispatch_source_cancel(readTimer); - readTimer = NULL; - } - - currentRead = nil; -} - -- (void)setupReadTimerWithTimeout:(NSTimeInterval)timeout -{ - if (timeout >= 0.0) - { - readTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue); - - __weak GCDAsyncSocket *weakSelf = self; - - dispatch_source_set_event_handler(readTimer, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - [strongSelf doReadTimeout]; - - #pragma clang diagnostic pop - }}); - - #if !OS_OBJECT_USE_OBJC - dispatch_source_t theReadTimer = readTimer; - dispatch_source_set_cancel_handler(readTimer, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - LogVerbose(@"dispatch_release(readTimer)"); - dispatch_release(theReadTimer); - - #pragma clang diagnostic pop - }); - #endif - - dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)); - - dispatch_source_set_timer(readTimer, tt, DISPATCH_TIME_FOREVER, 0); - dispatch_resume(readTimer); - } -} - -- (void)doReadTimeout -{ - // This is a little bit tricky. - // Ideally we'd like to synchronously query the delegate about a timeout extension. - // But if we do so synchronously we risk a possible deadlock. - // So instead we have to do so asynchronously, and callback to ourselves from within the delegate block. - - flags |= kReadsPaused; - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:shouldTimeoutReadWithTag:elapsed:bytesDone:)]) - { - GCDAsyncReadPacket *theRead = currentRead; - - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - NSTimeInterval timeoutExtension = 0.0; - - timeoutExtension = [theDelegate socket:self shouldTimeoutReadWithTag:theRead->tag - elapsed:theRead->timeout - bytesDone:theRead->bytesDone]; - - dispatch_async(socketQueue, ^{ @autoreleasepool { - - [self doReadTimeoutWithExtension:timeoutExtension]; - }}); - }}); - } - else - { - [self doReadTimeoutWithExtension:0.0]; - } -} - -- (void)doReadTimeoutWithExtension:(NSTimeInterval)timeoutExtension -{ - if (currentRead) - { - if (timeoutExtension > 0.0) - { - currentRead->timeout += timeoutExtension; - - // Reschedule the timer - dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeoutExtension * NSEC_PER_SEC)); - dispatch_source_set_timer(readTimer, tt, DISPATCH_TIME_FOREVER, 0); - - // Unpause reads, and continue - flags &= ~kReadsPaused; - [self doReadData]; - } - else - { - LogVerbose(@"ReadTimeout"); - - [self closeWithError:[self readTimeoutError]]; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Writing -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag -{ - if ([data length] == 0) return; - - GCDAsyncWritePacket *packet = [[GCDAsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag]; - - dispatch_async(socketQueue, ^{ @autoreleasepool { - - LogTrace(); - - if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites)) - { - [writeQueue addObject:packet]; - [self maybeDequeueWrite]; - } - }}); - - // Do not rely on the block being run in order to release the packet, - // as the queue might get released without the block completing. -} - -- (float)progressOfWriteReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr -{ - __block float result = 0.0F; - - dispatch_block_t block = ^{ - - if (!currentWrite || ![currentWrite isKindOfClass:[GCDAsyncWritePacket class]]) - { - // We're not writing anything right now. - - if (tagPtr != NULL) *tagPtr = 0; - if (donePtr != NULL) *donePtr = 0; - if (totalPtr != NULL) *totalPtr = 0; - - result = NAN; - } - else - { - NSUInteger done = currentWrite->bytesDone; - NSUInteger total = [currentWrite->buffer length]; - - if (tagPtr != NULL) *tagPtr = currentWrite->tag; - if (donePtr != NULL) *donePtr = done; - if (totalPtr != NULL) *totalPtr = total; - - result = (float)done / (float)total; - } - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); - - return result; -} - -/** - * Conditionally starts a new write. - * - * It is called when: - * - a user requests a write - * - after a write request has finished (to handle the next request) - * - immediately after the socket opens to handle any pending requests - * - * This method also handles auto-disconnect post read/write completion. -**/ -- (void)maybeDequeueWrite -{ - LogTrace(); - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - - // If we're not currently processing a write AND we have an available write stream - if ((currentWrite == nil) && (flags & kConnected)) - { - if ([writeQueue count] > 0) - { - // Dequeue the next object in the write queue - currentWrite = [writeQueue objectAtIndex:0]; - [writeQueue removeObjectAtIndex:0]; - - - if ([currentWrite isKindOfClass:[GCDAsyncSpecialPacket class]]) - { - LogVerbose(@"Dequeued GCDAsyncSpecialPacket"); - - // Attempt to start TLS - flags |= kStartingWriteTLS; - - // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set - [self maybeStartTLS]; - } - else - { - LogVerbose(@"Dequeued GCDAsyncWritePacket"); - - // Setup write timer (if needed) - [self setupWriteTimerWithTimeout:currentWrite->timeout]; - - // Immediately write, if possible - [self doWriteData]; - } - } - else if (flags & kDisconnectAfterWrites) - { - if (flags & kDisconnectAfterReads) - { - if (([readQueue count] == 0) && (currentRead == nil)) - { - [self closeWithError:nil]; - } - } - else - { - [self closeWithError:nil]; - } - } - } -} - -- (void)doWriteData -{ - LogTrace(); - - // This method is called by the writeSource via the socketQueue - - if ((currentWrite == nil) || (flags & kWritesPaused)) - { - LogVerbose(@"No currentWrite or kWritesPaused"); - - // Unable to write at this time - - if ([self usingCFStreamForTLS]) - { - // CFWriteStream only fires once when there is available data. - // It won't fire again until we've invoked CFWriteStreamWrite. - } - else - { - // If the writeSource is firing, we need to pause it - // or else it will continue to fire over and over again. - - if (flags & kSocketCanAcceptBytes) - { - [self suspendWriteSource]; - } - } - return; - } - - if (!(flags & kSocketCanAcceptBytes)) - { - LogVerbose(@"No space available to write..."); - - // No space available to write. - - if (![self usingCFStreamForTLS]) - { - // Need to wait for writeSource to fire and notify us of - // available space in the socket's internal write buffer. - - [self resumeWriteSource]; - } - return; - } - - if (flags & kStartingWriteTLS) - { - LogVerbose(@"Waiting for SSL/TLS handshake to complete"); - - // The writeQueue is waiting for SSL/TLS handshake to complete. - - if (flags & kStartingReadTLS) - { - if ([self usingSecureTransportForTLS]) - { - // We are in the process of a SSL Handshake. - // We were waiting for available space in the socket's internal OS buffer to continue writing. - - [self ssl_continueSSLHandshake]; - } - } - else - { - // We are still waiting for the readQueue to drain and start the SSL/TLS process. - // We now know we can write to the socket. - - if (![self usingCFStreamForTLS]) - { - // Suspend the write source or else it will continue to fire nonstop. - - [self suspendWriteSource]; - } - } - - return; - } - - // Note: This method is not called if currentWrite is a GCDAsyncSpecialPacket (startTLS packet) - - BOOL waiting = NO; - NSError *error = nil; - size_t bytesWritten = 0; - - if (flags & kSocketSecure) - { - if ([self usingCFStreamForTLS]) - { - #if TARGET_OS_IPHONE - - // - // Writing data using CFStream (over internal TLS) - // - - const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] + currentWrite->bytesDone; - - NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone; - - if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3) - { - bytesToWrite = SIZE_MAX; - } - - CFIndex result = CFWriteStreamWrite(writeStream, buffer, (CFIndex)bytesToWrite); - LogVerbose(@"CFWriteStreamWrite(%lu) = %li", (unsigned long)bytesToWrite, result); - - if (result < 0) - { - error = (__bridge_transfer NSError *)CFWriteStreamCopyError(writeStream); - } - else - { - bytesWritten = (size_t)result; - - // We always set waiting to true in this scenario. - // CFStream may have altered our underlying socket to non-blocking. - // Thus if we attempt to write without a callback, we may end up blocking our queue. - waiting = YES; - } - - #endif - } - else - { - // We're going to use the SSLWrite function. - // - // OSStatus SSLWrite(SSLContextRef context, const void *data, size_t dataLength, size_t *processed) - // - // Parameters: - // context - An SSL session context reference. - // data - A pointer to the buffer of data to write. - // dataLength - The amount, in bytes, of data to write. - // processed - On return, the length, in bytes, of the data actually written. - // - // It sounds pretty straight-forward, - // but there are a few caveats you should be aware of. - // - // The SSLWrite method operates in a non-obvious (and rather annoying) manner. - // According to the documentation: - // - // Because you may configure the underlying connection to operate in a non-blocking manner, - // a write operation might return errSSLWouldBlock, indicating that less data than requested - // was actually transferred. In this case, you should repeat the call to SSLWrite until some - // other result is returned. - // - // This sounds perfect, but when our SSLWriteFunction returns errSSLWouldBlock, - // then the SSLWrite method returns (with the proper errSSLWouldBlock return value), - // but it sets processed to dataLength !! - // - // In other words, if the SSLWrite function doesn't completely write all the data we tell it to, - // then it doesn't tell us how many bytes were actually written. So, for example, if we tell it to - // write 256 bytes then it might actually write 128 bytes, but then report 0 bytes written. - // - // You might be wondering: - // If the SSLWrite function doesn't tell us how many bytes were written, - // then how in the world are we supposed to update our parameters (buffer & bytesToWrite) - // for the next time we invoke SSLWrite? - // - // The answer is that SSLWrite cached all the data we told it to write, - // and it will push out that data next time we call SSLWrite. - // If we call SSLWrite with new data, it will push out the cached data first, and then the new data. - // If we call SSLWrite with empty data, then it will simply push out the cached data. - // - // For this purpose we're going to break large writes into a series of smaller writes. - // This allows us to report progress back to the delegate. - - OSStatus result; - - BOOL hasCachedDataToWrite = (sslWriteCachedLength > 0); - BOOL hasNewDataToWrite = YES; - - if (hasCachedDataToWrite) - { - size_t processed = 0; - - result = SSLWrite(sslContext, NULL, 0, &processed); - - if (result == noErr) - { - bytesWritten = sslWriteCachedLength; - sslWriteCachedLength = 0; - - if ([currentWrite->buffer length] == (currentWrite->bytesDone + bytesWritten)) - { - // We've written all data for the current write. - hasNewDataToWrite = NO; - } - } - else - { - if (result == errSSLWouldBlock) - { - waiting = YES; - } - else - { - error = [self sslError:result]; - } - - // Can't write any new data since we were unable to write the cached data. - hasNewDataToWrite = NO; - } - } - - if (hasNewDataToWrite) - { - const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] - + currentWrite->bytesDone - + bytesWritten; - - NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone - bytesWritten; - - if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3) - { - bytesToWrite = SIZE_MAX; - } - - size_t bytesRemaining = bytesToWrite; - - BOOL keepLooping = YES; - while (keepLooping) - { - const size_t sslMaxBytesToWrite = 32768; - size_t sslBytesToWrite = MIN(bytesRemaining, sslMaxBytesToWrite); - size_t sslBytesWritten = 0; - - result = SSLWrite(sslContext, buffer, sslBytesToWrite, &sslBytesWritten); - - if (result == noErr) - { - buffer += sslBytesWritten; - bytesWritten += sslBytesWritten; - bytesRemaining -= sslBytesWritten; - - keepLooping = (bytesRemaining > 0); - } - else - { - if (result == errSSLWouldBlock) - { - waiting = YES; - sslWriteCachedLength = sslBytesToWrite; - } - else - { - error = [self sslError:result]; - } - - keepLooping = NO; - } - - } // while (keepLooping) - - } // if (hasNewDataToWrite) - } - } - else - { - // - // Writing data directly over raw socket - // - - int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD; - - const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] + currentWrite->bytesDone; - - NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone; - - if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3) - { - bytesToWrite = SIZE_MAX; - } - - ssize_t result = write(socketFD, buffer, (size_t)bytesToWrite); - LogVerbose(@"wrote to socket = %zd", result); - - // Check results - if (result < 0) - { - if (errno == EWOULDBLOCK) - { - waiting = YES; - } - else - { - error = [self errnoErrorWithReason:@"Error in write() function"]; - } - } - else - { - bytesWritten = result; - } - } - - // We're done with our writing. - // If we explictly ran into a situation where the socket told us there was no room in the buffer, - // then we immediately resume listening for notifications. - // - // We must do this before we dequeue another write, - // as that may in turn invoke this method again. - // - // Note that if CFStream is involved, it may have maliciously put our socket in blocking mode. - - if (waiting) - { - flags &= ~kSocketCanAcceptBytes; - - if (![self usingCFStreamForTLS]) - { - [self resumeWriteSource]; - } - } - - // Check our results - - BOOL done = NO; - - if (bytesWritten > 0) - { - // Update total amount read for the current write - currentWrite->bytesDone += bytesWritten; - LogVerbose(@"currentWrite->bytesDone = %lu", (unsigned long)currentWrite->bytesDone); - - // Is packet done? - done = (currentWrite->bytesDone == [currentWrite->buffer length]); - } - - if (done) - { - [self completeCurrentWrite]; - - if (!error) - { - dispatch_async(socketQueue, ^{ @autoreleasepool{ - - [self maybeDequeueWrite]; - }}); - } - } - else - { - // We were unable to finish writing the data, - // so we're waiting for another callback to notify us of available space in the lower-level output buffer. - - if (!waiting && !error) - { - // This would be the case if our write was able to accept some data, but not all of it. - - flags &= ~kSocketCanAcceptBytes; - - if (![self usingCFStreamForTLS]) - { - [self resumeWriteSource]; - } - } - - if (bytesWritten > 0) - { - // We're not done with the entire write, but we have written some bytes - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:didWritePartialDataOfLength:tag:)]) - { - long theWriteTag = currentWrite->tag; - - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socket:self didWritePartialDataOfLength:bytesWritten tag:theWriteTag]; - }}); - } - } - } - - // Check for errors - - if (error) - { - [self closeWithError:[self errnoErrorWithReason:@"Error in write() function"]]; - } - - // Do not add any code here without first adding a return statement in the error case above. -} - -- (void)completeCurrentWrite -{ - LogTrace(); - - NSAssert(currentWrite, @"Trying to complete current write when there is no current write."); - - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:didWriteDataWithTag:)]) - { - long theWriteTag = currentWrite->tag; - - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socket:self didWriteDataWithTag:theWriteTag]; - }}); - } - - [self endCurrentWrite]; -} - -- (void)endCurrentWrite -{ - if (writeTimer) - { - dispatch_source_cancel(writeTimer); - writeTimer = NULL; - } - - currentWrite = nil; -} - -- (void)setupWriteTimerWithTimeout:(NSTimeInterval)timeout -{ - if (timeout >= 0.0) - { - writeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue); - - __weak GCDAsyncSocket *weakSelf = self; - - dispatch_source_set_event_handler(writeTimer, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf == nil) return_from_block; - - [strongSelf doWriteTimeout]; - - #pragma clang diagnostic pop - }}); - - #if !OS_OBJECT_USE_OBJC - dispatch_source_t theWriteTimer = writeTimer; - dispatch_source_set_cancel_handler(writeTimer, ^{ - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - LogVerbose(@"dispatch_release(writeTimer)"); - dispatch_release(theWriteTimer); - - #pragma clang diagnostic pop - }); - #endif - - dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)); - - dispatch_source_set_timer(writeTimer, tt, DISPATCH_TIME_FOREVER, 0); - dispatch_resume(writeTimer); - } -} - -- (void)doWriteTimeout -{ - // This is a little bit tricky. - // Ideally we'd like to synchronously query the delegate about a timeout extension. - // But if we do so synchronously we risk a possible deadlock. - // So instead we have to do so asynchronously, and callback to ourselves from within the delegate block. - - flags |= kWritesPaused; - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:shouldTimeoutWriteWithTag:elapsed:bytesDone:)]) - { - GCDAsyncWritePacket *theWrite = currentWrite; - - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - NSTimeInterval timeoutExtension = 0.0; - - timeoutExtension = [theDelegate socket:self shouldTimeoutWriteWithTag:theWrite->tag - elapsed:theWrite->timeout - bytesDone:theWrite->bytesDone]; - - dispatch_async(socketQueue, ^{ @autoreleasepool { - - [self doWriteTimeoutWithExtension:timeoutExtension]; - }}); - }}); - } - else - { - [self doWriteTimeoutWithExtension:0.0]; - } -} - -- (void)doWriteTimeoutWithExtension:(NSTimeInterval)timeoutExtension -{ - if (currentWrite) - { - if (timeoutExtension > 0.0) - { - currentWrite->timeout += timeoutExtension; - - // Reschedule the timer - dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeoutExtension * NSEC_PER_SEC)); - dispatch_source_set_timer(writeTimer, tt, DISPATCH_TIME_FOREVER, 0); - - // Unpause writes, and continue - flags &= ~kWritesPaused; - [self doWriteData]; - } - else - { - LogVerbose(@"WriteTimeout"); - - [self closeWithError:[self writeTimeoutError]]; - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Security -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (void)startTLS:(NSDictionary *)tlsSettings -{ - LogTrace(); - - if (tlsSettings == nil) - { - // Passing nil/NULL to CFReadStreamSetProperty will appear to work the same as passing an empty dictionary, - // but causes problems if we later try to fetch the remote host's certificate. - // - // To be exact, it causes the following to return NULL instead of the normal result: - // CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLPeerCertificates) - // - // So we use an empty dictionary instead, which works perfectly. - - tlsSettings = [NSDictionary dictionary]; - } - - GCDAsyncSpecialPacket *packet = [[GCDAsyncSpecialPacket alloc] initWithTLSSettings:tlsSettings]; - - dispatch_async(socketQueue, ^{ @autoreleasepool { - - if ((flags & kSocketStarted) && !(flags & kQueuedTLS) && !(flags & kForbidReadsWrites)) - { - [readQueue addObject:packet]; - [writeQueue addObject:packet]; - - flags |= kQueuedTLS; - - [self maybeDequeueRead]; - [self maybeDequeueWrite]; - } - }}); - -} - -- (void)maybeStartTLS -{ - // We can't start TLS until: - // - All queued reads prior to the user calling startTLS are complete - // - All queued writes prior to the user calling startTLS are complete - // - // We'll know these conditions are met when both kStartingReadTLS and kStartingWriteTLS are set - - if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS)) - { - BOOL useSecureTransport = YES; - - #if TARGET_OS_IPHONE - { - GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead; - NSDictionary *tlsSettings = tlsPacket->tlsSettings; - - NSNumber *value = [tlsSettings objectForKey:GCDAsyncSocketUseCFStreamForTLS]; - if (value && [value boolValue] == YES) - useSecureTransport = NO; - } - #endif - - if (useSecureTransport) - { - [self ssl_startTLS]; - } - else - { - #if TARGET_OS_IPHONE - [self cf_startTLS]; - #endif - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Security via SecureTransport -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength -{ - LogVerbose(@"sslReadWithBuffer:%p length:%lu", buffer, (unsigned long)*bufferLength); - - if ((socketFDBytesAvailable == 0) && ([sslPreBuffer availableBytes] == 0)) - { - LogVerbose(@"%@ - No data available to read...", THIS_METHOD); - - // No data available to read. - // - // Need to wait for readSource to fire and notify us of - // available data in the socket's internal read buffer. - - [self resumeReadSource]; - - *bufferLength = 0; - return errSSLWouldBlock; - } - - size_t totalBytesRead = 0; - size_t totalBytesLeftToBeRead = *bufferLength; - - BOOL done = NO; - BOOL socketError = NO; - - // - // STEP 1 : READ FROM SSL PRE BUFFER - // - - size_t sslPreBufferLength = [sslPreBuffer availableBytes]; - - if (sslPreBufferLength > 0) - { - LogVerbose(@"%@: Reading from SSL pre buffer...", THIS_METHOD); - - size_t bytesToCopy; - if (sslPreBufferLength > totalBytesLeftToBeRead) - bytesToCopy = totalBytesLeftToBeRead; - else - bytesToCopy = sslPreBufferLength; - - LogVerbose(@"%@: Copying %zu bytes from sslPreBuffer", THIS_METHOD, bytesToCopy); - - memcpy(buffer, [sslPreBuffer readBuffer], bytesToCopy); - [sslPreBuffer didRead:bytesToCopy]; - - LogVerbose(@"%@: sslPreBuffer.length = %zu", THIS_METHOD, [sslPreBuffer availableBytes]); - - totalBytesRead += bytesToCopy; - totalBytesLeftToBeRead -= bytesToCopy; - - done = (totalBytesLeftToBeRead == 0); - - if (done) LogVerbose(@"%@: Complete", THIS_METHOD); - } - - // - // STEP 2 : READ FROM SOCKET - // - - if (!done && (socketFDBytesAvailable > 0)) - { - LogVerbose(@"%@: Reading from socket...", THIS_METHOD); - - int socketFD = (socket6FD == SOCKET_NULL) ? socket4FD : socket6FD; - - BOOL readIntoPreBuffer; - size_t bytesToRead; - uint8_t *buf; - - if (socketFDBytesAvailable > totalBytesLeftToBeRead) - { - // Read all available data from socket into sslPreBuffer. - // Then copy requested amount into dataBuffer. - - LogVerbose(@"%@: Reading into sslPreBuffer...", THIS_METHOD); - - [sslPreBuffer ensureCapacityForWrite:socketFDBytesAvailable]; - - readIntoPreBuffer = YES; - bytesToRead = (size_t)socketFDBytesAvailable; - buf = [sslPreBuffer writeBuffer]; - } - else - { - // Read available data from socket directly into dataBuffer. - - LogVerbose(@"%@: Reading directly into dataBuffer...", THIS_METHOD); - - readIntoPreBuffer = NO; - bytesToRead = totalBytesLeftToBeRead; - buf = (uint8_t *)buffer + totalBytesRead; - } - - ssize_t result = read(socketFD, buf, bytesToRead); - LogVerbose(@"%@: read from socket = %zd", THIS_METHOD, result); - - if (result < 0) - { - LogVerbose(@"%@: read errno = %i", THIS_METHOD, errno); - - if (errno != EWOULDBLOCK) - { - socketError = YES; - } - - socketFDBytesAvailable = 0; - } - else if (result == 0) - { - LogVerbose(@"%@: read EOF", THIS_METHOD); - - socketError = YES; - socketFDBytesAvailable = 0; - } - else - { - size_t bytesReadFromSocket = result; - - if (socketFDBytesAvailable > bytesReadFromSocket) - socketFDBytesAvailable -= bytesReadFromSocket; - else - socketFDBytesAvailable = 0; - - if (readIntoPreBuffer) - { - [sslPreBuffer didWrite:bytesReadFromSocket]; - - size_t bytesToCopy = MIN(totalBytesLeftToBeRead, bytesReadFromSocket); - - LogVerbose(@"%@: Copying %zu bytes out of sslPreBuffer", THIS_METHOD, bytesToCopy); - - memcpy((uint8_t *)buffer + totalBytesRead, [sslPreBuffer readBuffer], bytesToCopy); - [sslPreBuffer didRead:bytesToCopy]; - - totalBytesRead += bytesToCopy; - totalBytesLeftToBeRead -= bytesToCopy; - - LogVerbose(@"%@: sslPreBuffer.length = %zu", THIS_METHOD, [sslPreBuffer availableBytes]); - } - else - { - totalBytesRead += bytesReadFromSocket; - totalBytesLeftToBeRead -= bytesReadFromSocket; - } - - done = (totalBytesLeftToBeRead == 0); - - if (done) LogVerbose(@"%@: Complete", THIS_METHOD); - } - } - - *bufferLength = totalBytesRead; - - if (done) - return noErr; - - if (socketError) - return errSSLClosedAbort; - - return errSSLWouldBlock; -} - -- (OSStatus)sslWriteWithBuffer:(const void *)buffer length:(size_t *)bufferLength -{ - if (!(flags & kSocketCanAcceptBytes)) - { - // Unable to write. - // - // Need to wait for writeSource to fire and notify us of - // available space in the socket's internal write buffer. - - [self resumeWriteSource]; - - *bufferLength = 0; - return errSSLWouldBlock; - } - - size_t bytesToWrite = *bufferLength; - size_t bytesWritten = 0; - - BOOL done = NO; - BOOL socketError = NO; - - int socketFD = (socket4FD == SOCKET_NULL) ? socket6FD : socket4FD; - - ssize_t result = write(socketFD, buffer, bytesToWrite); - - if (result < 0) - { - if (errno != EWOULDBLOCK) - { - socketError = YES; - } - - flags &= ~kSocketCanAcceptBytes; - } - else if (result == 0) - { - flags &= ~kSocketCanAcceptBytes; - } - else - { - bytesWritten = result; - - done = (bytesWritten == bytesToWrite); - } - - *bufferLength = bytesWritten; - - if (done) - return noErr; - - if (socketError) - return errSSLClosedAbort; - - return errSSLWouldBlock; -} - -static OSStatus SSLReadFunction(SSLConnectionRef connection, void *data, size_t *dataLength) -{ - GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)connection; - - NSCAssert(dispatch_get_specific(asyncSocket->IsOnSocketQueueOrTargetQueueKey), @"What the deuce?"); - - return [asyncSocket sslReadWithBuffer:data length:dataLength]; -} - -static OSStatus SSLWriteFunction(SSLConnectionRef connection, const void *data, size_t *dataLength) -{ - GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)connection; - - NSCAssert(dispatch_get_specific(asyncSocket->IsOnSocketQueueOrTargetQueueKey), @"What the deuce?"); - - return [asyncSocket sslWriteWithBuffer:data length:dataLength]; -} - -- (void)ssl_startTLS -{ - LogTrace(); - - LogVerbose(@"Starting TLS (via SecureTransport)..."); - - OSStatus status; - - GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead; - if (tlsPacket == nil) // Code to quiet the analyzer - { - NSAssert(NO, @"Logic error"); - - [self closeWithError:[self otherError:@"Logic error"]]; - return; - } - NSDictionary *tlsSettings = tlsPacket->tlsSettings; - - // Create SSLContext, and setup IO callbacks and connection ref - - BOOL isServer = [[tlsSettings objectForKey:(NSString *)kCFStreamSSLIsServer] boolValue]; - - #if TARGET_OS_IPHONE || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) - { - if (isServer) - sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType); - else - sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType); - - if (sslContext == NULL) - { - [self closeWithError:[self otherError:@"Error in SSLCreateContext"]]; - return; - } - } - #else // (__MAC_OS_X_VERSION_MIN_REQUIRED < 1080) - { - status = SSLNewContext(isServer, &sslContext); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLNewContext"]]; - return; - } - } - #endif - - status = SSLSetIOFuncs(sslContext, &SSLReadFunction, &SSLWriteFunction); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetIOFuncs"]]; - return; - } - - status = SSLSetConnection(sslContext, (__bridge SSLConnectionRef)self); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetConnection"]]; - return; - } - - - BOOL shouldManuallyEvaluateTrust = [[tlsSettings objectForKey:GCDAsyncSocketManuallyEvaluateTrust] boolValue]; - if (shouldManuallyEvaluateTrust) - { - if (isServer) - { - [self closeWithError:[self otherError:@"Manual trust validation is not supported for server sockets"]]; - return; - } - - status = SSLSetSessionOption(sslContext, kSSLSessionOptionBreakOnServerAuth, true); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetSessionOption"]]; - return; - } - - #if !TARGET_OS_IPHONE && (__MAC_OS_X_VERSION_MIN_REQUIRED < 1080) - - // Note from Apple's documentation: - // - // It is only necessary to call SSLSetEnableCertVerify on the Mac prior to OS X 10.8. - // On OS X 10.8 and later setting kSSLSessionOptionBreakOnServerAuth always disables the - // built-in trust evaluation. All versions of iOS behave like OS X 10.8 and thus - // SSLSetEnableCertVerify is not available on that platform at all. - - status = SSLSetEnableCertVerify(sslContext, NO); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetEnableCertVerify"]]; - return; - } - - #endif - } - - // Configure SSLContext from given settings - // - // Checklist: - // 1. kCFStreamSSLPeerName - // 2. kCFStreamSSLCertificates - // 3. GCDAsyncSocketSSLPeerID - // 4. GCDAsyncSocketSSLProtocolVersionMin - // 5. GCDAsyncSocketSSLProtocolVersionMax - // 6. GCDAsyncSocketSSLSessionOptionFalseStart - // 7. GCDAsyncSocketSSLSessionOptionSendOneByteRecord - // 8. GCDAsyncSocketSSLCipherSuites - // 9. GCDAsyncSocketSSLDiffieHellmanParameters (Mac) - // - // Deprecated (throw error): - // 10. kCFStreamSSLAllowsAnyRoot - // 11. kCFStreamSSLAllowsExpiredRoots - // 12. kCFStreamSSLAllowsExpiredCertificates - // 13. kCFStreamSSLValidatesCertificateChain - // 14. kCFStreamSSLLevel - - id value; - - // 1. kCFStreamSSLPeerName - - value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLPeerName]; - if ([value isKindOfClass:[NSString class]]) - { - NSString *peerName = (NSString *)value; - - const char *peer = [peerName UTF8String]; - size_t peerLen = strlen(peer); - - status = SSLSetPeerDomainName(sslContext, peer, peerLen); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetPeerDomainName"]]; - return; - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for kCFStreamSSLPeerName. Value must be of type NSString."); - - [self closeWithError:[self otherError:@"Invalid value for kCFStreamSSLPeerName."]]; - return; - } - - // 2. kCFStreamSSLCertificates - - value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLCertificates]; - if ([value isKindOfClass:[NSArray class]]) - { - CFArrayRef certs = (__bridge CFArrayRef)value; - - status = SSLSetCertificate(sslContext, certs); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetCertificate"]]; - return; - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for kCFStreamSSLCertificates. Value must be of type NSArray."); - - [self closeWithError:[self otherError:@"Invalid value for kCFStreamSSLCertificates."]]; - return; - } - - // 3. GCDAsyncSocketSSLPeerID - - value = [tlsSettings objectForKey:GCDAsyncSocketSSLPeerID]; - if ([value isKindOfClass:[NSData class]]) - { - NSData *peerIdData = (NSData *)value; - - status = SSLSetPeerID(sslContext, [peerIdData bytes], [peerIdData length]); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetPeerID"]]; - return; - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for GCDAsyncSocketSSLPeerID. Value must be of type NSData." - @" (You can convert strings to data using a method like" - @" [string dataUsingEncoding:NSUTF8StringEncoding])"); - - [self closeWithError:[self otherError:@"Invalid value for GCDAsyncSocketSSLPeerID."]]; - return; - } - - // 4. GCDAsyncSocketSSLProtocolVersionMin - - value = [tlsSettings objectForKey:GCDAsyncSocketSSLProtocolVersionMin]; - if ([value isKindOfClass:[NSNumber class]]) - { - SSLProtocol minProtocol = (SSLProtocol)[(NSNumber *)value intValue]; - if (minProtocol != kSSLProtocolUnknown) - { - status = SSLSetProtocolVersionMin(sslContext, minProtocol); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetProtocolVersionMin"]]; - return; - } - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for GCDAsyncSocketSSLProtocolVersionMin. Value must be of type NSNumber."); - - [self closeWithError:[self otherError:@"Invalid value for GCDAsyncSocketSSLProtocolVersionMin."]]; - return; - } - - // 5. GCDAsyncSocketSSLProtocolVersionMax - - value = [tlsSettings objectForKey:GCDAsyncSocketSSLProtocolVersionMax]; - if ([value isKindOfClass:[NSNumber class]]) - { - SSLProtocol maxProtocol = (SSLProtocol)[(NSNumber *)value intValue]; - if (maxProtocol != kSSLProtocolUnknown) - { - status = SSLSetProtocolVersionMax(sslContext, maxProtocol); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetProtocolVersionMax"]]; - return; - } - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for GCDAsyncSocketSSLProtocolVersionMax. Value must be of type NSNumber."); - - [self closeWithError:[self otherError:@"Invalid value for GCDAsyncSocketSSLProtocolVersionMax."]]; - return; - } - - // 6. GCDAsyncSocketSSLSessionOptionFalseStart - - value = [tlsSettings objectForKey:GCDAsyncSocketSSLSessionOptionFalseStart]; - if ([value isKindOfClass:[NSNumber class]]) - { - status = SSLSetSessionOption(sslContext, kSSLSessionOptionFalseStart, [value boolValue]); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetSessionOption (kSSLSessionOptionFalseStart)"]]; - return; - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for GCDAsyncSocketSSLSessionOptionFalseStart. Value must be of type NSNumber."); - - [self closeWithError:[self otherError:@"Invalid value for GCDAsyncSocketSSLSessionOptionFalseStart."]]; - return; - } - - // 7. GCDAsyncSocketSSLSessionOptionSendOneByteRecord - - value = [tlsSettings objectForKey:GCDAsyncSocketSSLSessionOptionSendOneByteRecord]; - if ([value isKindOfClass:[NSNumber class]]) - { - status = SSLSetSessionOption(sslContext, kSSLSessionOptionSendOneByteRecord, [value boolValue]); - if (status != noErr) - { - [self closeWithError: - [self otherError:@"Error in SSLSetSessionOption (kSSLSessionOptionSendOneByteRecord)"]]; - return; - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for GCDAsyncSocketSSLSessionOptionSendOneByteRecord." - @" Value must be of type NSNumber."); - - [self closeWithError:[self otherError:@"Invalid value for GCDAsyncSocketSSLSessionOptionSendOneByteRecord."]]; - return; - } - - // 8. GCDAsyncSocketSSLCipherSuites - - value = [tlsSettings objectForKey:GCDAsyncSocketSSLCipherSuites]; - if ([value isKindOfClass:[NSArray class]]) - { - NSArray *cipherSuites = (NSArray *)value; - NSUInteger numberCiphers = [cipherSuites count]; - SSLCipherSuite ciphers[numberCiphers]; - - NSUInteger cipherIndex; - for (cipherIndex = 0; cipherIndex < numberCiphers; cipherIndex++) - { - NSNumber *cipherObject = [cipherSuites objectAtIndex:cipherIndex]; - ciphers[cipherIndex] = [cipherObject shortValue]; - } - - status = SSLSetEnabledCiphers(sslContext, ciphers, numberCiphers); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetEnabledCiphers"]]; - return; - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for GCDAsyncSocketSSLCipherSuites. Value must be of type NSArray."); - - [self closeWithError:[self otherError:@"Invalid value for GCDAsyncSocketSSLCipherSuites."]]; - return; - } - - // 9. GCDAsyncSocketSSLDiffieHellmanParameters - - #if !TARGET_OS_IPHONE - value = [tlsSettings objectForKey:GCDAsyncSocketSSLDiffieHellmanParameters]; - if ([value isKindOfClass:[NSData class]]) - { - NSData *diffieHellmanData = (NSData *)value; - - status = SSLSetDiffieHellmanParams(sslContext, [diffieHellmanData bytes], [diffieHellmanData length]); - if (status != noErr) - { - [self closeWithError:[self otherError:@"Error in SSLSetDiffieHellmanParams"]]; - return; - } - } - else if (value) - { - NSAssert(NO, @"Invalid value for GCDAsyncSocketSSLDiffieHellmanParameters. Value must be of type NSData."); - - [self closeWithError:[self otherError:@"Invalid value for GCDAsyncSocketSSLDiffieHellmanParameters."]]; - return; - } - #endif - - // DEPRECATED checks - - // 10. kCFStreamSSLAllowsAnyRoot - - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsAnyRoot]; - #pragma clang diagnostic pop - if (value) - { - NSAssert(NO, @"Security option unavailable - kCFStreamSSLAllowsAnyRoot" - @" - You must use manual trust evaluation"); - - [self closeWithError:[self otherError:@"Security option unavailable - kCFStreamSSLAllowsAnyRoot"]]; - return; - } - - // 11. kCFStreamSSLAllowsExpiredRoots - - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredRoots]; - #pragma clang diagnostic pop - if (value) - { - NSAssert(NO, @"Security option unavailable - kCFStreamSSLAllowsExpiredRoots" - @" - You must use manual trust evaluation"); - - [self closeWithError:[self otherError:@"Security option unavailable - kCFStreamSSLAllowsExpiredRoots"]]; - return; - } - - // 12. kCFStreamSSLValidatesCertificateChain - - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLValidatesCertificateChain]; - #pragma clang diagnostic pop - if (value) - { - NSAssert(NO, @"Security option unavailable - kCFStreamSSLValidatesCertificateChain" - @" - You must use manual trust evaluation"); - - [self closeWithError:[self otherError:@"Security option unavailable - kCFStreamSSLValidatesCertificateChain"]]; - return; - } - - // 13. kCFStreamSSLAllowsExpiredCertificates - - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates]; - #pragma clang diagnostic pop - if (value) - { - NSAssert(NO, @"Security option unavailable - kCFStreamSSLAllowsExpiredCertificates" - @" - You must use manual trust evaluation"); - - [self closeWithError:[self otherError:@"Security option unavailable - kCFStreamSSLAllowsExpiredCertificates"]]; - return; - } - - // 14. kCFStreamSSLLevel - - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated-declarations" - value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLLevel]; - #pragma clang diagnostic pop - if (value) - { - NSAssert(NO, @"Security option unavailable - kCFStreamSSLLevel" - @" - You must use GCDAsyncSocketSSLProtocolVersionMin & GCDAsyncSocketSSLProtocolVersionMax"); - - [self closeWithError:[self otherError:@"Security option unavailable - kCFStreamSSLLevel"]]; - return; - } - - // Setup the sslPreBuffer - // - // Any data in the preBuffer needs to be moved into the sslPreBuffer, - // as this data is now part of the secure read stream. - - sslPreBuffer = [[GCDAsyncSocketPreBuffer alloc] initWithCapacity:(1024 * 4)]; - - size_t preBufferLength = [preBuffer availableBytes]; - - if (preBufferLength > 0) - { - [sslPreBuffer ensureCapacityForWrite:preBufferLength]; - - memcpy([sslPreBuffer writeBuffer], [preBuffer readBuffer], preBufferLength); - [preBuffer didRead:preBufferLength]; - [sslPreBuffer didWrite:preBufferLength]; - } - - sslErrCode = noErr; - - // Start the SSL Handshake process - - [self ssl_continueSSLHandshake]; -} - -- (void)ssl_continueSSLHandshake -{ - LogTrace(); - - // If the return value is noErr, the session is ready for normal secure communication. - // If the return value is errSSLWouldBlock, the SSLHandshake function must be called again. - // If the return value is errSSLServerAuthCompleted, we ask delegate if we should trust the - // server and then call SSLHandshake again to resume the handshake or close the connection - // errSSLPeerBadCert SSL error. - // Otherwise, the return value indicates an error code. - - OSStatus status = SSLHandshake(sslContext); - - if (status == noErr) - { - LogVerbose(@"SSLHandshake complete"); - - flags &= ~kStartingReadTLS; - flags &= ~kStartingWriteTLS; - - flags |= kSocketSecure; - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socketDidSecure:)]) - { - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socketDidSecure:self]; - }}); - } - - [self endCurrentRead]; - [self endCurrentWrite]; - - [self maybeDequeueRead]; - [self maybeDequeueWrite]; - } - else if (status == errSSLPeerAuthCompleted) - { - LogVerbose(@"SSLHandshake peerAuthCompleted - awaiting delegate approval"); - - __block SecTrustRef trust = NULL; - status = SSLCopyPeerTrust(sslContext, &trust); - if (status != noErr) - { - [self closeWithError:[self sslError:status]]; - return; - } - - int aStateIndex = stateIndex; - dispatch_queue_t theSocketQueue = socketQueue; - - __weak GCDAsyncSocket *weakSelf = self; - - void (^comletionHandler)(BOOL) = ^(BOOL shouldTrust){ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - dispatch_async(theSocketQueue, ^{ @autoreleasepool { - - if (trust) { - CFRelease(trust); - trust = NULL; - } - - __strong GCDAsyncSocket *strongSelf = weakSelf; - if (strongSelf) - { - [strongSelf ssl_shouldTrustPeer:shouldTrust stateIndex:aStateIndex]; - } - }}); - - #pragma clang diagnostic pop - }}; - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socket:didReceiveTrust:completionHandler:)]) - { - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socket:self didReceiveTrust:trust completionHandler:comletionHandler]; - }}); - } - else - { - if (trust) { - CFRelease(trust); - trust = NULL; - } - - NSString *msg = @"GCDAsyncSocketManuallyEvaluateTrust specified in tlsSettings," - @" but delegate doesn't implement socket:shouldTrustPeer:"; - - [self closeWithError:[self otherError:msg]]; - return; - } - } - else if (status == errSSLWouldBlock) - { - LogVerbose(@"SSLHandshake continues..."); - - // Handshake continues... - // - // This method will be called again from doReadData or doWriteData. - } - else - { - [self closeWithError:[self sslError:status]]; - } -} - -- (void)ssl_shouldTrustPeer:(BOOL)shouldTrust stateIndex:(int)aStateIndex -{ - LogTrace(); - - if (aStateIndex != stateIndex) - { - LogInfo(@"Ignoring ssl_shouldTrustPeer - invalid state (maybe disconnected)"); - - // One of the following is true - // - the socket was disconnected - // - the startTLS operation timed out - // - the completionHandler was already invoked once - - return; - } - - // Increment stateIndex to ensure completionHandler can only be called once. - stateIndex++; - - if (shouldTrust) - { - [self ssl_continueSSLHandshake]; - } - else - { - [self closeWithError:[self sslError:errSSLPeerBadCert]]; - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Security via CFStream -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#if TARGET_OS_IPHONE - -- (void)cf_finishSSLHandshake -{ - LogTrace(); - - if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS)) - { - flags &= ~kStartingReadTLS; - flags &= ~kStartingWriteTLS; - - flags |= kSocketSecure; - - __strong id theDelegate = delegate; - - if (delegateQueue && [theDelegate respondsToSelector:@selector(socketDidSecure:)]) - { - dispatch_async(delegateQueue, ^{ @autoreleasepool { - - [theDelegate socketDidSecure:self]; - }}); - } - - [self endCurrentRead]; - [self endCurrentWrite]; - - [self maybeDequeueRead]; - [self maybeDequeueWrite]; - } -} - -- (void)cf_abortSSLHandshake:(NSError *)error -{ - LogTrace(); - - if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS)) - { - flags &= ~kStartingReadTLS; - flags &= ~kStartingWriteTLS; - - [self closeWithError:error]; - } -} - -- (void)cf_startTLS -{ - LogTrace(); - - LogVerbose(@"Starting TLS (via CFStream)..."); - - if ([preBuffer availableBytes] > 0) - { - NSString *msg = @"Invalid TLS transition. Handshake has already been read from socket."; - - [self closeWithError:[self otherError:msg]]; - return; - } - - [self suspendReadSource]; - [self suspendWriteSource]; - - socketFDBytesAvailable = 0; - flags &= ~kSocketCanAcceptBytes; - flags &= ~kSecureSocketHasBytesAvailable; - - flags |= kUsingCFStreamForTLS; - - if (![self createReadAndWriteStream]) - { - [self closeWithError:[self otherError:@"Error in CFStreamCreatePairWithSocket"]]; - return; - } - - if (![self registerForStreamCallbacksIncludingReadWrite:YES]) - { - [self closeWithError:[self otherError:@"Error in CFStreamSetClient"]]; - return; - } - - if (![self addStreamsToRunLoop]) - { - [self closeWithError:[self otherError:@"Error in CFStreamScheduleWithRunLoop"]]; - return; - } - - NSAssert([currentRead isKindOfClass:[GCDAsyncSpecialPacket class]], @"Invalid read packet for startTLS"); - NSAssert([currentWrite isKindOfClass:[GCDAsyncSpecialPacket class]], @"Invalid write packet for startTLS"); - - GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead; - CFDictionaryRef tlsSettings = (__bridge CFDictionaryRef)tlsPacket->tlsSettings; - - // Getting an error concerning kCFStreamPropertySSLSettings ? - // You need to add the CFNetwork framework to your iOS application. - - BOOL r1 = CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, tlsSettings); - BOOL r2 = CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, tlsSettings); - - // For some reason, starting around the time of iOS 4.3, - // the first call to set the kCFStreamPropertySSLSettings will return true, - // but the second will return false. - // - // Order doesn't seem to matter. - // So you could call CFReadStreamSetProperty and then CFWriteStreamSetProperty, or you could reverse the order. - // Either way, the first call will return true, and the second returns false. - // - // Interestingly, this doesn't seem to affect anything. - // Which is not altogether unusual, as the documentation seems to suggest that (for many settings) - // setting it on one side of the stream automatically sets it for the other side of the stream. - // - // Although there isn't anything in the documentation to suggest that the second attempt would fail. - // - // Furthermore, this only seems to affect streams that are negotiating a security upgrade. - // In other words, the socket gets connected, there is some back-and-forth communication over the unsecure - // connection, and then a startTLS is issued. - // So this mostly affects newer protocols (XMPP, IMAP) as opposed to older protocols (HTTPS). - - if (!r1 && !r2) // Yes, the && is correct - workaround for apple bug. - { - [self closeWithError:[self otherError:@"Error in CFStreamSetProperty"]]; - return; - } - - if (![self openStreams]) - { - [self closeWithError:[self otherError:@"Error in CFStreamOpen"]]; - return; - } - - LogVerbose(@"Waiting for SSL Handshake to complete..."); -} - -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark CFStream -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#if TARGET_OS_IPHONE - -+ (void)ignore:(id)_ -{} - -+ (void)startCFStreamThreadIfNeeded -{ - LogTrace(); - - static dispatch_once_t predicate; - dispatch_once(&predicate, ^{ - - cfstreamThreadRetainCount = 0; - cfstreamThreadSetupQueue = dispatch_queue_create("GCDAsyncSocket-CFStreamThreadSetup", DISPATCH_QUEUE_SERIAL); - }); - - dispatch_sync(cfstreamThreadSetupQueue, ^{ @autoreleasepool { - - if (++cfstreamThreadRetainCount == 1) - { - cfstreamThread = [[NSThread alloc] initWithTarget:self - selector:@selector(cfstreamThread) - object:nil]; - [cfstreamThread start]; - } - }}); -} - -+ (void)stopCFStreamThreadIfNeeded -{ - LogTrace(); - - // The creation of the cfstreamThread is relatively expensive. - // So we'd like to keep it available for recycling. - // However, there's a tradeoff here, because it shouldn't remain alive forever. - // So what we're going to do is use a little delay before taking it down. - // This way it can be reused properly in situations where multiple sockets are continually in flux. - - int delayInSeconds = 30; - dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); - dispatch_after(when, cfstreamThreadSetupQueue, ^{ @autoreleasepool { - #pragma clang diagnostic push - #pragma clang diagnostic warning "-Wimplicit-retain-self" - - if (cfstreamThreadRetainCount == 0) - { - LogWarn(@"Logic error concerning cfstreamThread start / stop"); - return_from_block; - } - - if (--cfstreamThreadRetainCount == 0) - { - [cfstreamThread cancel]; // set isCancelled flag - - // wake up the thread - [GCDAsyncSocket performSelector:@selector(ignore:) - onThread:cfstreamThread - withObject:[NSNull null] - waitUntilDone:NO]; - - cfstreamThread = nil; - } - - #pragma clang diagnostic pop - }}); -} - -+ (void)cfstreamThread { @autoreleasepool -{ - [[NSThread currentThread] setName:GCDAsyncSocketThreadName]; - - LogInfo(@"CFStreamThread: Started"); - - // We can't run the run loop unless it has an associated input source or a timer. - // So we'll just create a timer that will never fire - unless the server runs for decades. - [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow] - target:self - selector:@selector(ignore:) - userInfo:nil - repeats:YES]; - - NSThread *currentThread = [NSThread currentThread]; - NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; - - BOOL isCancelled = [currentThread isCancelled]; - - while (!isCancelled && [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) - { - isCancelled = [currentThread isCancelled]; - } - - LogInfo(@"CFStreamThread: Stopped"); -}} - -+ (void)scheduleCFStreams:(GCDAsyncSocket *)asyncSocket -{ - LogTrace(); - NSAssert([NSThread currentThread] == cfstreamThread, @"Invoked on wrong thread"); - - CFRunLoopRef runLoop = CFRunLoopGetCurrent(); - - if (asyncSocket->readStream) - CFReadStreamScheduleWithRunLoop(asyncSocket->readStream, runLoop, kCFRunLoopDefaultMode); - - if (asyncSocket->writeStream) - CFWriteStreamScheduleWithRunLoop(asyncSocket->writeStream, runLoop, kCFRunLoopDefaultMode); -} - -+ (void)unscheduleCFStreams:(GCDAsyncSocket *)asyncSocket -{ - LogTrace(); - NSAssert([NSThread currentThread] == cfstreamThread, @"Invoked on wrong thread"); - - CFRunLoopRef runLoop = CFRunLoopGetCurrent(); - - if (asyncSocket->readStream) - CFReadStreamUnscheduleFromRunLoop(asyncSocket->readStream, runLoop, kCFRunLoopDefaultMode); - - if (asyncSocket->writeStream) - CFWriteStreamUnscheduleFromRunLoop(asyncSocket->writeStream, runLoop, kCFRunLoopDefaultMode); -} - -static void CFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo) -{ - GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)pInfo; - - switch(type) - { - case kCFStreamEventHasBytesAvailable: - { - dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool { - - LogCVerbose(@"CFReadStreamCallback - HasBytesAvailable"); - - if (asyncSocket->readStream != stream) - return_from_block; - - if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS)) - { - // If we set kCFStreamPropertySSLSettings before we opened the streams, this might be a lie. - // (A callback related to the tcp stream, but not to the SSL layer). - - if (CFReadStreamHasBytesAvailable(asyncSocket->readStream)) - { - asyncSocket->flags |= kSecureSocketHasBytesAvailable; - [asyncSocket cf_finishSSLHandshake]; - } - } - else - { - asyncSocket->flags |= kSecureSocketHasBytesAvailable; - [asyncSocket doReadData]; - } - }}); - - break; - } - default: - { - NSError *error = (__bridge_transfer NSError *)CFReadStreamCopyError(stream); - - if (error == nil && type == kCFStreamEventEndEncountered) - { - error = [asyncSocket connectionClosedError]; - } - - dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool { - - LogCVerbose(@"CFReadStreamCallback - Other"); - - if (asyncSocket->readStream != stream) - return_from_block; - - if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS)) - { - [asyncSocket cf_abortSSLHandshake:error]; - } - else - { - [asyncSocket closeWithError:error]; - } - }}); - - break; - } - } - -} - -static void CFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType type, void *pInfo) -{ - GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)pInfo; - - switch(type) - { - case kCFStreamEventCanAcceptBytes: - { - dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool { - - LogCVerbose(@"CFWriteStreamCallback - CanAcceptBytes"); - - if (asyncSocket->writeStream != stream) - return_from_block; - - if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS)) - { - // If we set kCFStreamPropertySSLSettings before we opened the streams, this might be a lie. - // (A callback related to the tcp stream, but not to the SSL layer). - - if (CFWriteStreamCanAcceptBytes(asyncSocket->writeStream)) - { - asyncSocket->flags |= kSocketCanAcceptBytes; - [asyncSocket cf_finishSSLHandshake]; - } - } - else - { - asyncSocket->flags |= kSocketCanAcceptBytes; - [asyncSocket doWriteData]; - } - }}); - - break; - } - default: - { - NSError *error = (__bridge_transfer NSError *)CFWriteStreamCopyError(stream); - - if (error == nil && type == kCFStreamEventEndEncountered) - { - error = [asyncSocket connectionClosedError]; - } - - dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool { - - LogCVerbose(@"CFWriteStreamCallback - Other"); - - if (asyncSocket->writeStream != stream) - return_from_block; - - if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS)) - { - [asyncSocket cf_abortSSLHandshake:error]; - } - else - { - [asyncSocket closeWithError:error]; - } - }}); - - break; - } - } - -} - -- (BOOL)createReadAndWriteStream -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - - - if (readStream || writeStream) - { - // Streams already created - return YES; - } - - int socketFD = (socket6FD == SOCKET_NULL) ? socket4FD : socket6FD; - - if (socketFD == SOCKET_NULL) - { - // Cannot create streams without a file descriptor - return NO; - } - - if (![self isConnected]) - { - // Cannot create streams until file descriptor is connected - return NO; - } - - LogVerbose(@"Creating read and write stream..."); - - CFStreamCreatePairWithSocket(NULL, (CFSocketNativeHandle)socketFD, &readStream, &writeStream); - - // The kCFStreamPropertyShouldCloseNativeSocket property should be false by default (for our case). - // But let's not take any chances. - - if (readStream) - CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse); - if (writeStream) - CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse); - - if ((readStream == NULL) || (writeStream == NULL)) - { - LogWarn(@"Unable to create read and write stream..."); - - if (readStream) - { - CFReadStreamClose(readStream); - CFRelease(readStream); - readStream = NULL; - } - if (writeStream) - { - CFWriteStreamClose(writeStream); - CFRelease(writeStream); - writeStream = NULL; - } - - return NO; - } - - return YES; -} - -- (BOOL)registerForStreamCallbacksIncludingReadWrite:(BOOL)includeReadWrite -{ - LogVerbose(@"%@ %@", THIS_METHOD, (includeReadWrite ? @"YES" : @"NO")); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null"); - - streamContext.version = 0; - streamContext.info = (__bridge void *)(self); - streamContext.retain = nil; - streamContext.release = nil; - streamContext.copyDescription = nil; - - CFOptionFlags readStreamEvents = kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered; - if (includeReadWrite) - readStreamEvents |= kCFStreamEventHasBytesAvailable; - - if (!CFReadStreamSetClient(readStream, readStreamEvents, &CFReadStreamCallback, &streamContext)) - { - return NO; - } - - CFOptionFlags writeStreamEvents = kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered; - if (includeReadWrite) - writeStreamEvents |= kCFStreamEventCanAcceptBytes; - - if (!CFWriteStreamSetClient(writeStream, writeStreamEvents, &CFWriteStreamCallback, &streamContext)) - { - return NO; - } - - return YES; -} - -- (BOOL)addStreamsToRunLoop -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null"); - - if (!(flags & kAddedStreamsToRunLoop)) - { - LogVerbose(@"Adding streams to runloop..."); - - [[self class] startCFStreamThreadIfNeeded]; - [[self class] performSelector:@selector(scheduleCFStreams:) - onThread:cfstreamThread - withObject:self - waitUntilDone:YES]; - - flags |= kAddedStreamsToRunLoop; - } - - return YES; -} - -- (void)removeStreamsFromRunLoop -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null"); - - if (flags & kAddedStreamsToRunLoop) - { - LogVerbose(@"Removing streams from runloop..."); - - [[self class] performSelector:@selector(unscheduleCFStreams:) - onThread:cfstreamThread - withObject:self - waitUntilDone:YES]; - [[self class] stopCFStreamThreadIfNeeded]; - - flags &= ~kAddedStreamsToRunLoop; - } -} - -- (BOOL)openStreams -{ - LogTrace(); - - NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); - NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null"); - - CFStreamStatus readStatus = CFReadStreamGetStatus(readStream); - CFStreamStatus writeStatus = CFWriteStreamGetStatus(writeStream); - - if ((readStatus == kCFStreamStatusNotOpen) || (writeStatus == kCFStreamStatusNotOpen)) - { - LogVerbose(@"Opening read and write stream..."); - - BOOL r1 = CFReadStreamOpen(readStream); - BOOL r2 = CFWriteStreamOpen(writeStream); - - if (!r1 || !r2) - { - LogError(@"Error in CFStreamOpen"); - return NO; - } - } - - return YES; -} - -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Advanced -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * See header file for big discussion of this method. -**/ -- (BOOL)autoDisconnectOnClosedReadStream -{ - // Note: YES means kAllowHalfDuplexConnection is OFF - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - return ((config & kAllowHalfDuplexConnection) == 0); - } - else - { - __block BOOL result; - - dispatch_sync(socketQueue, ^{ - result = ((config & kAllowHalfDuplexConnection) == 0); - }); - - return result; - } -} - -/** - * See header file for big discussion of this method. -**/ -- (void)setAutoDisconnectOnClosedReadStream:(BOOL)flag -{ - // Note: YES means kAllowHalfDuplexConnection is OFF - - dispatch_block_t block = ^{ - - if (flag) - config &= ~kAllowHalfDuplexConnection; - else - config |= kAllowHalfDuplexConnection; - }; - - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_async(socketQueue, block); -} - - -/** - * See header file for big discussion of this method. -**/ -- (void)markSocketQueueTargetQueue:(dispatch_queue_t)socketNewTargetQueue -{ - void *nonNullUnusedPointer = (__bridge void *)self; - dispatch_queue_set_specific(socketNewTargetQueue, IsOnSocketQueueOrTargetQueueKey, nonNullUnusedPointer, NULL); -} - -/** - * See header file for big discussion of this method. -**/ -- (void)unmarkSocketQueueTargetQueue:(dispatch_queue_t)socketOldTargetQueue -{ - dispatch_queue_set_specific(socketOldTargetQueue, IsOnSocketQueueOrTargetQueueKey, NULL, NULL); -} - -/** - * See header file for big discussion of this method. -**/ -- (void)performBlock:(dispatch_block_t)block -{ - if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - block(); - else - dispatch_sync(socketQueue, block); -} - -/** - * Questions? Have you read the header file? -**/ -- (int)socketFD -{ - if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD); - return SOCKET_NULL; - } - - if (socket4FD != SOCKET_NULL) - return socket4FD; - else - return socket6FD; -} - -/** - * Questions? Have you read the header file? -**/ -- (int)socket4FD -{ - if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD); - return SOCKET_NULL; - } - - return socket4FD; -} - -/** - * Questions? Have you read the header file? -**/ -- (int)socket6FD -{ - if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD); - return SOCKET_NULL; - } - - return socket6FD; -} - -#if TARGET_OS_IPHONE - -/** - * Questions? Have you read the header file? -**/ -- (CFReadStreamRef)readStream -{ - if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD); - return NULL; - } - - if (readStream == NULL) - [self createReadAndWriteStream]; - - return readStream; -} - -/** - * Questions? Have you read the header file? -**/ -- (CFWriteStreamRef)writeStream -{ - if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD); - return NULL; - } - - if (writeStream == NULL) - [self createReadAndWriteStream]; - - return writeStream; -} - -- (BOOL)enableBackgroundingOnSocketWithCaveat:(BOOL)caveat -{ - if (![self createReadAndWriteStream]) - { - // Error occured creating streams (perhaps socket isn't open) - return NO; - } - - BOOL r1, r2; - - LogVerbose(@"Enabling backgrouding on socket"); - - r1 = CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); - r2 = CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); - - if (!r1 || !r2) - { - return NO; - } - - if (!caveat) - { - if (![self openStreams]) - { - return NO; - } - } - - return YES; -} - -/** - * Questions? Have you read the header file? -**/ -- (BOOL)enableBackgroundingOnSocket -{ - LogTrace(); - - if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD); - return NO; - } - - return [self enableBackgroundingOnSocketWithCaveat:NO]; -} - -- (BOOL)enableBackgroundingOnSocketWithCaveat // Deprecated in iOS 4.??? -{ - // This method was created as a workaround for a bug in iOS. - // Apple has since fixed this bug. - // I'm not entirely sure which version of iOS they fixed it in... - - LogTrace(); - - if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD); - return NO; - } - - return [self enableBackgroundingOnSocketWithCaveat:YES]; -} - -#endif - -- (SSLContextRef)sslContext -{ - if (!dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) - { - LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD); - return NULL; - } - - return sslContext; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Class Utilities -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -+ (NSMutableArray *)lookupHost:(NSString *)host port:(uint16_t)port error:(NSError **)errPtr -{ - LogTrace(); - - NSMutableArray *addresses = nil; - NSError *error = nil; - - if ([host isEqualToString:@"localhost"] || [host isEqualToString:@"loopback"]) - { - // Use LOOPBACK address - struct sockaddr_in nativeAddr4; - nativeAddr4.sin_len = sizeof(struct sockaddr_in); - nativeAddr4.sin_family = AF_INET; - nativeAddr4.sin_port = htons(port); - nativeAddr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - memset(&(nativeAddr4.sin_zero), 0, sizeof(nativeAddr4.sin_zero)); - - struct sockaddr_in6 nativeAddr6; - nativeAddr6.sin6_len = sizeof(struct sockaddr_in6); - nativeAddr6.sin6_family = AF_INET6; - nativeAddr6.sin6_port = htons(port); - nativeAddr6.sin6_flowinfo = 0; - nativeAddr6.sin6_addr = in6addr_loopback; - nativeAddr6.sin6_scope_id = 0; - - // Wrap the native address structures - - NSData *address4 = [NSData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)]; - NSData *address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)]; - - addresses = [NSMutableArray arrayWithCapacity:2]; - [addresses addObject:address4]; - [addresses addObject:address6]; - } - else - { - NSString *portStr = [NSString stringWithFormat:@"%hu", port]; - - struct addrinfo hints, *res, *res0; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - int gai_error = getaddrinfo([host UTF8String], [portStr UTF8String], &hints, &res0); - - if (gai_error) - { - error = [self gaiError:gai_error]; - } - else - { - NSUInteger capacity = 0; - for (res = res0; res; res = res->ai_next) - { - if (res->ai_family == AF_INET || res->ai_family == AF_INET6) { - capacity++; - } - } - - addresses = [NSMutableArray arrayWithCapacity:capacity]; - - for (res = res0; res; res = res->ai_next) - { - if (res->ai_family == AF_INET) - { - // Found IPv4 address. - // Wrap the native address structure, and add to results. - - NSData *address4 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen]; - [addresses addObject:address4]; - } - else if (res->ai_family == AF_INET6) - { - // Found IPv6 address. - // Wrap the native address structure, and add to results. - - NSData *address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen]; - [addresses addObject:address6]; - } - } - freeaddrinfo(res0); - - if ([addresses count] == 0) - { - error = [self gaiError:EAI_FAIL]; - } - } - } - - if (errPtr) *errPtr = error; - return addresses; -} - -+ (NSString *)hostFromSockaddr4:(const struct sockaddr_in *)pSockaddr4 -{ - char addrBuf[INET_ADDRSTRLEN]; - - if (inet_ntop(AF_INET, &pSockaddr4->sin_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL) - { - addrBuf[0] = '\0'; - } - - return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding]; -} - -+ (NSString *)hostFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6 -{ - char addrBuf[INET6_ADDRSTRLEN]; - - if (inet_ntop(AF_INET6, &pSockaddr6->sin6_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL) - { - addrBuf[0] = '\0'; - } - - return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding]; -} - -+ (uint16_t)portFromSockaddr4:(const struct sockaddr_in *)pSockaddr4 -{ - return ntohs(pSockaddr4->sin_port); -} - -+ (uint16_t)portFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6 -{ - return ntohs(pSockaddr6->sin6_port); -} - -+ (NSString *)hostFromAddress:(NSData *)address -{ - NSString *host; - - if ([self getHost:&host port:NULL fromAddress:address]) - return host; - else - return nil; -} - -+ (uint16_t)portFromAddress:(NSData *)address -{ - uint16_t port; - - if ([self getHost:NULL port:&port fromAddress:address]) - return port; - else - return 0; -} - -+ (BOOL)isIPv4Address:(NSData *)address -{ - if ([address length] >= sizeof(struct sockaddr)) - { - const struct sockaddr *sockaddrX = [address bytes]; - - if (sockaddrX->sa_family == AF_INET) { - return YES; - } - } - - return NO; -} - -+ (BOOL)isIPv6Address:(NSData *)address -{ - if ([address length] >= sizeof(struct sockaddr)) - { - const struct sockaddr *sockaddrX = [address bytes]; - - if (sockaddrX->sa_family == AF_INET6) { - return YES; - } - } - - return NO; -} - -+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address -{ - return [self getHost:hostPtr port:portPtr family:NULL fromAddress:address]; -} - -+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr family:(sa_family_t *)afPtr fromAddress:(NSData *)address -{ - if ([address length] >= sizeof(struct sockaddr)) - { - const struct sockaddr *sockaddrX = [address bytes]; - - if (sockaddrX->sa_family == AF_INET) - { - if ([address length] >= sizeof(struct sockaddr_in)) - { - struct sockaddr_in sockaddr4; - memcpy(&sockaddr4, sockaddrX, sizeof(sockaddr4)); - - if (hostPtr) *hostPtr = [self hostFromSockaddr4:&sockaddr4]; - if (portPtr) *portPtr = [self portFromSockaddr4:&sockaddr4]; - if (afPtr) *afPtr = AF_INET; - - return YES; - } - } - else if (sockaddrX->sa_family == AF_INET6) - { - if ([address length] >= sizeof(struct sockaddr_in6)) - { - struct sockaddr_in6 sockaddr6; - memcpy(&sockaddr6, sockaddrX, sizeof(sockaddr6)); - - if (hostPtr) *hostPtr = [self hostFromSockaddr6:&sockaddr6]; - if (portPtr) *portPtr = [self portFromSockaddr6:&sockaddr6]; - if (afPtr) *afPtr = AF_INET6; - - return YES; - } - } - } - - return NO; -} - -+ (NSData *)CRLFData -{ - return [NSData dataWithBytes:"\x0D\x0A" length:2]; -} - -+ (NSData *)CRData -{ - return [NSData dataWithBytes:"\x0D" length:1]; -} - -+ (NSData *)LFData -{ - return [NSData dataWithBytes:"\x0A" length:1]; -} - -+ (NSData *)ZeroData -{ - return [NSData dataWithBytes:"" length:1]; -} - -@end diff --git a/Vendor/CocoaLumberjack/DDASLLogger.h b/Vendor/CocoaLumberjack/DDASLLogger.h deleted file mode 100755 index 2aaf4e3225..0000000000 --- a/Vendor/CocoaLumberjack/DDASLLogger.h +++ /dev/null @@ -1,41 +0,0 @@ -#import -#import - -#import "DDLog.h" - -/** - * Welcome to Cocoa Lumberjack! - * - * The project page has a wealth of documentation if you have any questions. - * https://github.com/CocoaLumberjack/CocoaLumberjack - * - * If you're new to the project you may wish to read the "Getting Started" wiki. - * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted - * - * - * This class provides a logger for the Apple System Log facility. - * - * As described in the "Getting Started" page, - * the traditional NSLog() function directs it's output to two places: - * - * - Apple System Log - * - StdErr (if stderr is a TTY) so log statements show up in Xcode console - * - * To duplicate NSLog() functionality you can simply add this logger and a tty logger. - * However, if you instead choose to use file logging (for faster performance), - * you may choose to use a file logger and a tty logger. -**/ - -@interface DDASLLogger : DDAbstractLogger -{ - aslclient client; -} - -+ (instancetype)sharedInstance; - -// Inherited from DDAbstractLogger - -// - (id )logFormatter; -// - (void)setLogFormatter:(id )formatter; - -@end diff --git a/Vendor/CocoaLumberjack/DDASLLogger.m b/Vendor/CocoaLumberjack/DDASLLogger.m deleted file mode 100755 index 90beff113c..0000000000 --- a/Vendor/CocoaLumberjack/DDASLLogger.m +++ /dev/null @@ -1,100 +0,0 @@ -#import "DDASLLogger.h" - -#import - -/** - * Welcome to Cocoa Lumberjack! - * - * The project page has a wealth of documentation if you have any questions. - * https://github.com/CocoaLumberjack/CocoaLumberjack - * - * If you're new to the project you may wish to read the "Getting Started" wiki. - * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted -**/ - -#if ! __has_feature(objc_arc) -#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). -#endif - - -@implementation DDASLLogger - -static DDASLLogger *sharedInstance; - -/** - * The runtime sends initialize to each class in a program exactly one time just before the class, - * or any class that inherits from it, is sent its first message from within the program. (Thus the - * method may never be invoked if the class is not used.) The runtime sends the initialize message to - * classes in a thread-safe manner. Superclasses receive this message before their subclasses. - * - * This method may also be called directly (assumably by accident), hence the safety mechanism. -**/ -+ (void)initialize -{ - static BOOL initialized = NO; - if (!initialized) - { - initialized = YES; - - sharedInstance = [[[self class] alloc] init]; - } -} - -+ (instancetype)sharedInstance -{ - return sharedInstance; -} - -- (id)init -{ - if (sharedInstance != nil) - { - return nil; - } - - if ((self = [super init])) - { - // A default asl client is provided for the main thread, - // but background threads need to create their own client. - - client = asl_open(NULL, "com.apple.console", 0); - } - return self; -} - -- (void)logMessage:(DDLogMessage *)logMessage -{ - NSString *logMsg = logMessage->logMsg; - - if (formatter) - { - logMsg = [formatter formatLogMessage:logMessage]; - } - - if (logMsg) - { - const char *msg = [logMsg UTF8String]; - - int aslLogLevel; - switch (logMessage->logFlag) - { - // Note: By default ASL will filter anything above level 5 (Notice). - // So our mappings shouldn't go above that level. - - case LOG_FLAG_ERROR : aslLogLevel = ASL_LEVEL_ALERT; break; - case LOG_FLAG_WARN : aslLogLevel = ASL_LEVEL_CRIT; break; - case LOG_FLAG_INFO : aslLogLevel = ASL_LEVEL_ERR; break; - case LOG_FLAG_DEBUG : aslLogLevel = ASL_LEVEL_WARNING; break; - default : aslLogLevel = ASL_LEVEL_NOTICE; break; - } - - asl_log(client, NULL, aslLogLevel, "%s", msg); - } -} - -- (NSString *)loggerName -{ - return @"cocoa.lumberjack.aslLogger"; -} - -@end diff --git a/Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.h b/Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.h deleted file mode 100755 index 4e0c33cdac..0000000000 --- a/Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.h +++ /dev/null @@ -1,102 +0,0 @@ -#import - -#import "DDLog.h" - -/** - * Welcome to Cocoa Lumberjack! - * - * The project page has a wealth of documentation if you have any questions. - * https://github.com/CocoaLumberjack/CocoaLumberjack - * - * If you're new to the project you may wish to read the "Getting Started" wiki. - * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted - * - * - * This class provides an abstract implementation of a database logger. - * - * That is, it provides the base implementation for a database logger to build atop of. - * All that is needed for a concrete database logger is to extend this class - * and override the methods in the implementation file that are prefixed with "db_". -**/ - -@interface DDAbstractDatabaseLogger : DDAbstractLogger { -@protected - NSUInteger saveThreshold; - NSTimeInterval saveInterval; - NSTimeInterval maxAge; - NSTimeInterval deleteInterval; - BOOL deleteOnEverySave; - - BOOL saveTimerSuspended; - NSUInteger unsavedCount; - dispatch_time_t unsavedTime; - dispatch_source_t saveTimer; - dispatch_time_t lastDeleteTime; - dispatch_source_t deleteTimer; -} - -/** - * Specifies how often to save the data to disk. - * Since saving is an expensive operation (disk io) it is not done after every log statement. - * These properties allow you to configure how/when the logger saves to disk. - * - * A save is done when either (whichever happens first): - * - * - The number of unsaved log entries reaches saveThreshold - * - The amount of time since the oldest unsaved log entry was created reaches saveInterval - * - * You can optionally disable the saveThreshold by setting it to zero. - * If you disable the saveThreshold you are entirely dependent on the saveInterval. - * - * You can optionally disable the saveInterval by setting it to zero (or a negative value). - * If you disable the saveInterval you are entirely dependent on the saveThreshold. - * - * It's not wise to disable both saveThreshold and saveInterval. - * - * The default saveThreshold is 500. - * The default saveInterval is 60 seconds. -**/ -@property (assign, readwrite) NSUInteger saveThreshold; -@property (assign, readwrite) NSTimeInterval saveInterval; - -/** - * It is likely you don't want the log entries to persist forever. - * Doing so would allow the database to grow infinitely large over time. - * - * The maxAge property provides a way to specify how old a log statement can get - * before it should get deleted from the database. - * - * The deleteInterval specifies how often to sweep for old log entries. - * Since deleting is an expensive operation (disk io) is is done on a fixed interval. - * - * An alternative to the deleteInterval is the deleteOnEverySave option. - * This specifies that old log entries should be deleted during every save operation. - * - * You can optionally disable the maxAge by setting it to zero (or a negative value). - * If you disable the maxAge then old log statements are not deleted. - * - * You can optionally disable the deleteInterval by setting it to zero (or a negative value). - * - * If you disable both deleteInterval and deleteOnEverySave then old log statements are not deleted. - * - * It's not wise to enable both deleteInterval and deleteOnEverySave. - * - * The default maxAge is 7 days. - * The default deleteInterval is 5 minutes. - * The default deleteOnEverySave is NO. -**/ -@property (assign, readwrite) NSTimeInterval maxAge; -@property (assign, readwrite) NSTimeInterval deleteInterval; -@property (assign, readwrite) BOOL deleteOnEverySave; - -/** - * Forces a save of any pending log entries (flushes log entries to disk). -**/ -- (void)savePendingLogEntries; - -/** - * Removes any log entries that are older than maxAge. -**/ -- (void)deleteOldLogEntries; - -@end diff --git a/Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.m b/Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.m deleted file mode 100755 index 1410f7a5e7..0000000000 --- a/Vendor/CocoaLumberjack/DDAbstractDatabaseLogger.m +++ /dev/null @@ -1,727 +0,0 @@ -#import "DDAbstractDatabaseLogger.h" -#import - -/** - * Welcome to Cocoa Lumberjack! - * - * The project page has a wealth of documentation if you have any questions. - * https://github.com/CocoaLumberjack/CocoaLumberjack - * - * If you're new to the project you may wish to read the "Getting Started" wiki. - * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted -**/ - -#if ! __has_feature(objc_arc) -#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). -#endif - -@interface DDAbstractDatabaseLogger () -- (void)destroySaveTimer; -- (void)destroyDeleteTimer; -@end - -#pragma mark - - -@implementation DDAbstractDatabaseLogger - -- (id)init -{ - if ((self = [super init])) - { - saveThreshold = 500; - saveInterval = 60; // 60 seconds - maxAge = (60 * 60 * 24 * 7); // 7 days - deleteInterval = (60 * 5); // 5 minutes - } - return self; -} - -- (void)dealloc -{ - [self destroySaveTimer]; - [self destroyDeleteTimer]; - -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Override Me -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (BOOL)db_log:(DDLogMessage *)logMessage -{ - // Override me and add your implementation. - // - // Return YES if an item was added to the buffer. - // Return NO if the logMessage was ignored. - - return NO; -} - -- (void)db_save -{ - // Override me and add your implementation. -} - -- (void)db_delete -{ - // Override me and add your implementation. -} - -- (void)db_saveAndDelete -{ - // Override me and add your implementation. -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Private API -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (void)performSaveAndSuspendSaveTimer -{ - if (unsavedCount > 0) - { - if (deleteOnEverySave) - [self db_saveAndDelete]; - else - [self db_save]; - } - - unsavedCount = 0; - unsavedTime = 0; - - if (saveTimer && !saveTimerSuspended) - { - dispatch_suspend(saveTimer); - saveTimerSuspended = YES; - } -} - -- (void)performDelete -{ - if (maxAge > 0.0) - { - [self db_delete]; - - lastDeleteTime = dispatch_time(DISPATCH_TIME_NOW, 0); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Timers -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (void)destroySaveTimer -{ - if (saveTimer) - { - dispatch_source_cancel(saveTimer); - if (saveTimerSuspended) - { - // Must resume a timer before releasing it (or it will crash) - dispatch_resume(saveTimer); - saveTimerSuspended = NO; - } - #if !OS_OBJECT_USE_OBJC - dispatch_release(saveTimer); - #endif - saveTimer = NULL; - } -} - -- (void)updateAndResumeSaveTimer -{ - if ((saveTimer != NULL) && (saveInterval > 0.0) && (unsavedTime > 0.0)) - { - uint64_t interval = (uint64_t)(saveInterval * NSEC_PER_SEC); - dispatch_time_t startTime = dispatch_time(unsavedTime, interval); - - dispatch_source_set_timer(saveTimer, startTime, interval, 1.0); - - if (saveTimerSuspended) - { - dispatch_resume(saveTimer); - saveTimerSuspended = NO; - } - } -} - -- (void)createSuspendedSaveTimer -{ - if ((saveTimer == NULL) && (saveInterval > 0.0)) - { - saveTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, loggerQueue); - - dispatch_source_set_event_handler(saveTimer, ^{ @autoreleasepool { - - [self performSaveAndSuspendSaveTimer]; - - }}); - - saveTimerSuspended = YES; - } -} - -- (void)destroyDeleteTimer -{ - if (deleteTimer) - { - dispatch_source_cancel(deleteTimer); - #if !OS_OBJECT_USE_OBJC - dispatch_release(deleteTimer); - #endif - deleteTimer = NULL; - } -} - -- (void)updateDeleteTimer -{ - if ((deleteTimer != NULL) && (deleteInterval > 0.0) && (maxAge > 0.0)) - { - uint64_t interval = (uint64_t)(deleteInterval * NSEC_PER_SEC); - dispatch_time_t startTime; - - if (lastDeleteTime > 0) - startTime = dispatch_time(lastDeleteTime, interval); - else - startTime = dispatch_time(DISPATCH_TIME_NOW, interval); - - dispatch_source_set_timer(deleteTimer, startTime, interval, 1.0); - } -} - -- (void)createAndStartDeleteTimer -{ - if ((deleteTimer == NULL) && (deleteInterval > 0.0) && (maxAge > 0.0)) - { - deleteTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, loggerQueue); - - if (deleteTimer != NULL) { - dispatch_source_set_event_handler(deleteTimer, ^{ @autoreleasepool { - - [self performDelete]; - - }}); - - [self updateDeleteTimer]; - - if (deleteTimer != NULL) dispatch_resume(deleteTimer); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Configuration -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (NSUInteger)saveThreshold -{ - // The design of this method is taken from the DDAbstractLogger implementation. - // For extensive documentation please refer to the DDAbstractLogger implementation. - - // Note: The internal implementation MUST access the colorsEnabled variable directly, - // This method is designed explicitly for external access. - // - // Using "self." syntax to go through this method will cause immediate deadlock. - // This is the intended result. Fix it by accessing the ivar directly. - // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster. - - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax."); - - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - - __block NSUInteger result; - - dispatch_sync(globalLoggingQueue, ^{ - dispatch_sync(loggerQueue, ^{ - result = saveThreshold; - }); - }); - - return result; -} - -- (void)setSaveThreshold:(NSUInteger)threshold -{ - dispatch_block_t block = ^{ @autoreleasepool { - - if (saveThreshold != threshold) - { - saveThreshold = threshold; - - // Since the saveThreshold has changed, - // we check to see if the current unsavedCount has surpassed the new threshold. - // - // If it has, we immediately save the log. - - if ((unsavedCount >= saveThreshold) && (saveThreshold > 0)) - { - [self performSaveAndSuspendSaveTimer]; - } - } - }}; - - // The design of the setter logic below is taken from the DDAbstractLogger implementation. - // For documentation please refer to the DDAbstractLogger implementation. - - if ([self isOnInternalLoggerQueue]) - { - block(); - } - else - { - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - - dispatch_async(globalLoggingQueue, ^{ - dispatch_async(loggerQueue, block); - }); - } -} - -- (NSTimeInterval)saveInterval -{ - // The design of this method is taken from the DDAbstractLogger implementation. - // For extensive documentation please refer to the DDAbstractLogger implementation. - - // Note: The internal implementation MUST access the colorsEnabled variable directly, - // This method is designed explicitly for external access. - // - // Using "self." syntax to go through this method will cause immediate deadlock. - // This is the intended result. Fix it by accessing the ivar directly. - // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster. - - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax."); - - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - - __block NSTimeInterval result; - - dispatch_sync(globalLoggingQueue, ^{ - dispatch_sync(loggerQueue, ^{ - result = saveInterval; - }); - }); - - return result; -} - -- (void)setSaveInterval:(NSTimeInterval)interval -{ - dispatch_block_t block = ^{ @autoreleasepool { - - // C99 recommended floating point comparison macro - // Read: isLessThanOrGreaterThan(floatA, floatB) - - if (/* saveInterval != interval */ islessgreater(saveInterval, interval)) - { - saveInterval = interval; - - // There are several cases we need to handle here. - // - // 1. If the saveInterval was previously enabled and it just got disabled, - // then we need to stop the saveTimer. (And we might as well release it.) - // - // 2. If the saveInterval was previously disabled and it just got enabled, - // then we need to setup the saveTimer. (Plus we might need to do an immediate save.) - // - // 3. If the saveInterval increased, then we need to reset the timer so that it fires at the later date. - // - // 4. If the saveInterval decreased, then we need to reset the timer so that it fires at an earlier date. - // (Plus we might need to do an immediate save.) - - if (saveInterval > 0.0) - { - if (saveTimer == NULL) - { - // Handles #2 - // - // Since the saveTimer uses the unsavedTime to calculate it's first fireDate, - // if a save is needed the timer will fire immediately. - - [self createSuspendedSaveTimer]; - [self updateAndResumeSaveTimer]; - } - else - { - // Handles #3 - // Handles #4 - // - // Since the saveTimer uses the unsavedTime to calculate it's first fireDate, - // if a save is needed the timer will fire immediately. - - [self updateAndResumeSaveTimer]; - } - } - else if (saveTimer) - { - // Handles #1 - - [self destroySaveTimer]; - } - } - }}; - - // The design of the setter logic below is taken from the DDAbstractLogger implementation. - // For documentation please refer to the DDAbstractLogger implementation. - - if ([self isOnInternalLoggerQueue]) - { - block(); - } - else - { - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - - dispatch_async(globalLoggingQueue, ^{ - dispatch_async(loggerQueue, block); - }); - } -} - -- (NSTimeInterval)maxAge -{ - // The design of this method is taken from the DDAbstractLogger implementation. - // For extensive documentation please refer to the DDAbstractLogger implementation. - - // Note: The internal implementation MUST access the colorsEnabled variable directly, - // This method is designed explicitly for external access. - // - // Using "self." syntax to go through this method will cause immediate deadlock. - // This is the intended result. Fix it by accessing the ivar directly. - // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster. - - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax."); - - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - - __block NSTimeInterval result; - - dispatch_sync(globalLoggingQueue, ^{ - dispatch_sync(loggerQueue, ^{ - result = maxAge; - }); - }); - - return result; -} - -- (void)setMaxAge:(NSTimeInterval)interval -{ - dispatch_block_t block = ^{ @autoreleasepool { - - // C99 recommended floating point comparison macro - // Read: isLessThanOrGreaterThan(floatA, floatB) - - if (/* maxAge != interval */ islessgreater(maxAge, interval)) - { - NSTimeInterval oldMaxAge = maxAge; - NSTimeInterval newMaxAge = interval; - - maxAge = interval; - - // There are several cases we need to handle here. - // - // 1. If the maxAge was previously enabled and it just got disabled, - // then we need to stop the deleteTimer. (And we might as well release it.) - // - // 2. If the maxAge was previously disabled and it just got enabled, - // then we need to setup the deleteTimer. (Plus we might need to do an immediate delete.) - // - // 3. If the maxAge was increased, - // then we don't need to do anything. - // - // 4. If the maxAge was decreased, - // then we should do an immediate delete. - - BOOL shouldDeleteNow = NO; - - if (oldMaxAge > 0.0) - { - if (newMaxAge <= 0.0) - { - // Handles #1 - - [self destroyDeleteTimer]; - } - else if (oldMaxAge > newMaxAge) - { - // Handles #4 - shouldDeleteNow = YES; - } - } - else if (newMaxAge > 0.0) - { - // Handles #2 - shouldDeleteNow = YES; - } - - if (shouldDeleteNow) - { - [self performDelete]; - - if (deleteTimer) - [self updateDeleteTimer]; - else - [self createAndStartDeleteTimer]; - } - } - }}; - - // The design of the setter logic below is taken from the DDAbstractLogger implementation. - // For documentation please refer to the DDAbstractLogger implementation. - - if ([self isOnInternalLoggerQueue]) - { - block(); - } - else - { - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - - dispatch_async(globalLoggingQueue, ^{ - dispatch_async(loggerQueue, block); - }); - } -} - -- (NSTimeInterval)deleteInterval -{ - // The design of this method is taken from the DDAbstractLogger implementation. - // For extensive documentation please refer to the DDAbstractLogger implementation. - - // Note: The internal implementation MUST access the colorsEnabled variable directly, - // This method is designed explicitly for external access. - // - // Using "self." syntax to go through this method will cause immediate deadlock. - // This is the intended result. Fix it by accessing the ivar directly. - // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster. - - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax."); - - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - - __block NSTimeInterval result; - - dispatch_sync(globalLoggingQueue, ^{ - dispatch_sync(loggerQueue, ^{ - result = deleteInterval; - }); - }); - - return result; -} - -- (void)setDeleteInterval:(NSTimeInterval)interval -{ - dispatch_block_t block = ^{ @autoreleasepool { - - // C99 recommended floating point comparison macro - // Read: isLessThanOrGreaterThan(floatA, floatB) - - if (/* deleteInterval != interval */ islessgreater(deleteInterval, interval)) - { - deleteInterval = interval; - - // There are several cases we need to handle here. - // - // 1. If the deleteInterval was previously enabled and it just got disabled, - // then we need to stop the deleteTimer. (And we might as well release it.) - // - // 2. If the deleteInterval was previously disabled and it just got enabled, - // then we need to setup the deleteTimer. (Plus we might need to do an immediate delete.) - // - // 3. If the deleteInterval increased, then we need to reset the timer so that it fires at the later date. - // - // 4. If the deleteInterval decreased, then we need to reset the timer so that it fires at an earlier date. - // (Plus we might need to do an immediate delete.) - - if (deleteInterval > 0.0) - { - if (deleteTimer == NULL) - { - // Handles #2 - // - // Since the deleteTimer uses the lastDeleteTime to calculate it's first fireDate, - // if a delete is needed the timer will fire immediately. - - [self createAndStartDeleteTimer]; - } - else - { - // Handles #3 - // Handles #4 - // - // Since the deleteTimer uses the lastDeleteTime to calculate it's first fireDate, - // if a save is needed the timer will fire immediately. - - [self updateDeleteTimer]; - } - } - else if (deleteTimer) - { - // Handles #1 - - [self destroyDeleteTimer]; - } - } - }}; - - // The design of the setter logic below is taken from the DDAbstractLogger implementation. - // For documentation please refer to the DDAbstractLogger implementation. - - if ([self isOnInternalLoggerQueue]) - { - block(); - } - else - { - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - - dispatch_async(globalLoggingQueue, ^{ - dispatch_async(loggerQueue, block); - }); - } -} - -- (BOOL)deleteOnEverySave -{ - // The design of this method is taken from the DDAbstractLogger implementation. - // For extensive documentation please refer to the DDAbstractLogger implementation. - - // Note: The internal implementation MUST access the colorsEnabled variable directly, - // This method is designed explicitly for external access. - // - // Using "self." syntax to go through this method will cause immediate deadlock. - // This is the intended result. Fix it by accessing the ivar directly. - // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster. - - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax."); - - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - - __block BOOL result; - - dispatch_sync(globalLoggingQueue, ^{ - dispatch_sync(loggerQueue, ^{ - result = deleteOnEverySave; - }); - }); - - return result; -} - -- (void)setDeleteOnEverySave:(BOOL)flag -{ - dispatch_block_t block = ^{ - - deleteOnEverySave = flag; - }; - - // The design of the setter logic below is taken from the DDAbstractLogger implementation. - // For documentation please refer to the DDAbstractLogger implementation. - - if ([self isOnInternalLoggerQueue]) - { - block(); - } - else - { - dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue]; - NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure"); - - dispatch_async(globalLoggingQueue, ^{ - dispatch_async(loggerQueue, block); - }); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Public API -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (void)savePendingLogEntries -{ - dispatch_block_t block = ^{ @autoreleasepool { - - [self performSaveAndSuspendSaveTimer]; - }}; - - if ([self isOnInternalLoggerQueue]) - block(); - else - dispatch_async(loggerQueue, block); -} - -- (void)deleteOldLogEntries -{ - dispatch_block_t block = ^{ @autoreleasepool { - - [self performDelete]; - }}; - - if ([self isOnInternalLoggerQueue]) - block(); - else - dispatch_async(loggerQueue, block); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark DDLogger -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -- (void)didAddLogger -{ - // If you override me be sure to invoke [super didAddLogger]; - - [self createSuspendedSaveTimer]; - - [self createAndStartDeleteTimer]; -} - -- (void)willRemoveLogger -{ - // If you override me be sure to invoke [super willRemoveLogger]; - - [self performSaveAndSuspendSaveTimer]; - - [self destroySaveTimer]; - [self destroyDeleteTimer]; -} - -- (void)logMessage:(DDLogMessage *)logMessage -{ - if ([self db_log:logMessage]) - { - BOOL firstUnsavedEntry = (++unsavedCount == 1); - - if ((unsavedCount >= saveThreshold) && (saveThreshold > 0)) - { - [self performSaveAndSuspendSaveTimer]; - } - else if (firstUnsavedEntry) - { - unsavedTime = dispatch_time(DISPATCH_TIME_NOW, 0); - [self updateAndResumeSaveTimer]; - } - } -} - -- (void)flush -{ - // This method is invoked by DDLog's flushLog method. - // - // It is called automatically when the application quits, - // or if the developer invokes DDLog's flushLog method prior to crashing or something. - - [self performSaveAndSuspendSaveTimer]; -} - -@end diff --git a/Vendor/CocoaLumberjack/DDFileLogger.h b/Vendor/CocoaLumberjack/DDFileLogger.h deleted file mode 100755 index e5f20dc58c..0000000000 --- a/Vendor/CocoaLumberjack/DDFileLogger.h +++ /dev/null @@ -1,369 +0,0 @@ -#import -#import "DDLog.h" - -@class DDLogFileInfo; - -/** - * Welcome to Cocoa Lumberjack! - * - * The project page has a wealth of documentation if you have any questions. - * https://github.com/CocoaLumberjack/CocoaLumberjack - * - * If you're new to the project you may wish to read the "Getting Started" wiki. - * https://github.com/CocoaLumberjack/CocoaLumberjack/wiki/GettingStarted - * - * - * This class provides a logger to write log statements to a file. -**/ - - -// Default configuration and safety/sanity values. -// -// maximumFileSize -> DEFAULT_LOG_MAX_FILE_SIZE -// rollingFrequency -> DEFAULT_LOG_ROLLING_FREQUENCY -// maximumNumberOfLogFiles -> DEFAULT_LOG_MAX_NUM_LOG_FILES -// -// You should carefully consider the proper configuration values for your application. - -#define DEFAULT_LOG_MAX_FILE_SIZE (1024 * 1024) // 1 MB -#define DEFAULT_LOG_ROLLING_FREQUENCY (60 * 60 * 24) // 24 Hours -#define DEFAULT_LOG_MAX_NUM_LOG_FILES (5) // 5 Files - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// The LogFileManager protocol is designed to allow you to control all aspects of your log files. -// -// The primary purpose of this is to allow you to do something with the log files after they have been rolled. -// Perhaps you want to compress them to save disk space. -// Perhaps you want to upload them to an FTP server. -// Perhaps you want to run some analytics on the file. -// -// A default LogFileManager is, of course, provided. -// The default LogFileManager simply deletes old log files according to the maximumNumberOfLogFiles property. -// -// This protocol provides various methods to fetch the list of log files. -// -// There are two variants: sorted and unsorted. -// If sorting is not necessary, the unsorted variant is obviously faster. -// The sorted variant will return an array sorted by when the log files were created, -// with the most recently created log file at index 0, and the oldest log file at the end of the array. -// -// You can fetch only the log file paths (full path including name), log file names (name only), -// or an array of DDLogFileInfo objects. -// The DDLogFileInfo class is documented below, and provides a handy wrapper that -// gives you easy access to various file attributes such as the creation date or the file size. - -@protocol DDLogFileManager -@required - -// Public properties - -/** - * The maximum number of archived log files to keep on disk. - * For example, if this property is set to 3, - * then the LogFileManager will only keep 3 archived log files (plus the current active log file) on disk. - * Once the active log file is rolled/archived, then the oldest of the existing 3 rolled/archived log files is deleted. - * - * You may optionally disable deleting old/rolled/archived log files by setting this property to zero. -**/ -@property (readwrite, assign) NSUInteger maximumNumberOfLogFiles; - -// Public methods - -- (NSString *)logsDirectory; - -- (NSArray *)unsortedLogFilePaths; -- (NSArray *)unsortedLogFileNames; -- (NSArray *)unsortedLogFileInfos; - -- (NSArray *)sortedLogFilePaths; -- (NSArray *)sortedLogFileNames; -- (NSArray *)sortedLogFileInfos; - -// Private methods (only to be used by DDFileLogger) - -- (NSString *)createNewLogFile; - -@optional - -// Notifications from DDFileLogger - -- (void)didArchiveLogFile:(NSString *)logFilePath; -- (void)didRollAndArchiveLogFile:(NSString *)logFilePath; - -@end - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Default log file manager. - * - * All log files are placed inside the logsDirectory. - * If a specific logsDirectory isn't specified, the default directory is used. - * On Mac, this is in ~/Library/Logs/. - * On iPhone, this is in ~/Library/Caches/Logs. - * - * Log files are named "