From 1c785c3cbf558baa6bab703efc0a5a010e8f3c6a Mon Sep 17 00:00:00 2001 From: Maximilian Szengel Date: Fri, 15 Nov 2013 15:49:18 +0100 Subject: [PATCH 01/16] Fix stream handling --- Core/Source/DTBonjourDataConnection.m | 97 +++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/Core/Source/DTBonjourDataConnection.m b/Core/Source/DTBonjourDataConnection.m index 1a0a423..0a37fa2 100644 --- a/Core/Source/DTBonjourDataConnection.m +++ b/Core/Source/DTBonjourDataConnection.m @@ -14,6 +14,83 @@ NSString * DTBonjourDataConnectionErrorDomain = @"DTBonjourDataConnection"; +@interface NSNetService (QNetworkAdditions) + +- (BOOL)qNetworkAdditions_getInputStream:(out NSInputStream **)inputStreamPtr + outputStream:(out NSOutputStream **)outputStreamPtr; + +@end + +@implementation NSNetService (QNetworkAdditions) + +- (BOOL)qNetworkAdditions_getInputStream:(out NSInputStream **)inputStreamPtr + outputStream:(out NSOutputStream **)outputStreamPtr + // The following works around three problems with + // -[NSNetService getInputStream:outputStream:]: + // + // o -- Currently the returns the streams with + // +1 retain count, which is counter to Cocoa conventions and results in + // leaks when you use it in ARC code. + // + // o -- If you create two pairs of streams from + // one NSNetService and then attempt to open all the streams simultaneously, + // some of the streams might fail to open. + // + // o -- If you create streams using + // -[NSNetService getInputStream:outputStream:], start to open them, and + // then release the last reference to the original NSNetService, the + // streams never finish opening. This problem is exacerbated under ARC + // because ARC is better about keeping things out of the autorelease pool. +{ + BOOL result; + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + + result = NO; + + readStream = NULL; + writeStream = NULL; + + if ( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) ) { + CFNetServiceRef netService; + + netService = CFNetServiceCreate( + NULL, + (__bridge CFStringRef) [self domain], + (__bridge CFStringRef) [self type], + (__bridge CFStringRef) [self name], + 0 + ); + if (netService != NULL) { + CFStreamCreatePairWithSocketToNetService( + NULL, + netService, + ((inputStreamPtr != nil) ? &readStream : NULL), + ((outputStreamPtr != nil) ? &writeStream : NULL) + ); + CFRelease(netService); + } + + // We have failed if the client requested an input stream and didn't + // get one, or requested an output stream and didn't get one. We also + // fail if the client requested neither the input nor the output + // stream, but we don't get here in that case. + + result = ! ((( inputStreamPtr != NULL) && ( readStream == NULL)) || + ((outputStreamPtr != NULL) && (writeStream == NULL))); + } + if (inputStreamPtr != NULL) { + *inputStreamPtr = CFBridgingRelease(readStream); + } + if (outputStreamPtr != NULL) { + *outputStreamPtr = CFBridgingRelease(writeStream); + } + + return result; +} + +@end + @interface DTBonjourDataConnection () @end @@ -82,11 +159,14 @@ - (id)initWithService:(NSNetService *)service if (self) { - if (![service getInputStream:&_inputStream outputStream:&_outputStream]) + NSInputStream *in; + NSOutputStream *out; + if (![service qNetworkAdditions_getInputStream:&in outputStream:&out]) { return nil; } - + _inputStream = in; + _outputStream = out; _outputQueue = [[NSMutableArray alloc] init]; } @@ -207,7 +287,7 @@ - (void)_startOutput } } - NSUInteger writtenBytes = [chunk writeToOutputStream:_outputStream]; + NSInteger writtenBytes = [chunk writeToOutputStream:_outputStream]; if (writtenBytes > 0) { @@ -252,12 +332,13 @@ - (BOOL)sendObject:(id)object error:(NSError **)error return NO; } - DTBonjourDataChunk *newChunk = [[DTBonjourDataChunk alloc] initWithObject:object encoding:self.sendingContentType error:error]; + DTBonjourDataChunk *newChunk = [[DTBonjourDataChunk alloc] + initWithObject:object + encoding:self.sendingContentType + error:error]; if (!newChunk) - { return NO; - } newChunk.sequenceNumber = _chunkSequenceNumber; @@ -267,7 +348,9 @@ - (BOOL)sendObject:(id)object error:(NSError **)error if (queueWasEmpty && _outputStream.streamStatus == NSStreamStatusOpen) { - [self _startOutput]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self _startOutput]; + }); } return YES; From 8f677cf7a202e480707ee9ba4a89522718398640 Mon Sep 17 00:00:00 2001 From: Maximilian Szengel Date: Tue, 19 Nov 2013 10:40:14 +0100 Subject: [PATCH 02/16] Add timeout to connection opening --- Core/Source/DTBonjourDataConnection.h | 11 ++++- Core/Source/DTBonjourDataConnection.m | 65 ++++++++++++--------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Core/Source/DTBonjourDataConnection.h b/Core/Source/DTBonjourDataConnection.h index 3903970..e9029e6 100644 --- a/Core/Source/DTBonjourDataConnection.h +++ b/Core/Source/DTBonjourDataConnection.h @@ -19,6 +19,7 @@ typedef enum } DTBonjourDataConnectionContentType; extern NSString * DTBonjourDataConnectionErrorDomain; +extern CGFloat DTBonjourDataConnectionDefaultTimeout; @class DTBonjourDataConnection, DTBonjourDataChunk; @@ -130,11 +131,19 @@ extern NSString * DTBonjourDataConnectionErrorDomain; */ /** - Opens the connection and establishes the input and output streams. + Opens the connection and establishes the input and output streams. Cancels the + opening after a timeout of `DTBonjourDataConnectionDefaultTimeout` seconds. @returns `YES` if the connection could be established. */ - (BOOL)open; +/** + Opens the connection and establishes the input and output streams. + @param timeout Timeout in seconds after which to cancel the stream opening. + @returns `YES` if the connection could be established. + */ +- (BOOL)openWithTimeout:(CGFloat)timeout; + /** Closes the connection */ diff --git a/Core/Source/DTBonjourDataConnection.m b/Core/Source/DTBonjourDataConnection.m index 0a37fa2..fe73eae 100644 --- a/Core/Source/DTBonjourDataConnection.m +++ b/Core/Source/DTBonjourDataConnection.m @@ -12,6 +12,7 @@ #import +CGFloat DTBonjourDataConnectionDefaultTimeout = 60.0; NSString * DTBonjourDataConnectionErrorDomain = @"DTBonjourDataConnection"; @interface NSNetService (QNetworkAdditions) @@ -193,7 +194,7 @@ - (void)dealloc [self close]; } -- (BOOL)open +- (BOOL)openWithTimeout:(CGFloat)timeout { [_inputStream setDelegate:self]; [_outputStream setDelegate:self]; @@ -202,9 +203,24 @@ - (BOOL)open [_inputStream open]; [_outputStream open]; + __weak id weakSelf = self; + double delayInSeconds = timeout; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + // No connection after timeout, closing. + if (![weakSelf isOpen]) { + [weakSelf close]; + } + }); + return YES; } +- (BOOL)open +{ + return [self openWithTimeout:DTBonjourDataConnectionDefaultTimeout]; +} + - (void)close { if (!_inputStream&&!_outputStream) @@ -222,50 +238,23 @@ - (void)close _outputStream = nil; if ([_delegate respondsToSelector:@selector(connectionDidClose:)]) - { [_delegate connectionDidClose:self]; - } } - (BOOL)isOpen { if (!_inputStream) - { return NO; - } NSStreamStatus inputStatus = [_inputStream streamStatus]; - - switch (inputStatus) - { - case NSStreamStatusNotOpen: - case NSStreamStatusAtEnd: - case NSStreamStatusClosed: - case NSStreamStatusError: - { - return NO; - } - - default: - break; - } - - NSStreamStatus outputStatus = [_outputStream streamStatus]; - - switch (outputStatus) - { - case NSStreamStatusNotOpen: - case NSStreamStatusAtEnd: - case NSStreamStatusClosed: - case NSStreamStatusError: - { - return NO; - } - - default: - break; - } - + NSStreamStatus outputStatus = [_outputStream streamStatus]; + + if (NSStreamStatusOpen != inputStatus) + return NO; + + if (NSStreamStatusOpen != outputStatus) + return NO; + return YES; } @@ -278,7 +267,7 @@ - (void)_startOutput DTBonjourDataChunk *chunk = _outputQueue[0]; - if (chunk.numberOfTransferredBytes==0) + if (0 == chunk.numberOfTransferredBytes) { // nothing sent yet if ([_delegate respondsToSelector:@selector(connection:willStartSendingChunk:)]) @@ -424,6 +413,8 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent case NSStreamEventErrorOccurred: { NSLog(@"Error occurred: %@", [aStream.streamError localizedDescription]); + + // Intentional fall-through. } case NSStreamEventEndEncountered: From 367bf5c65fe9c8b225f71347ff1761a19ba6b17c Mon Sep 17 00:00:00 2001 From: Maximilian Szengel Date: Tue, 19 Nov 2013 16:57:41 +0100 Subject: [PATCH 03/16] Remove outdated NSNetService workaround --- Core/Source/DTBonjourDataConnection.m | 79 +-------------------------- 1 file changed, 1 insertion(+), 78 deletions(-) diff --git a/Core/Source/DTBonjourDataConnection.m b/Core/Source/DTBonjourDataConnection.m index fe73eae..0cf9b46 100644 --- a/Core/Source/DTBonjourDataConnection.m +++ b/Core/Source/DTBonjourDataConnection.m @@ -15,83 +15,6 @@ CGFloat DTBonjourDataConnectionDefaultTimeout = 60.0; NSString * DTBonjourDataConnectionErrorDomain = @"DTBonjourDataConnection"; -@interface NSNetService (QNetworkAdditions) - -- (BOOL)qNetworkAdditions_getInputStream:(out NSInputStream **)inputStreamPtr - outputStream:(out NSOutputStream **)outputStreamPtr; - -@end - -@implementation NSNetService (QNetworkAdditions) - -- (BOOL)qNetworkAdditions_getInputStream:(out NSInputStream **)inputStreamPtr - outputStream:(out NSOutputStream **)outputStreamPtr - // The following works around three problems with - // -[NSNetService getInputStream:outputStream:]: - // - // o -- Currently the returns the streams with - // +1 retain count, which is counter to Cocoa conventions and results in - // leaks when you use it in ARC code. - // - // o -- If you create two pairs of streams from - // one NSNetService and then attempt to open all the streams simultaneously, - // some of the streams might fail to open. - // - // o -- If you create streams using - // -[NSNetService getInputStream:outputStream:], start to open them, and - // then release the last reference to the original NSNetService, the - // streams never finish opening. This problem is exacerbated under ARC - // because ARC is better about keeping things out of the autorelease pool. -{ - BOOL result; - CFReadStreamRef readStream; - CFWriteStreamRef writeStream; - - result = NO; - - readStream = NULL; - writeStream = NULL; - - if ( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) ) { - CFNetServiceRef netService; - - netService = CFNetServiceCreate( - NULL, - (__bridge CFStringRef) [self domain], - (__bridge CFStringRef) [self type], - (__bridge CFStringRef) [self name], - 0 - ); - if (netService != NULL) { - CFStreamCreatePairWithSocketToNetService( - NULL, - netService, - ((inputStreamPtr != nil) ? &readStream : NULL), - ((outputStreamPtr != nil) ? &writeStream : NULL) - ); - CFRelease(netService); - } - - // We have failed if the client requested an input stream and didn't - // get one, or requested an output stream and didn't get one. We also - // fail if the client requested neither the input nor the output - // stream, but we don't get here in that case. - - result = ! ((( inputStreamPtr != NULL) && ( readStream == NULL)) || - ((outputStreamPtr != NULL) && (writeStream == NULL))); - } - if (inputStreamPtr != NULL) { - *inputStreamPtr = CFBridgingRelease(readStream); - } - if (outputStreamPtr != NULL) { - *outputStreamPtr = CFBridgingRelease(writeStream); - } - - return result; -} - -@end - @interface DTBonjourDataConnection () @end @@ -162,7 +85,7 @@ - (id)initWithService:(NSNetService *)service { NSInputStream *in; NSOutputStream *out; - if (![service qNetworkAdditions_getInputStream:&in outputStream:&out]) + if (![service getInputStream:&in outputStream:&out]) { return nil; } From e2f84b59125ed2dcbf6faaeae5032bf8081cbb52 Mon Sep 17 00:00:00 2001 From: Maximilian Szengel Date: Tue, 19 Nov 2013 17:07:57 +0100 Subject: [PATCH 04/16] Fix type warning --- Core/Source/DTBonjourDataChunk.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Source/DTBonjourDataChunk.m b/Core/Source/DTBonjourDataChunk.m index 971df76..2a4445b 100644 --- a/Core/Source/DTBonjourDataChunk.m +++ b/Core/Source/DTBonjourDataChunk.m @@ -251,7 +251,7 @@ - (void)_decodeHeader */ _sequenceNumber = [headers[@"Sequence-Number:"] unsignedIntegerValue]; - _contentLength = [headers[@"Content-Length"] longLongValue]; + _contentLength = [[[NSNumberFormatter new] numberFromString:headers[@"Content-Length"]] unsignedIntegerValue]; _totalBytes = _rangeOfHeader.length + _contentLength; } From a85c6ea12e23acc9548046a442d85f3f9f9df569 Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 15:31:57 +0100 Subject: [PATCH 05/16] Updated comments for appledoc-support for enums --- AppledocSettings.plist | 11 +---------- Core/Source/DTBonjourDataConnection.h | 11 +++++++++-- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/AppledocSettings.plist b/AppledocSettings.plist index 85d2e84..0605578 100644 --- a/AppledocSettings.plist +++ b/AppledocSettings.plist @@ -37,16 +37,7 @@ Demo --index-desc - Readme.markdown - --include - - ./Documentation/Setup Guide-template.markdown - ./Documentation/Known Issues-template.markdown - ./Documentation/DTCoreText_Demo_App.png - ./Documentation/DTCoreText_Linker_Flags.png - ./Documentation/DTCoreText_Search_Paths.png - ./Documentation/DTCoreText_Reference.png - + readme.markdown --warn-invalid-crossref diff --git a/Core/Source/DTBonjourDataConnection.h b/Core/Source/DTBonjourDataConnection.h index 2ae0e47..e488718 100644 --- a/Core/Source/DTBonjourDataConnection.h +++ b/Core/Source/DTBonjourDataConnection.h @@ -12,11 +12,18 @@ /** Type of encoding to use for sending objects */ -typedef enum +NS_ENUM(NSUInteger, DTBonjourDataConnectionContentType) { + /** + Encode sent objects with NSCoding + */ DTBonjourDataConnectionContentTypeNSCoding = 0, + + /** + Encode sent objects as JSON. Note that not all kinds of Objective-C objects can be represented as JSON. + */ DTBonjourDataConnectionContentTypeJSON, -} DTBonjourDataConnectionContentType; +}; extern NSString * DTBonjourDataConnectionErrorDomain; From 59bc7922ccb92e41eaa7fe41ebf882dc340d44c4 Mon Sep 17 00:00:00 2001 From: Maximilian Szengel Date: Wed, 18 Dec 2013 16:27:18 +0100 Subject: [PATCH 06/16] Re-add NSNetService patch with a runtime check for >=iOS7/OSX10.9. --- Core/Source/DTBonjourDataConnection.m | 100 ++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/Core/Source/DTBonjourDataConnection.m b/Core/Source/DTBonjourDataConnection.m index 0cf9b46..c615ae1 100644 --- a/Core/Source/DTBonjourDataConnection.m +++ b/Core/Source/DTBonjourDataConnection.m @@ -12,9 +12,88 @@ #import +#define kDTBonjourQNetworkAdditionsCheckSEL NSSelectorFromString(@"netService:didAcceptConnectionWithInputStream:outputStream:") + CGFloat DTBonjourDataConnectionDefaultTimeout = 60.0; NSString * DTBonjourDataConnectionErrorDomain = @"DTBonjourDataConnection"; +@interface NSNetService (QNetworkAdditions) + +- (BOOL)qNetworkAdditions_getInputStream:(out NSInputStream **)inputStreamPtr + outputStream:(out NSOutputStream **)outputStreamPtr; + +@end + +@implementation NSNetService (QNetworkAdditions) + +- (BOOL)qNetworkAdditions_getInputStream:(out NSInputStream **)inputStreamPtr + outputStream:(out NSOutputStream **)outputStreamPtr + // The following works around three problems with + // -[NSNetService getInputStream:outputStream:]: + // + // o -- Currently the returns the streams with + // +1 retain count, which is counter to Cocoa conventions and results in + // leaks when you use it in ARC code. + // + // o -- If you create two pairs of streams from + // one NSNetService and then attempt to open all the streams simultaneously, + // some of the streams might fail to open. + // + // o -- If you create streams using + // -[NSNetService getInputStream:outputStream:], start to open them, and + // then release the last reference to the original NSNetService, the + // streams never finish opening. This problem is exacerbated under ARC + // because ARC is better about keeping things out of the autorelease pool. +{ + BOOL result; + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + + result = NO; + + readStream = NULL; + writeStream = NULL; + + if ( (inputStreamPtr != NULL) || (outputStreamPtr != NULL) ) { + CFNetServiceRef netService; + + netService = CFNetServiceCreate( + NULL, + (__bridge CFStringRef) [self domain], + (__bridge CFStringRef) [self type], + (__bridge CFStringRef) [self name], + 0 + ); + if (netService != NULL) { + CFStreamCreatePairWithSocketToNetService( + NULL, + netService, + ((inputStreamPtr != nil) ? &readStream : NULL), + ((outputStreamPtr != nil) ? &writeStream : NULL) + ); + CFRelease(netService); + } + + // We have failed if the client requested an input stream and didn't + // get one, or requested an output stream and didn't get one. We also + // fail if the client requested neither the input nor the output + // stream, but we don't get here in that case. + + result = ! ((( inputStreamPtr != NULL) && ( readStream == NULL)) || + ((outputStreamPtr != NULL) && (writeStream == NULL))); + } + if (inputStreamPtr != NULL) { + *inputStreamPtr = CFBridgingRelease(readStream); + } + if (outputStreamPtr != NULL) { + *outputStreamPtr = CFBridgingRelease(writeStream); + } + + return result; +} + +@end + @interface DTBonjourDataConnection () @end @@ -85,10 +164,23 @@ - (id)initWithService:(NSNetService *)service { NSInputStream *in; NSOutputStream *out; - if (![service getInputStream:&in outputStream:&out]) - { - return nil; - } + + if (![[service delegate] respondsToSelector:kDTBonjourQNetworkAdditionsCheckSEL]) + { + // Older iOS/OSX versions need a patch for getting input and output + // streams see the `QNetworkAdditions` above. (If the delegate does not + // implement the `kDTBonjourQNetworkAdditionsCheck` selector, we can + // simply use the patched version. + if ([service qNetworkAdditions_getInputStream:&in outputStream:&out]) + return nil; + } + else + { + // iOS7/OSX10.9 + if (![service getInputStream:&in outputStream:&out]) + return nil; + } + _inputStream = in; _outputStream = out; _outputQueue = [[NSMutableArray alloc] init]; From 16fa9c817ab3b7ef038f03df026e1522fa544b07 Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 17:37:20 +0100 Subject: [PATCH 07/16] Setup for Travis-CI building --- .travis.yml | 13 ++++ .../xcschemes/DTBonjour (OS X).xcscheme | 59 +++++++++++++++++++ .../xcschemes/DTBonjour (iOS).xcscheme | 59 +++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 .travis.yml create mode 100644 DTBonjour.xcodeproj/xcshareddata/xcschemes/DTBonjour (OS X).xcscheme create mode 100644 DTBonjour.xcodeproj/xcshareddata/xcschemes/DTBonjour (iOS).xcscheme diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..eaafd24 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +--- +language: objective-c + +before_script: + - sudo easy_install cpp-coveralls + +script: + - xctool project DTBonjour.xcodeproj -scheme "DTBonjour (iOS)" build -sdk iphonesimulator6.1 -arch i386 ONLY_ACTIVE_ARCH=NO + - xctool project DTBonjour.xcodeproj -scheme "DTBonjour (OS X)" build -arch x86_64 ONLY_ACTIVE_ARCH=NO + - appledoc -o /tmp . + +after_success: + - ./coveralls.rb --extension m --exclude-folder Demo --exclude-folder Test --exclude-folder Externals diff --git a/DTBonjour.xcodeproj/xcshareddata/xcschemes/DTBonjour (OS X).xcscheme b/DTBonjour.xcodeproj/xcshareddata/xcschemes/DTBonjour (OS X).xcscheme new file mode 100644 index 0000000..48d1e16 --- /dev/null +++ b/DTBonjour.xcodeproj/xcshareddata/xcschemes/DTBonjour (OS X).xcscheme @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DTBonjour.xcodeproj/xcshareddata/xcschemes/DTBonjour (iOS).xcscheme b/DTBonjour.xcodeproj/xcshareddata/xcschemes/DTBonjour (iOS).xcscheme new file mode 100644 index 0000000..1a543a1 --- /dev/null +++ b/DTBonjour.xcodeproj/xcshareddata/xcschemes/DTBonjour (iOS).xcscheme @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From a800b63e0cbdbfe3f4b7481ba7994aca6b63b3fe Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 17:37:36 +0100 Subject: [PATCH 08/16] Fixed improperly removed typedef --- Core/Source/DTBonjourDataConnection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Source/DTBonjourDataConnection.h b/Core/Source/DTBonjourDataConnection.h index 2a22156..fb54e77 100644 --- a/Core/Source/DTBonjourDataConnection.h +++ b/Core/Source/DTBonjourDataConnection.h @@ -12,7 +12,7 @@ /** Type of encoding to use for sending objects */ -NS_ENUM(NSUInteger, DTBonjourDataConnectionContentType) +typedef NS_ENUM(NSUInteger, DTBonjourDataConnectionContentType) { /** Encode sent objects with NSCoding From a70ef962e3f12dea2090b561bbc65568f9e7402a Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 17:40:43 +0100 Subject: [PATCH 09/16] Fixed typecast warning --- Core/Source/DTBonjourDataChunk.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Source/DTBonjourDataChunk.m b/Core/Source/DTBonjourDataChunk.m index 2a4445b..6d45c18 100644 --- a/Core/Source/DTBonjourDataChunk.m +++ b/Core/Source/DTBonjourDataChunk.m @@ -123,7 +123,7 @@ - (BOOL)_encodeObject:(id)object error:(NSError **)error { if (error) { - NSString *errorMsg = [NSString stringWithFormat:@"Unknown encoding type %d", _encoding]; + NSString *errorMsg = [NSString stringWithFormat:@"Unknown encoding type %lu", _encoding]; NSDictionary *userInfo = @{NSLocalizedDescriptionKey:errorMsg}; *error = [NSError errorWithDomain:DTBonjourDataConnectionErrorDomain code:1 userInfo:userInfo]; } From 9a2ddc5b1a1d93f43f1ce00818209f82bb2a8aac Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 17:42:07 +0100 Subject: [PATCH 10/16] Fixed missing protocol docs --- Core/Source/DTBonjourDataConnection.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/Source/DTBonjourDataConnection.h b/Core/Source/DTBonjourDataConnection.h index fb54e77..07eb3e8 100644 --- a/Core/Source/DTBonjourDataConnection.h +++ b/Core/Source/DTBonjourDataConnection.h @@ -30,7 +30,12 @@ extern CGFloat DTBonjourDataConnectionDefaultTimeout; @class DTBonjourDataConnection, DTBonjourDataChunk; + +/** + Protocol to inform delegate of a DTBonjourDataConnection about what is happening + */ @protocol DTBonjourDataConnectionDelegate + @optional // sending From 1f5149f8c20a30b1ecd51e6cc5de16eb370412a3 Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 17:44:47 +0100 Subject: [PATCH 11/16] fixed warning --- Core/Source/DTBonjourDataChunk.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Source/DTBonjourDataChunk.m b/Core/Source/DTBonjourDataChunk.m index 6d45c18..e706ee4 100644 --- a/Core/Source/DTBonjourDataChunk.m +++ b/Core/Source/DTBonjourDataChunk.m @@ -123,7 +123,7 @@ - (BOOL)_encodeObject:(id)object error:(NSError **)error { if (error) { - NSString *errorMsg = [NSString stringWithFormat:@"Unknown encoding type %lu", _encoding]; + NSString *errorMsg = [NSString stringWithFormat:@"Unknown encoding type %d", (int)_encoding]; NSDictionary *userInfo = @{NSLocalizedDescriptionKey:errorMsg}; *error = [NSError errorWithDomain:DTBonjourDataConnectionErrorDomain code:1 userInfo:userInfo]; } From a58e69d09e05ac2ee0b4f7ff176b7f2d72653924 Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 17:47:17 +0100 Subject: [PATCH 12/16] Added coveralls script --- coveralls.rb | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100755 coveralls.rb diff --git a/coveralls.rb b/coveralls.rb new file mode 100755 index 0000000..e182aab --- /dev/null +++ b/coveralls.rb @@ -0,0 +1,136 @@ +#!/usr/bin/env ruby + +require 'etc' +require 'fileutils' +require 'find' +require 'optparse' + +# arraw of source subfolders to exclude +excludedFolders = [] +extensionsToProcess = [] +coveralls_cmd = "coveralls" + +excludeHeaders = false + +# create option parser +opts = OptionParser.new +opts.banner = "Usage: coveralls.rb [options]" + +opts.on('-e', '--exclude-folder FOLDER', 'Folder to exclude') do |v| + excludedFolders << v + coveralls_cmd.concat(" -e #{v}") +end + +opts.on('-h', '--exclude-headers', 'Ignores headers') do |v| + excludeHeaders = true +end + +opts.on('-x', '--extension EXT', 'Source file extension to process') do |v| + extensionsToProcess << v + coveralls_cmd.concat(" -x #{v}") +end + +opts.on_tail("-?", "--help", "Show this message") do + puts opts + exit +end + +# parse the options +begin + opts.parse!(ARGV) +rescue OptionParser::InvalidOption => e + puts e + puts opts + exit(1) +end + +# the folders +workingDir = Dir.getwd +derivedDataDir = "#{Etc.getpwuid.dir}/Library/Developer/Xcode/DerivedData/" +outputDir = workingDir + "/gcov" + +# create gcov output folder +FileUtils.mkdir outputDir + +# pattern to get source file from first line of gcov file +GCOV_SOURCE_PATTERN = Regexp.new(/Source:(.*)/) + +# enumerate all gcda files underneath derivedData +Find.find(derivedDataDir) do |gcda_file| + + if gcda_file.match(/\.gcda\Z/) + + #get just the folder name + gcov_dir = File.dirname(gcda_file) + + # cut off absolute working dir to get relative source path + relative_input_path = gcda_file.slice(derivedDataDir.length, gcda_file.length) + puts "\nINPUT: #{relative_input_path}" + + #process the file + result = %x( gcov '#{gcda_file}' -o '#{gcov_dir}' ) + + # filter the resulting output + Dir.glob("*.gcov") do |gcov_file| + + firstLine = File.open(gcov_file).readline + match = GCOV_SOURCE_PATTERN.match(firstLine) + + if (match) + + source_path = match[1] + + puts "source: #{source_path} - #{workingDir}" + + if (source_path.start_with? workingDir) + + # cut off absolute working dir to get relative source path + relative_path = source_path.slice(workingDir.length+1, source_path.length) + + extension = File.extname(relative_path) + extension = extension.slice(1, extension.length-1) + + puts "#{extension}" + + # get the path components + path_comps = relative_path.split(File::SEPARATOR) + + shouldProcess = false + exclusionMsg ="" + + if (excludedFolders.include?(path_comps[0])) + exclusionMsg = "excluded via option" + else + if (excludeHeaders == true && extension == 'h') + exclusionMsg = "excluded header" + else + if (extensionsToProcess.count == 0 || extensionsToProcess.include?(extension)) + shouldProcess = true + else + exclusionMsg = "excluded extension" + shouldProcess = false + end + end + end + + if (shouldProcess) + puts " - process: #{relative_path}" + FileUtils.mv(gcov_file, outputDir) + else + puts " - ignore: #{relative_path} (#{exclusionMsg})" + FileUtils.rm gcov_file + end + else + puts " - ignore: #{gcov_file} (outside source folder)" + FileUtils.rm gcov_file + end + end + end + end +end + +#call the coveralls, exclude some files +system coveralls_cmd + +#clean up +FileUtils.rm_rf outputDir From 6b26a197a01a2dfb74021a04e18283fc99b815e4 Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 17:51:08 +0100 Subject: [PATCH 13/16] Added Travis and Coveralls badges --- readme.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readme.markdown b/readme.markdown index 63f9e31..bfe3c4d 100644 --- a/readme.markdown +++ b/readme.markdown @@ -1,6 +1,8 @@ About DTBonjour ================== +[![Build Status](https://travis-ci.org/Cocoanetics/DTBonjour.png?branch=develop)](https://travis-ci.org/Cocoanetics/DTFoundation) [![Coverage Status](https://coveralls.io/repos/Cocoanetics/DTFoundation/badge.png?branch=develop)](https://coveralls.io/r/Cocoanetics/DTFoundation?branch=develop) + DTBonjour had its origin when I wanted communicate between a Mac app and an iOS app. It greatly simplifies networking over WiFi by giving you an easy method to transmit any NSObject that conforms to NSCoding. Documentation From 31654ea293061714d7111d428c06c45b5353946d Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 17:52:04 +0100 Subject: [PATCH 14/16] fixed links --- readme.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.markdown b/readme.markdown index bfe3c4d..032a84b 100644 --- a/readme.markdown +++ b/readme.markdown @@ -1,7 +1,7 @@ About DTBonjour ================== -[![Build Status](https://travis-ci.org/Cocoanetics/DTBonjour.png?branch=develop)](https://travis-ci.org/Cocoanetics/DTFoundation) [![Coverage Status](https://coveralls.io/repos/Cocoanetics/DTFoundation/badge.png?branch=develop)](https://coveralls.io/r/Cocoanetics/DTFoundation?branch=develop) +[![Build Status](https://travis-ci.org/Cocoanetics/DTBonjour.png?branch=develop)](https://travis-ci.org/Cocoanetics/DTFoundation) [![Coverage Status](https://coveralls.io/repos/Cocoanetics/DTFoundation/badge.png?branch=develop)](https://coveralls.io/r/Cocoanetics/DTBonjour?branch=develop) DTBonjour had its origin when I wanted communicate between a Mac app and an iOS app. It greatly simplifies networking over WiFi by giving you an easy method to transmit any NSObject that conforms to NSCoding. From 3e7045c07d8e60f0926d6f7466d9eae9645df341 Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 18:10:49 +0100 Subject: [PATCH 15/16] Added change log, enabled arm64 building --- DTBonjour.xcodeproj/project.pbxproj | 2 ++ Documentation/Change Log-template.markdown | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 Documentation/Change Log-template.markdown diff --git a/DTBonjour.xcodeproj/project.pbxproj b/DTBonjour.xcodeproj/project.pbxproj index 336a13c..a66e993 100644 --- a/DTBonjour.xcodeproj/project.pbxproj +++ b/DTBonjour.xcodeproj/project.pbxproj @@ -330,6 +330,7 @@ A719022816A7F5E300C1EC52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; DSTROOT = /tmp/DTBonjour.dst; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Core/DTBonjour-Prefix.pch"; @@ -340,6 +341,7 @@ A719022916A7F5E300C1EC52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; DSTROOT = /tmp/DTBonjour.dst; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Core/DTBonjour-Prefix.pch"; diff --git a/Documentation/Change Log-template.markdown b/Documentation/Change Log-template.markdown new file mode 100644 index 0000000..bbff6a8 --- /dev/null +++ b/Documentation/Change Log-template.markdown @@ -0,0 +1,17 @@ +Change Log +========== + +This is the history of version updates. + +**Version 1.1.0** + +- FIXED: Various type warnings +- ADDED: New method on DTBonjourDataConnection which allows specifying a timeout +- ADDED: Delegate method for when connection was opened +- ADDED: arm64 support +- CHANGED: Updated for building with Xcode 5 +- CHANGED: Use original NSNetService method to get connection where workaround no longer necessary + +**Version 1.0.0** + +Initial release \ No newline at end of file From f34f70dd9b5d7b2fe1d3385ab105f8e707f775ca Mon Sep 17 00:00:00 2001 From: Oliver Drobnik Date: Wed, 18 Dec 2013 18:11:07 +0100 Subject: [PATCH 16/16] Updated appledoc settings and podspec --- AppledocSettings.plist | 4 ++++ DTBonjour.podspec | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/AppledocSettings.plist b/AppledocSettings.plist index 0605578..05430d2 100644 --- a/AppledocSettings.plist +++ b/AppledocSettings.plist @@ -30,6 +30,10 @@ --no-repeat-first-par + --include + + ./Documentation/Change Log-template.markdown + --ignore *.m diff --git a/DTBonjour.podspec b/DTBonjour.podspec index 39415a5..5c230c7 100644 --- a/DTBonjour.podspec +++ b/DTBonjour.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'DTBonjour' - spec.version = '1.0.0' + spec.version = '1.1.0' spec.summary = "Client/Server Communication of NSObjects over WiFi." spec.homepage = "https://github.com/Cocoanetics/DTBonjour" spec.author = { "Oliver Drobnik" => "oliver@drobnik.com" }