* Added MYBonjourBrowser and MYBonjourService.
* Added MYPortMapper.
* Added -[TCPEndpoint setPeerToPeerIdentity:].
* Created a static-library target.
1.1 --- a/BLIP/BLIP.h Tue Dec 02 22:42:56 2008 -0800
1.2 +++ b/BLIP/BLIP.h Wed Apr 22 16:45:39 2009 -0700
1.3 @@ -3,7 +3,7 @@
1.4 // MYNetwork
1.5 //
1.6 // Created by Jens Alfke on 5/24/08.
1.7 -// Copyright 2008 __MyCompanyName__. All rights reserved.
1.8 +// Copyright 2008 Jens Alfke. All rights reserved.
1.9 //
1.10
1.11 #import "BLIPConnection.h"
2.1 --- a/BLIP/BLIPConnection.h Tue Dec 02 22:42:56 2008 -0800
2.2 +++ b/BLIP/BLIPConnection.h Wed Apr 22 16:45:39 2009 -0700
2.3 @@ -19,6 +19,7 @@
2.4 Most of the API is inherited from TCPConnection. */
2.5 @interface BLIPConnection : TCPConnection
2.6 {
2.7 + @private
2.8 BLIPDispatcher *_dispatcher;
2.9 BOOL _blipClosing;
2.10 }
3.1 --- a/BLIP/BLIPDispatcher.h Tue Dec 02 22:42:56 2008 -0800
3.2 +++ b/BLIP/BLIPDispatcher.h Wed Apr 22 16:45:39 2009 -0700
3.3 @@ -25,6 +25,7 @@
3.4 request based on property values. */
3.5 @interface BLIPDispatcher : NSObject
3.6 {
3.7 + @private
3.8 NSMutableArray *_predicates, *_targets;
3.9 BLIPDispatcher *_parent;
3.10 }
4.1 --- a/BLIP/BLIPMessage.h Tue Dec 02 22:42:56 2008 -0800
4.2 +++ b/BLIP/BLIPMessage.h Wed Apr 22 16:45:39 2009 -0700
4.3 @@ -36,6 +36,7 @@
4.4 /** Abstract superclass for <a href=".#blipdesc">BLIP</a> requests and responses. */
4.5 @interface BLIPMessage : NSObject
4.6 {
4.7 + @protected
4.8 BLIPConnection *_connection;
4.9 UInt16 _flags;
4.10 UInt32 _number;
5.1 --- a/BLIP/BLIPProperties.h Tue Dec 02 22:42:56 2008 -0800
5.2 +++ b/BLIP/BLIPProperties.h Wed Apr 22 16:45:39 2009 -0700
5.3 @@ -45,6 +45,7 @@
5.4 /** Mutable subclass of BLIPProperties, used for creating new instances. */
5.5 @interface BLIPMutableProperties : BLIPProperties
5.6 {
5.7 + @private
5.8 NSMutableDictionary *_properties;
5.9 }
5.10
6.1 --- a/BLIP/BLIPProperties.m Tue Dec 02 22:42:56 2008 -0800
6.2 +++ b/BLIP/BLIPProperties.m Wed Apr 22 16:45:39 2009 -0700
6.3 @@ -69,7 +69,7 @@
6.4 else
6.5 props = [BLIPProperties properties];
6.6
6.7 - *usedLength = props ?length :-1;
6.8 + *usedLength = props ?(ssize_t)length :-1;
6.9 return props;
6.10 }
6.11
6.12 @@ -132,7 +132,7 @@
6.13 goto fail;
6.14
6.15 // The data consists of consecutive NUL-terminated strings, alternating key/value:
6.16 - unsigned capacity = 0;
6.17 + int capacity = 0;
6.18 const char *end = bytes+length;
6.19 for( const char *str=bytes; str < end; str += strlen(str)+1, _nStrings++ ) {
6.20 if( _nStrings >= capacity ) {
6.21 @@ -285,7 +285,7 @@
6.22 static void appendStr( NSMutableData *data, NSString *str ) {
6.23 const char *utf8 = [str UTF8String];
6.24 size_t size = strlen(utf8)+1;
6.25 - for( int i=0; i<kNAbbreviations; i++ )
6.26 + for( unsigned i=0; i<kNAbbreviations; i++ )
6.27 if( memcmp(utf8,kAbbreviations[i],size)==0 ) {
6.28 const UInt8 abbrev[2] = {i+1,0};
6.29 [data appendBytes: &abbrev length: 2];
6.30 @@ -345,7 +345,7 @@
6.31
6.32 props = [BLIPProperties properties];
6.33 CAssert(props);
6.34 - CAssertEq(props.count,0);
6.35 + CAssertEq(props.count,0U);
6.36 Log(@"Empty properties:\n%@", props.allProperties);
6.37 NSData *data = props.encodedData;
6.38 Log(@"As data: %@", data);
6.39 @@ -359,7 +359,7 @@
6.40
6.41 ssize_t used;
6.42 props = [BLIPProperties propertiesWithEncodedData: data usedLength: &used];
6.43 - CAssertEq(used,data.length);
6.44 + CAssertEq(used,(ssize_t)data.length);
6.45 CAssertEqual(props,mprops);
6.46
6.47 [mprops setValue: @"Jens" ofProperty: @"First-Name"];
6.48 @@ -377,7 +377,7 @@
6.49 CAssertEq(used,0);
6.50 }
6.51 props = [BLIPProperties propertiesWithEncodedData: data usedLength: &used];
6.52 - CAssertEq(used,data.length);
6.53 + CAssertEq(used,(ssize_t)data.length);
6.54 Log(@"Read back in:\n%@",props.allProperties);
6.55 CAssertEqual(props,mprops);
6.56
7.1 --- a/BLIP/BLIPReader.h Tue Dec 02 22:42:56 2008 -0800
7.2 +++ b/BLIP/BLIPReader.h Wed Apr 22 16:45:39 2009 -0700
7.3 @@ -14,6 +14,7 @@
7.4 /** INTERNAL class that reads BLIP frames from the socket. */
7.5 @interface BLIPReader : TCPReader
7.6 {
7.7 + @private
7.8 BLIPFrameHeader _curHeader;
7.9 UInt32 _curBytesRead;
7.10 NSMutableData *_curBody;
8.1 --- a/BLIP/BLIPTest.m Tue Dec 02 22:42:56 2008 -0800
8.2 +++ b/BLIP/BLIPTest.m Wed Apr 22 16:45:39 2009 -0700
8.3 @@ -19,10 +19,13 @@
8.4 #import "Logging.h"
8.5 #import "Test.h"
8.6
8.7 -#define HAVE_KEYCHAIN_FRAMEWORK 0
8.8 -#if HAVE_KEYCHAIN_FRAMEWORK
8.9 -#import <Keychain/Keychain.h>
8.10 -#endif
8.11 +#import <Security/Security.h>
8.12 +#import <SecurityInterface/SFChooseIdentityPanel.h>
8.13 +
8.14 +@interface TCPEndpoint ()
8.15 ++ (NSString*) describeCert: (SecCertificateRef)cert;
8.16 ++ (NSString*) describeIdentity: (SecIdentityRef)identity;
8.17 +@end
8.18
8.19
8.20 #define kListenerHost @"localhost"
8.21 @@ -31,20 +34,41 @@
8.22 #define kNBatchedMessages 20
8.23 #define kUseCompression YES
8.24 #define kUrgentEvery 4
8.25 -#define kClientRequiresSSL NO
8.26 -#define kClientUsesSSLCert NO
8.27 -#define kListenerRequiresSSL NO
8.28 -#define kListenerRequiresClientCert NO
8.29 #define kListenerCloseAfter 50
8.30 #define kClientAcceptCloseRequest YES
8.31
8.32 +#define kListenerUsesSSL YES // Does the listener (server) use an SSL connection?
8.33 +#define kListenerRequiresClientCert YES // Does the listener require clients to have an SSL cert?
8.34 +#define kClientRequiresSSL YES // Does the client require the listener to use SSL?
8.35 +#define kClientUsesSSLCert YES // Does the client use an SSL cert?
8.36 +
8.37 +
8.38 +static SecIdentityRef ChooseIdentity( NSString *prompt ) {
8.39 + NSMutableArray *identities = [NSMutableArray array];
8.40 + SecKeychainRef kc;
8.41 + SecKeychainCopyDefault(&kc);
8.42 + SecIdentitySearchRef search;
8.43 + SecIdentitySearchCreate(kc, CSSM_KEYUSE_ANY, &search);
8.44 + SecIdentityRef identity;
8.45 + while (SecIdentitySearchCopyNext(search, &identity) == noErr)
8.46 + [identities addObject: (id)identity];
8.47 + Log(@"Found %u identities -- prompting '%@'", identities.count, prompt);
8.48 + if (identities.count > 0) {
8.49 + SFChooseIdentityPanel *panel = [SFChooseIdentityPanel sharedChooseIdentityPanel];
8.50 + if ([panel runModalForIdentities: identities message: prompt] == NSOKButton) {
8.51 + Log(@"Using SSL identity: %@", panel.identity);
8.52 + return panel.identity;
8.53 + }
8.54 + }
8.55 + return NULL;
8.56 +}
8.57
8.58 static SecIdentityRef GetClientIdentity(void) {
8.59 - return NULL; // Make this return a valid identity to test client-side certs
8.60 + return ChooseIdentity(@"Choose an identity for the BLIP Client Test:");
8.61 }
8.62
8.63 static SecIdentityRef GetListenerIdentity(void) {
8.64 - return NULL; // Make this return a valid identity to test client-side certs
8.65 + return ChooseIdentity(@"Choose an identity for the BLIP Listener Test:");
8.66 }
8.67
8.68
8.69 @@ -75,15 +99,11 @@
8.70 [self release];
8.71 return nil;
8.72 }
8.73 - if( kClientRequiresSSL ) {
8.74 - _conn.SSLProperties = $mdict({kTCPPropertySSLAllowsAnyRoot, $true});
8.75 - if( kClientUsesSSLCert ) {
8.76 - SecIdentityRef clientIdentity = GetClientIdentity();
8.77 - if( clientIdentity ) {
8.78 - [_conn setSSLProperty: $array((id)clientIdentity)
8.79 - forKey: kTCPPropertySSLCertificates];
8.80 - }
8.81 - }
8.82 + if( kClientUsesSSLCert ) {
8.83 + [_conn setPeerToPeerIdentity: GetClientIdentity()];
8.84 + } else if( kClientRequiresSSL ) {
8.85 + _conn.SSLProperties = $mdict({kTCPPropertySSLAllowsAnyRoot, $true},
8.86 + {(id)kCFStreamSSLPeerName, [NSNull null]});
8.87 }
8.88 _conn.delegate = self;
8.89 Log(@"** Opening connection...");
8.90 @@ -148,22 +168,20 @@
8.91 }
8.92 - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert
8.93 {
8.94 -#if HAVE_KEYCHAIN_FRAMEWORK
8.95 - Certificate *cert = peerCert ?[Certificate certificateWithCertificateRef: peerCert] :nil;
8.96 - Log(@"** %@ authorizeSSLPeer: %@",self,cert);
8.97 -#else
8.98 - Log(@"** %@ authorizeSSLPeer: %@",self,peerCert);
8.99 -#endif
8.100 + Log(@"** %@ authorizeSSLPeer: %@",self, [TCPEndpoint describeCert:peerCert]);
8.101 return peerCert != nil;
8.102 }
8.103 - (void) connection: (TCPConnection*)connection failedToOpen: (NSError*)error
8.104 {
8.105 - Log(@"** %@ failedToOpen: %@",connection,error);
8.106 + Warn(@"** %@ failedToOpen: %@",connection,error);
8.107 CFRunLoopStop(CFRunLoopGetCurrent());
8.108 }
8.109 - (void) connectionDidClose: (TCPConnection*)connection
8.110 {
8.111 - Log(@"** %@ didClose",connection);
8.112 + if (connection.error)
8.113 + Warn(@"** %@ didClose: %@", connection,connection.error);
8.114 + else
8.115 + Log(@"** %@ didClose", connection);
8.116 setObj(&_conn,nil);
8.117 [NSObject cancelPreviousPerformRequestsWithTarget: self];
8.118 CFRunLoopStop(CFRunLoopGetCurrent());
8.119 @@ -188,7 +206,7 @@
8.120 const UInt8 *bytes = body.bytes;
8.121 for( size_t i=0; i<size; i++ )
8.122 AssertEq(bytes[i],i % 256);
8.123 - AssertEq(size,sizeObj.intValue);
8.124 + AssertEq(size,sizeObj.unsignedIntValue);
8.125 }
8.126 Assert(sizeObj);
8.127 [_pending removeObjectForKey: $object(response.number)];
8.128 @@ -207,9 +225,7 @@
8.129
8.130
8.131 TestCase(BLIPConnection) {
8.132 -#if HAVE_KEYCHAIN_FRAMEWORK
8.133 - [Keychain setUserInteractionAllowed: YES];
8.134 -#endif
8.135 + SecKeychainSetUserInteractionAllowed(true);
8.136 BLIPConnectionTester *tester = [[BLIPConnectionTester alloc] init];
8.137 CAssert(tester);
8.138
8.139 @@ -244,12 +260,11 @@
8.140 _listener.delegate = self;
8.141 _listener.pickAvailablePort = YES;
8.142 _listener.bonjourServiceType = @"_bliptest._tcp";
8.143 - if( kListenerRequiresSSL ) {
8.144 - SecIdentityRef listenerIdentity = GetListenerIdentity();
8.145 - Assert(listenerIdentity);
8.146 - _listener.SSLProperties = $mdict({kTCPPropertySSLCertificates, $array((id)listenerIdentity)},
8.147 - {kTCPPropertySSLAllowsAnyRoot,$true},
8.148 - {kTCPPropertySSLClientSideAuthentication, $object(kTCPTryAuthenticate)});
8.149 + if( kListenerUsesSSL ) {
8.150 + [_listener setPeerToPeerIdentity: GetListenerIdentity()];
8.151 + if (!kListenerRequiresClientCert)
8.152 + [_listener setSSLProperty: $object(kTCPTryAuthenticate)
8.153 + forKey: kTCPPropertySSLClientSideAuthentication];
8.154 }
8.155 Assert( [_listener open] );
8.156 Log(@"%@ is listening...",self);
8.157 @@ -293,12 +308,7 @@
8.158 }
8.159 - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert
8.160 {
8.161 -#if HAVE_KEYCHAIN_FRAMEWORK
8.162 - Certificate *cert = peerCert ?[Certificate certificateWithCertificateRef: peerCert] :nil;
8.163 - Log(@"** %@ authorizeSSLPeer: %@",connection,cert);
8.164 -#else
8.165 - Log(@"** %@ authorizeSSLPeer: %@",self,peerCert);
8.166 -#endif
8.167 + Log(@"** %@ authorizeSSLPeer: %@",self, [TCPEndpoint describeCert:peerCert]);
8.168 return peerCert != nil || ! kListenerRequiresClientCert;
8.169 }
8.170 - (void) connection: (TCPConnection*)connection failedToOpen: (NSError*)error
8.171 @@ -307,7 +317,10 @@
8.172 }
8.173 - (void) connectionDidClose: (TCPConnection*)connection
8.174 {
8.175 - Log(@"** %@ didClose",connection);
8.176 + if (connection.error)
8.177 + Warn(@"** %@ didClose: %@", connection,connection.error);
8.178 + else
8.179 + Log(@"** %@ didClose", connection);
8.180 [connection release];
8.181 }
8.182 - (void) connection: (BLIPConnection*)connection receivedRequest: (BLIPRequest*)request
8.183 @@ -322,7 +335,7 @@
8.184
8.185 AssertEqual([request valueOfProperty: @"Content-Type"], @"application/octet-stream");
8.186 Assert([request valueOfProperty: @"User-Agent"] != nil);
8.187 - AssertEq([[request valueOfProperty: @"Size"] intValue], size);
8.188 + AssertEq((size_t)[[request valueOfProperty: @"Size"] intValue], size);
8.189
8.190 [request respondWithData: body contentType: request.contentType];
8.191
8.192 @@ -351,9 +364,7 @@
8.193 EnableLogTo(BLIP,YES);
8.194 EnableLogTo(PortMapper,YES);
8.195 EnableLogTo(Bonjour,YES);
8.196 -#if HAVE_KEYCHAIN_FRAMEWORK
8.197 - [Keychain setUserInteractionAllowed: YES];
8.198 -#endif
8.199 + SecKeychainSetUserInteractionAllowed(true);
8.200 BLIPTestListener *listener = [[BLIPTestListener alloc] init];
8.201
8.202 [[NSRunLoop currentRunLoop] run];
9.1 --- a/BLIP/BLIPWriter.h Tue Dec 02 22:42:56 2008 -0800
9.2 +++ b/BLIP/BLIPWriter.h Wed Apr 22 16:45:39 2009 -0700
9.3 @@ -10,8 +10,10 @@
9.4 @class BLIPRequest, BLIPResponse, BLIPMessage;
9.5
9.6
9.7 +/** INTERNAL class that sends BLIP frames over the socket. */
9.8 @interface BLIPWriter : TCPWriter
9.9 {
9.10 + @private
9.11 NSMutableArray *_outBox;
9.12 UInt32 _numRequestsSent;
9.13 }
10.1 --- a/BLIP/Demo/BLIP Echo Client-Info.plist Tue Dec 02 22:42:56 2008 -0800
10.2 +++ b/BLIP/Demo/BLIP Echo Client-Info.plist Wed Apr 22 16:45:39 2009 -0700
10.3 @@ -7,7 +7,7 @@
10.4 <key>CFBundleExecutable</key>
10.5 <string>${EXECUTABLE_NAME}</string>
10.6 <key>CFBundleIdentifier</key>
10.7 - <string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
10.8 + <string>com.mooseyard.BLIPEchoClient</string>
10.9 <key>CFBundleInfoDictionaryVersion</key>
10.10 <string>6.0</string>
10.11 <key>CFBundlePackageType</key>
11.1 --- a/BLIP/Demo/BLIPEchoClient.h Tue Dec 02 22:42:56 2008 -0800
11.2 +++ b/BLIP/Demo/BLIPEchoClient.h Wed Apr 22 16:45:39 2009 -0700
11.3 @@ -9,23 +9,24 @@
11.4 //
11.5
11.6 #import <Cocoa/Cocoa.h>
11.7 -@class BLIPConnection;
11.8 +#import "BLIPConnection.h"
11.9 +@class MYBonjourBrowser;
11.10
11.11
11.12 -@interface BLIPEchoClient : NSObject
11.13 +@interface BLIPEchoClient : NSObject <BLIPConnectionDelegate>
11.14 {
11.15 IBOutlet NSTextField * inputField;
11.16 IBOutlet NSTextField * responseField;
11.17 IBOutlet NSTableView * serverTableView;
11.18
11.19 - NSNetServiceBrowser * _serviceBrowser;
11.20 - NSMutableArray * _serviceList;
11.21 -
11.22 + MYBonjourBrowser * _serviceBrowser;
11.23 BLIPConnection *_connection;
11.24 }
11.25
11.26 -@property (readonly) NSMutableArray *serviceList;
11.27 +@property (readonly) MYBonjourBrowser *serviceBrowser;
11.28 +@property (readonly) NSArray *serviceList;
11.29
11.30 +- (IBAction)serverClicked:(id)sender;
11.31 - (IBAction)sendText:(id)sender;
11.32
11.33 @end
12.1 --- a/BLIP/Demo/BLIPEchoClient.m Tue Dec 02 22:42:56 2008 -0800
12.2 +++ b/BLIP/Demo/BLIPEchoClient.m Wed Apr 22 16:45:39 2009 -0700
12.3 @@ -9,44 +9,36 @@
12.4 //
12.5
12.6 #import "BLIPEchoClient.h"
12.7 -#import "BLIP.h"
12.8 +#import "MYBonjourBrowser.h"
12.9 +#import "MYBonjourService.h"
12.10 +#import "CollectionUtils.h"
12.11 +#import "MYNetwork.h"
12.12 #import "Target.h"
12.13
12.14
12.15 @implementation BLIPEchoClient
12.16
12.17 -@synthesize serviceList=_serviceList;
12.18
12.19 - (void)awakeFromNib
12.20 {
12.21 - _serviceBrowser = [[NSNetServiceBrowser alloc] init];
12.22 - _serviceList = [[NSMutableArray alloc] init];
12.23 - [_serviceBrowser setDelegate:self];
12.24 -
12.25 - [_serviceBrowser searchForServicesOfType:@"_blipecho._tcp." inDomain:@""];
12.26 + [self.serviceBrowser start];
12.27 }
12.28
12.29 -#pragma mark -
12.30 -#pragma mark NSNetServiceBrowser delegate methods
12.31 -
12.32 -// We broadcast the willChangeValueForKey: and didChangeValueForKey: for the NSTableView binding to work.
12.33 -
12.34 -- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing {
12.35 - if (![_serviceList containsObject:aNetService]) {
12.36 - [self willChangeValueForKey:@"serviceList"];
12.37 - [_serviceList addObject:aNetService];
12.38 - [self didChangeValueForKey:@"serviceList"];
12.39 - }
12.40 +- (MYBonjourBrowser*) serviceBrowser {
12.41 + if (!_serviceBrowser)
12.42 + _serviceBrowser = [[MYBonjourBrowser alloc] initWithServiceType: @"_blipecho._tcp."];
12.43 + return _serviceBrowser;
12.44 }
12.45
12.46 -- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService *)aNetService moreComing:(BOOL)moreComing {
12.47 - if ([_serviceList containsObject:aNetService]) {
12.48 - [self willChangeValueForKey:@"serviceList"];
12.49 - [_serviceList removeObject:aNetService];
12.50 - [self didChangeValueForKey:@"serviceList"];
12.51 - }
12.52 +- (NSArray*) serviceList {
12.53 + return [_serviceBrowser.services.allObjects sortedArrayUsingSelector: @selector(compare:)];
12.54 }
12.55
12.56 ++ (NSArray*) keyPathsForValuesAffectingServiceList {
12.57 + return $array(@"serviceBrowser.services");
12.58 +}
12.59 +
12.60 +
12.61 #pragma mark -
12.62 #pragma mark BLIPConnection support
12.63
12.64 @@ -54,9 +46,10 @@
12.65 - (void)openConnection: (NSNetService*)service
12.66 {
12.67 _connection = [[BLIPConnection alloc] initToNetService: service];
12.68 - if( _connection )
12.69 + if( _connection ) {
12.70 + _connection.delegate = self;
12.71 [_connection open];
12.72 - else
12.73 + } else
12.74 NSBeep();
12.75 }
12.76
12.77 @@ -64,10 +57,35 @@
12.78 - (void)closeConnection
12.79 {
12.80 [_connection close];
12.81 - [_connection release];
12.82 - _connection = nil;
12.83 }
12.84
12.85 +/** Called after the connection successfully opens. */
12.86 +- (void) connectionDidOpen: (TCPConnection*)connection {
12.87 + if (connection==_connection) {
12.88 + [inputField setEnabled: YES];
12.89 + [responseField setEnabled: YES];
12.90 + [inputField.window makeFirstResponder: inputField];
12.91 + }
12.92 +}
12.93 +
12.94 +/** Called after the connection fails to open due to an error. */
12.95 +- (void) connection: (TCPConnection*)connection failedToOpen: (NSError*)error {
12.96 + [serverTableView.window presentError: error];
12.97 +}
12.98 +
12.99 +/** Called after the connection closes. */
12.100 +- (void) connectionDidClose: (TCPConnection*)connection {
12.101 + if (connection==_connection) {
12.102 + if (connection.error)
12.103 + [serverTableView.window presentError: connection.error];
12.104 + [_connection release];
12.105 + _connection = nil;
12.106 + [inputField setEnabled: NO];
12.107 + [responseField setEnabled: NO];
12.108 + }
12.109 +}
12.110 +
12.111 +
12.112 #pragma mark -
12.113 #pragma mark GUI action methods
12.114
12.115 @@ -77,7 +95,7 @@
12.116
12.117 [self closeConnection];
12.118 if (-1 != selectedRow)
12.119 - [self openConnection: [_serviceList objectAtIndex:selectedRow]];
12.120 + [self openConnection: [[self.serviceList objectAtIndex:selectedRow] netService]];
12.121 }
12.122
12.123 /* Send a BLIP request containing the string in the textfield */
12.124 @@ -86,7 +104,11 @@
12.125 BLIPRequest *r = [_connection request];
12.126 r.bodyString = [sender stringValue];
12.127 BLIPResponse *response = [r send];
12.128 - response.onComplete = $target(self,gotResponse:);
12.129 + if (response) {
12.130 + response.onComplete = $target(self,gotResponse:);
12.131 + [inputField setStringValue: @""];
12.132 + } else
12.133 + NSBeep();
12.134 }
12.135
12.136 /* Receive the response to the BLIP request, and put its contents into the response field */
12.137 @@ -100,5 +122,6 @@
12.138
12.139 int main(int argc, char *argv[])
12.140 {
12.141 + //RunTestCases(argc,(const char**)argv);
12.142 return NSApplicationMain(argc, (const char **) argv);
12.143 }
13.1 --- a/BLIP/Demo/BLIPEchoClient.xib Tue Dec 02 22:42:56 2008 -0800
13.2 +++ b/BLIP/Demo/BLIPEchoClient.xib Wed Apr 22 16:45:39 2009 -0700
13.3 @@ -1,20 +1,29 @@
13.4 <?xml version="1.0" encoding="UTF-8"?>
13.5 -<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02">
13.6 +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
13.7 <data>
13.8 <int key="IBDocument.SystemTarget">1050</int>
13.9 - <string key="IBDocument.SystemVersion">9C7010</string>
13.10 - <string key="IBDocument.InterfaceBuilderVersion">658</string>
13.11 - <string key="IBDocument.AppKitVersion">949.26</string>
13.12 - <string key="IBDocument.HIToolboxVersion">352.00</string>
13.13 + <string key="IBDocument.SystemVersion">9G55</string>
13.14 + <string key="IBDocument.InterfaceBuilderVersion">677</string>
13.15 + <string key="IBDocument.AppKitVersion">949.43</string>
13.16 + <string key="IBDocument.HIToolboxVersion">353.00</string>
13.17 <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
13.18 <bool key="EncodedWithXMLCoder">YES</bool>
13.19 - <integer value="21"/>
13.20 <integer value="29"/>
13.21 + <integer value="2"/>
13.22 </object>
13.23 <object class="NSArray" key="IBDocument.PluginDependencies">
13.24 <bool key="EncodedWithXMLCoder">YES</bool>
13.25 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.26 </object>
13.27 + <object class="NSMutableDictionary" key="IBDocument.Metadata">
13.28 + <bool key="EncodedWithXMLCoder">YES</bool>
13.29 + <object class="NSArray" key="dict.sortedKeys">
13.30 + <bool key="EncodedWithXMLCoder">YES</bool>
13.31 + </object>
13.32 + <object class="NSMutableArray" key="dict.values">
13.33 + <bool key="EncodedWithXMLCoder">YES</bool>
13.34 + </object>
13.35 + </object>
13.36 <object class="NSMutableArray" key="IBDocument.RootObjects" id="81650750">
13.37 <bool key="EncodedWithXMLCoder">YES</bool>
13.38 <object class="NSCustomObject" id="568359733">
13.39 @@ -38,6 +47,7 @@
13.40 <object class="NSMutableString" key="NSViewClass">
13.41 <characters key="NS.bytes">View</characters>
13.42 </object>
13.43 + <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
13.44 <string key="NSWindowContentMinSize">{213, 107}</string>
13.45 <object class="NSView" key="NSWindowView" id="707481179">
13.46 <reference key="NSNextResponder"/>
13.47 @@ -217,7 +227,7 @@
13.48 <reference key="NSSuperview" ref="707481179"/>
13.49 <bool key="NSEnabled">YES</bool>
13.50 <object class="NSTextFieldCell" key="NSCell" id="364162739">
13.51 - <int key="NSCellFlags">-1804468671</int>
13.52 + <int key="NSCellFlags">-1267597759</int>
13.53 <int key="NSCellFlags2">272630784</int>
13.54 <string key="NSContents"/>
13.55 <reference key="NSSupport" ref="343719836"/>
13.56 @@ -244,7 +254,7 @@
13.57 <reference key="NSSuperview" ref="707481179"/>
13.58 <bool key="NSEnabled">YES</bool>
13.59 <object class="NSTextFieldCell" key="NSCell" id="617761818">
13.60 - <int key="NSCellFlags">-2072904127</int>
13.61 + <int key="NSCellFlags">-1536033215</int>
13.62 <int key="NSCellFlags2">272630784</int>
13.63 <string key="NSContents"/>
13.64 <reference key="NSSupport" ref="343719836"/>
13.65 @@ -1880,7 +1890,6 @@
13.66 <string>208.IBPluginDependency</string>
13.67 <string>208.ImportedFromIB2</string>
13.68 <string>21.IBEditorWindowLastContentRect</string>
13.69 - <string>21.IBPluginDependency</string>
13.70 <string>21.IBWindowTemplateEditedContentRect</string>
13.71 <string>21.ImportedFromIB2</string>
13.72 <string>21.NSWindowTemplate.visibleAtLaunch</string>
13.73 @@ -1894,11 +1903,18 @@
13.74 <string>213.ImportedFromIB2</string>
13.75 <string>214.IBPluginDependency</string>
13.76 <string>214.ImportedFromIB2</string>
13.77 + <string>228.IBPluginDependency</string>
13.78 + <string>229.IBPluginDependency</string>
13.79 <string>23.IBPluginDependency</string>
13.80 <string>23.ImportedFromIB2</string>
13.81 + <string>230.IBPluginDependency</string>
13.82 + <string>231.IBPluginDependency</string>
13.83 <string>231.IBShouldRemoveOnLegacySave</string>
13.84 + <string>232.IBPluginDependency</string>
13.85 <string>232.IBShouldRemoveOnLegacySave</string>
13.86 + <string>233.IBPluginDependency</string>
13.87 <string>233.IBShouldRemoveOnLegacySave</string>
13.88 + <string>234.IBPluginDependency</string>
13.89 <string>234.IBShouldRemoveOnLegacySave</string>
13.90 <string>24.IBPluginDependency</string>
13.91 <string>24.ImportedFromIB2</string>
13.92 @@ -2040,9 +2056,8 @@
13.93 <reference ref="5"/>
13.94 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.95 <reference ref="5"/>
13.96 - <string>{{108, 555}, {529, 256}}</string>
13.97 - <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.98 - <string>{{108, 555}, {529, 256}}</string>
13.99 + <string>{{82, 548}, {529, 256}}</string>
13.100 + <string>{{82, 548}, {529, 256}}</string>
13.101 <reference ref="5"/>
13.102 <reference ref="5"/>
13.103 <reference ref="5"/>
13.104 @@ -2056,10 +2071,17 @@
13.105 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.106 <reference ref="5"/>
13.107 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.108 + <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.109 + <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.110 <reference ref="5"/>
13.111 + <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.112 + <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.113 <reference ref="5"/>
13.114 + <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.115 <reference ref="5"/>
13.116 + <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.117 <reference ref="5"/>
13.118 + <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.119 <reference ref="5"/>
13.120 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
13.121 <reference ref="5"/>
13.122 @@ -2129,8 +2151,17 @@
13.123 <string key="className">BLIPEchoClient</string>
13.124 <string key="superclassName">NSObject</string>
13.125 <object class="NSMutableDictionary" key="actions">
13.126 - <string key="NS.key.0">sendText:</string>
13.127 - <string key="NS.object.0">id</string>
13.128 + <bool key="EncodedWithXMLCoder">YES</bool>
13.129 + <object class="NSMutableArray" key="dict.sortedKeys">
13.130 + <bool key="EncodedWithXMLCoder">YES</bool>
13.131 + <string>sendText:</string>
13.132 + <string>serverClicked:</string>
13.133 + </object>
13.134 + <object class="NSMutableArray" key="dict.values">
13.135 + <bool key="EncodedWithXMLCoder">YES</bool>
13.136 + <string>id</string>
13.137 + <string>id</string>
13.138 + </object>
13.139 </object>
13.140 <object class="NSMutableDictionary" key="outlets">
13.141 <bool key="EncodedWithXMLCoder">YES</bool>
13.142 @@ -2162,6 +2193,7 @@
13.143 </object>
13.144 <object class="IBPartialClassDescription">
13.145 <string key="className">FirstResponder</string>
13.146 + <string key="superclassName">NSObject</string>
13.147 <object class="IBClassDescriptionSource" key="sourceIdentifier">
13.148 <string key="majorKey">IBUserSource</string>
13.149 <string key="minorKey"/>
13.150 @@ -2170,7 +2202,7 @@
13.151 </object>
13.152 </object>
13.153 <int key="IBDocument.localizationMode">0</int>
13.154 - <nil key="IBDocument.LastKnownRelativeProjectPath"/>
13.155 + <string key="IBDocument.LastKnownRelativeProjectPath">../../MYNetwork.xcodeproj</string>
13.156 <int key="IBDocument.defaultPropertyAccessControl">3</int>
13.157 </data>
13.158 </archive>
14.1 --- a/BLIP/Demo/BLIPEchoServer.m Tue Dec 02 22:42:56 2008 -0800
14.2 +++ b/BLIP/Demo/BLIPEchoServer.m Wed Apr 22 16:45:39 2009 -0700
14.3 @@ -7,7 +7,7 @@
14.4 //
14.5
14.6 #import "BLIPEchoServer.h"
14.7 -#import "BLIP.h"
14.8 +#import "MYNetwork.h"
14.9
14.10
14.11 @implementation BLIPEchoServer
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/Bonjour/MYBonjourBrowser.h Wed Apr 22 16:45:39 2009 -0700
15.3 @@ -0,0 +1,52 @@
15.4 +//
15.5 +// MYBonjourBrowser.h
15.6 +// MYNetwork
15.7 +//
15.8 +// Created by Jens Alfke on 1/22/08.
15.9 +// Copyright 2008 Jens Alfke. All rights reserved.
15.10 +//
15.11 +
15.12 +#import <Foundation/Foundation.h>
15.13 +
15.14 +
15.15 +/** Searches for Bonjour services of a specific type. */
15.16 +@interface MYBonjourBrowser : NSObject
15.17 +{
15.18 + @private
15.19 + NSString *_serviceType;
15.20 + NSNetServiceBrowser *_browser;
15.21 + BOOL _browsing;
15.22 + NSError *_error;
15.23 + Class _serviceClass;
15.24 + NSMutableSet *_services, *_addServices, *_rmvServices;
15.25 +}
15.26 +
15.27 +/** Initializes a new BonjourBrowser.
15.28 + Call -start to begin browsing.
15.29 + @param serviceType The name of the service type to look for, e.g. "_http._tcp". */
15.30 +- (id) initWithServiceType: (NSString*)serviceType;
15.31 +
15.32 +/** Starts browsing. This is asynchronous, so nothing will happen immediately. */
15.33 +- (void) start;
15.34 +
15.35 +/** Stops browsing. */
15.36 +- (void) stop;
15.37 +
15.38 +/** Is the browser currently browsing? */
15.39 +@property (readonly) BOOL browsing;
15.40 +
15.41 +/** The current error status, if any.
15.42 + This is KV-observable. */
15.43 +@property (readonly,retain) NSError* error;
15.44 +
15.45 +/** The set of currently found services. These are instances of the serviceClass,
15.46 + which is BonjourService by default.
15.47 + This is KV-observable. */
15.48 +@property (readonly) NSSet *services;
15.49 +
15.50 +/** The class of objects to create to represent services.
15.51 + The default value is [BonjourService class]; you can change this, but only
15.52 + to a subclass of that. */
15.53 +@property Class serviceClass;
15.54 +
15.55 +@end
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/Bonjour/MYBonjourBrowser.m Wed Apr 22 16:45:39 2009 -0700
16.3 @@ -0,0 +1,239 @@
16.4 +//
16.5 +// MYBonjourBrowser.m
16.6 +// MYNetwork
16.7 +//
16.8 +// Created by Jens Alfke on 1/22/08.
16.9 +// Copyright 2008 Jens Alfke. All rights reserved.
16.10 +//
16.11 +
16.12 +#import "MYBonjourBrowser.h"
16.13 +#import "MYBonjourService.h"
16.14 +#import "Test.h"
16.15 +#import "Logging.h"
16.16 +
16.17 +
16.18 +@interface MYBonjourBrowser ()
16.19 +@property BOOL browsing;
16.20 +@property (retain) NSError* error;
16.21 +@end
16.22 +
16.23 +
16.24 +@implementation MYBonjourBrowser
16.25 +
16.26 +
16.27 +- (id) initWithServiceType: (NSString*)serviceType
16.28 +{
16.29 + Assert(serviceType);
16.30 + self = [super init];
16.31 + if (self != nil) {
16.32 + _serviceType = [serviceType copy];
16.33 + _browser = [[NSNetServiceBrowser alloc] init];
16.34 + _browser.delegate = self;
16.35 + _services = [[NSMutableSet alloc] init];
16.36 + _addServices = [[NSMutableSet alloc] init];
16.37 + _rmvServices = [[NSMutableSet alloc] init];
16.38 + _serviceClass = [MYBonjourService class];
16.39 + }
16.40 + return self;
16.41 +}
16.42 +
16.43 +
16.44 +- (void) dealloc
16.45 +{
16.46 + LogTo(Bonjour,@"DEALLOC BonjourBrowser");
16.47 + [_browser stop];
16.48 + _browser.delegate = nil;
16.49 + [_browser release];
16.50 + [_serviceType release];
16.51 + [_error release];
16.52 + [_services release];
16.53 + [_addServices release];
16.54 + [_rmvServices release];
16.55 + [super dealloc];
16.56 +}
16.57 +
16.58 +
16.59 +@synthesize browsing=_browsing, error=_error, services=_services, serviceClass=_serviceClass;
16.60 +
16.61 +
16.62 +- (void) start
16.63 +{
16.64 + [_browser searchForServicesOfType: _serviceType inDomain: @"local."];
16.65 +}
16.66 +
16.67 +- (void) stop
16.68 +{
16.69 + [_browser stop];
16.70 +}
16.71 +
16.72 +
16.73 +- (void)netServiceBrowserWillSearch:(NSNetServiceBrowser *)netServiceBrowser
16.74 +{
16.75 + LogTo(Bonjour,@"%@ started browsing",self);
16.76 + self.browsing = YES;
16.77 +}
16.78 +
16.79 +- (void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)netServiceBrowser
16.80 +{
16.81 + LogTo(Bonjour,@"%@ stopped browsing",self);
16.82 + self.browsing = NO;
16.83 +}
16.84 +
16.85 +- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser
16.86 + didNotSearch:(NSDictionary *)errorDict
16.87 +{
16.88 + NSString *domain = [errorDict objectForKey: NSNetServicesErrorDomain];
16.89 + int err = [[errorDict objectForKey: NSNetServicesErrorCode] intValue];
16.90 + self.error = [NSError errorWithDomain: domain code: err userInfo: nil];
16.91 + LogTo(Bonjour,@"%@ got error: ",self,self.error);
16.92 + self.browsing = NO;
16.93 +}
16.94 +
16.95 +
16.96 +- (void) _updateServiceList
16.97 +{
16.98 + if( _rmvServices.count ) {
16.99 + [self willChangeValueForKey: @"services"
16.100 + withSetMutation: NSKeyValueMinusSetMutation
16.101 + usingObjects: _rmvServices];
16.102 + [_services minusSet: _rmvServices];
16.103 + [self didChangeValueForKey: @"services"
16.104 + withSetMutation: NSKeyValueMinusSetMutation
16.105 + usingObjects: _rmvServices];
16.106 + [_rmvServices makeObjectsPerformSelector: @selector(removed)];
16.107 + [_rmvServices removeAllObjects];
16.108 + }
16.109 + if( _addServices.count ) {
16.110 + [_addServices makeObjectsPerformSelector: @selector(added)];
16.111 + [self willChangeValueForKey: @"services"
16.112 + withSetMutation: NSKeyValueUnionSetMutation
16.113 + usingObjects: _addServices];
16.114 + [_services unionSet: _addServices];
16.115 + [self didChangeValueForKey: @"services"
16.116 + withSetMutation: NSKeyValueUnionSetMutation
16.117 + usingObjects: _addServices];
16.118 + [_addServices removeAllObjects];
16.119 + }
16.120 +}
16.121 +
16.122 +
16.123 +- (void) _handleService: (NSNetService*)netService
16.124 + addTo: (NSMutableSet*)addTo
16.125 + removeFrom: (NSMutableSet*)removeFrom
16.126 + moreComing: (BOOL)moreComing
16.127 +{
16.128 + // Wrap the NSNetService in a BonjourService, using an existing instance if possible:
16.129 + MYBonjourService *service = [[_serviceClass alloc] initWithNetService: netService];
16.130 + MYBonjourService *existingService = [_services member: service];
16.131 + if( existingService ) {
16.132 + [service release];
16.133 + service = [existingService retain];
16.134 + }
16.135 +
16.136 + if( [removeFrom containsObject: service] )
16.137 + [removeFrom removeObject: service];
16.138 + else
16.139 + [addTo addObject: service];
16.140 + [service release];
16.141 + if( ! moreComing )
16.142 + [self _updateServiceList];
16.143 +}
16.144 +
16.145 +- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser
16.146 + didFindService:(NSNetService *)netService
16.147 + moreComing:(BOOL)moreComing
16.148 +{
16.149 + //LogTo(Bonjour,@"Add service %@",netService);
16.150 + [self _handleService: netService addTo: _addServices removeFrom: _rmvServices moreComing: moreComing];
16.151 +}
16.152 +
16.153 +- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser
16.154 + didRemoveService:(NSNetService *)netService
16.155 + moreComing:(BOOL)moreComing
16.156 +{
16.157 + //LogTo(Bonjour,@"Remove service %@",netService);
16.158 + [self _handleService: netService addTo: _rmvServices removeFrom: _addServices moreComing: moreComing];
16.159 +}
16.160 +
16.161 +
16.162 +@end
16.163 +
16.164 +
16.165 +
16.166 +#pragma mark -
16.167 +#pragma mark TESTING:
16.168 +
16.169 +@interface BonjourTester : NSObject
16.170 +{
16.171 + MYBonjourBrowser *_browser;
16.172 +}
16.173 +@end
16.174 +
16.175 +@implementation BonjourTester
16.176 +
16.177 +- (id) init
16.178 +{
16.179 + self = [super init];
16.180 + if (self != nil) {
16.181 + _browser = [[MYBonjourBrowser alloc] initWithServiceType: @"_http._tcp"];
16.182 + [_browser addObserver: self forKeyPath: @"services" options: NSKeyValueObservingOptionNew context: NULL];
16.183 + [_browser addObserver: self forKeyPath: @"browsing" options: NSKeyValueObservingOptionNew context: NULL];
16.184 + [_browser start];
16.185 + }
16.186 + return self;
16.187 +}
16.188 +
16.189 +- (void) dealloc
16.190 +{
16.191 + [_browser stop];
16.192 + [_browser removeObserver: self forKeyPath: @"services"];
16.193 + [_browser removeObserver: self forKeyPath: @"browsing"];
16.194 + [_browser release];
16.195 + [super dealloc];
16.196 +}
16.197 +
16.198 +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
16.199 +{
16.200 + LogTo(Bonjour,@"Observed change in %@: %@",keyPath,change);
16.201 + if( $equal(keyPath,@"services") ) {
16.202 + if( [[change objectForKey: NSKeyValueChangeKindKey] intValue]==NSKeyValueChangeInsertion ) {
16.203 + NSSet *newServices = [change objectForKey: NSKeyValueChangeNewKey];
16.204 + for( MYBonjourService *service in newServices ) {
16.205 + LogTo(Bonjour,@" --> %@ : TXT=%@", service,service.txtRecord);
16.206 + }
16.207 + }
16.208 + }
16.209 +}
16.210 +
16.211 +@end
16.212 +
16.213 +TestCase(Bonjour) {
16.214 + [NSRunLoop currentRunLoop]; // create runloop
16.215 + BonjourTester *tester = [[BonjourTester alloc] init];
16.216 + [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 15]];
16.217 + [tester release];
16.218 +}
16.219 +
16.220 +
16.221 +
16.222 +/*
16.223 + Copyright (c) 2008-2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
16.224 +
16.225 + Redistribution and use in source and binary forms, with or without modification, are permitted
16.226 + provided that the following conditions are met:
16.227 +
16.228 + * Redistributions of source code must retain the above copyright notice, this list of conditions
16.229 + and the following disclaimer.
16.230 + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
16.231 + and the following disclaimer in the documentation and/or other materials provided with the
16.232 + distribution.
16.233 +
16.234 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16.235 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16.236 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
16.237 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16.238 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16.239 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
16.240 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
16.241 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16.242 + */
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/Bonjour/MYBonjourService.h Wed Apr 22 16:45:39 2009 -0700
17.3 @@ -0,0 +1,70 @@
17.4 +//
17.5 +// MYBonjourService.h
17.6 +// MYNetwork
17.7 +//
17.8 +// Created by Jens Alfke on 1/22/08.
17.9 +// Copyright 2008 Jens Alfke. All rights reserved.
17.10 +//
17.11 +
17.12 +#import <Foundation/Foundation.h>
17.13 +#import "ConcurrentOperation.h"
17.14 +@class MYBonjourResolveOperation;
17.15 +
17.16 +
17.17 +/** Represents a Bonjour service discovered by a BonjourBrowser. */
17.18 +@interface MYBonjourService : NSObject
17.19 +{
17.20 + @private
17.21 + NSNetService *_netService;
17.22 + NSDictionary *_txtRecord;
17.23 + NSSet *_addresses;
17.24 + CFAbsoluteTime _addressesExpireAt;
17.25 + MYBonjourResolveOperation *_resolveOp;
17.26 +}
17.27 +
17.28 +/** The service's name. */
17.29 +@property (readonly) NSString *name;
17.30 +
17.31 +/** The service's metadata dictionary, from its DNS TXT record */
17.32 +@property (readonly,copy) NSDictionary *txtRecord;
17.33 +
17.34 +/** A convenience to access a single property from the TXT record. */
17.35 +- (NSString*) txtStringForKey: (NSString*)key;
17.36 +
17.37 +/** Returns a set of IPAddress objects; may be the empty set if address resolution failed,
17.38 + or nil if addresses have not been resolved yet (or expired).
17.39 + In the latter case, call -resolve and wait for the returned Operation to finish. */
17.40 +@property (readonly,copy) NSSet* addresses;
17.41 +
17.42 +/** Starts looking up the IP address(es) of this service.
17.43 + @return The NSOperation representing the lookup; you can observe this to see when it
17.44 + completes, or you can observe the service's 'addresses' property. */
17.45 +- (MYBonjourResolveOperation*) resolve;
17.46 +
17.47 +/** The underlying NSNetSerice object. */
17.48 +@property (readonly) NSNetService *netService;
17.49 +
17.50 +
17.51 +// Protected methods, for subclass use only:
17.52 +
17.53 +- (id) initWithNetService: (NSNetService*)netService;
17.54 +
17.55 +// (for subclasses to override, but not call):
17.56 +- (void) added;
17.57 +- (void) removed;
17.58 +- (void) txtRecordChanged;
17.59 +
17.60 +@end
17.61 +
17.62 +
17.63 +
17.64 +@interface MYBonjourResolveOperation : ConcurrentOperation
17.65 +{
17.66 + MYBonjourService *_service;
17.67 + NSSet *_addresses;
17.68 +}
17.69 +
17.70 +@property (readonly) MYBonjourService *service;
17.71 +@property (readonly,retain) NSSet *addresses;
17.72 +
17.73 +@end
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/Bonjour/MYBonjourService.m Wed Apr 22 16:45:39 2009 -0700
18.3 @@ -0,0 +1,251 @@
18.4 +//
18.5 +// MYBonjourService.m
18.6 +// MYNetwork
18.7 +//
18.8 +// Created by Jens Alfke on 1/22/08.
18.9 +// Copyright 2008 Jens Alfke. All rights reserved.
18.10 +//
18.11 +
18.12 +#import "MYBonjourService.h"
18.13 +#import "IPAddress.h"
18.14 +#import "ConcurrentOperation.h"
18.15 +#import "Test.h"
18.16 +#import "Logging.h"
18.17 +
18.18 +
18.19 +NSString* const kBonjourServiceResolvedAddressesNotification = @"BonjourServiceResolvedAddresses";
18.20 +
18.21 +
18.22 +@interface MYBonjourService ()
18.23 +@property (copy) NSSet* addresses;
18.24 +@end
18.25 +
18.26 +@interface MYBonjourResolveOperation ()
18.27 +@property (assign) MYBonjourService *service;
18.28 +@property (retain) NSSet *addresses;
18.29 +@end
18.30 +
18.31 +
18.32 +
18.33 +@implementation MYBonjourService
18.34 +
18.35 +
18.36 +- (id) initWithNetService: (NSNetService*)netService
18.37 +{
18.38 + self = [super init];
18.39 + if (self != nil) {
18.40 + _netService = [netService retain];
18.41 + _netService.delegate = self;
18.42 + }
18.43 + return self;
18.44 +}
18.45 +
18.46 +- (void) dealloc
18.47 +{
18.48 + Log(@"DEALLOC %@",self);
18.49 + _netService.delegate = nil;
18.50 + [_netService release];
18.51 + [_txtRecord release];
18.52 + [_addresses release];
18.53 + [super dealloc];
18.54 +}
18.55 +
18.56 +
18.57 +- (NSString*) description
18.58 +{
18.59 + return $sprintf(@"%@['%@'.%@%@]", self.class,self.name,_netService.type,_netService.domain);
18.60 +}
18.61 +
18.62 +
18.63 +- (NSComparisonResult) compare: (id)obj
18.64 +{
18.65 + return [self.name caseInsensitiveCompare: [obj name]];
18.66 +}
18.67 +
18.68 +
18.69 +- (NSNetService*) netService {return _netService;}
18.70 +- (BOOL) isEqual: (id)obj {return [obj isKindOfClass: [MYBonjourService class]] && [_netService isEqual: [obj netService]];}
18.71 +- (NSUInteger) hash {return _netService.hash;}
18.72 +- (NSString*) name {return _netService.name;}
18.73 +
18.74 +
18.75 +- (void) added
18.76 +{
18.77 + LogTo(Bonjour,@"Added %@",_netService);
18.78 +}
18.79 +
18.80 +- (void) removed
18.81 +{
18.82 + LogTo(Bonjour,@"Removed %@",_netService);
18.83 + [_netService stopMonitoring];
18.84 + _netService.delegate = nil;
18.85 +
18.86 + if( _resolveOp ) {
18.87 + [_resolveOp cancel];
18.88 + [_resolveOp release];
18.89 + _resolveOp = nil;
18.90 + }
18.91 +}
18.92 +
18.93 +
18.94 +#pragma mark -
18.95 +#pragma mark TXT RECORD:
18.96 +
18.97 +
18.98 +- (NSDictionary*) txtRecord
18.99 +{
18.100 + [_netService startMonitoring];
18.101 + return _txtRecord;
18.102 +}
18.103 +
18.104 +- (void) txtRecordChanged
18.105 +{
18.106 + // no-op (this is here for subclassers to override)
18.107 +}
18.108 +
18.109 +- (NSString*) txtStringForKey: (NSString*)key
18.110 +{
18.111 + NSData *value = [self.txtRecord objectForKey: key];
18.112 + if( ! value )
18.113 + return nil;
18.114 + if( ! [value isKindOfClass: [NSData class]] ) {
18.115 + Warn(@"TXT dictionary has unexpected value type: %@",value.class);
18.116 + return nil;
18.117 + }
18.118 + NSString *str = [[NSString alloc] initWithData: value encoding: NSUTF8StringEncoding];
18.119 + if( ! str )
18.120 + str = [[NSString alloc] initWithData: value encoding: NSWindowsCP1252StringEncoding];
18.121 + return [str autorelease];
18.122 +}
18.123 +
18.124 +
18.125 +- (void)netService:(NSNetService *)sender didUpdateTXTRecordData:(NSData *)data
18.126 +{
18.127 + NSDictionary *txtDict = [NSNetService dictionaryFromTXTRecordData: data];
18.128 + if( ! $equal(txtDict,_txtRecord) ) {
18.129 + LogTo(Bonjour,@"%@ got TXT record (%u bytes)",self,data.length);
18.130 + [self willChangeValueForKey: @"txtRecord"];
18.131 + setObj(&_txtRecord,txtDict);
18.132 + [self didChangeValueForKey: @"txtRecord"];
18.133 + [self txtRecordChanged];
18.134 + }
18.135 +}
18.136 +
18.137 +
18.138 +#pragma mark -
18.139 +#pragma mark ADDRESS RESOLUTION:
18.140 +
18.141 +
18.142 +#define kAddressResolveTimeout 10.0
18.143 +#define kAddressExpirationInterval 60.0
18.144 +#define kAddressErrorRetryInterval 5.0
18.145 +
18.146 +
18.147 +- (NSSet*) addresses
18.148 +{
18.149 + if( _addresses && CFAbsoluteTimeGetCurrent() >= _addressesExpireAt ) {
18.150 + setObj(&_addresses,nil); // eww, toss 'em and get new ones
18.151 + [self resolve];
18.152 + }
18.153 + return _addresses;
18.154 +}
18.155 +
18.156 +
18.157 +- (MYBonjourResolveOperation*) resolve
18.158 +{
18.159 + if( ! _resolveOp ) {
18.160 + LogTo(Bonjour,@"Resolving %@",self);
18.161 + _resolveOp = [[MYBonjourResolveOperation alloc] init];
18.162 + _resolveOp.service = self;
18.163 + [_resolveOp start];
18.164 + Assert(_netService);
18.165 + Assert(_netService.delegate=self);
18.166 + [_netService resolveWithTimeout: kAddressResolveTimeout];
18.167 + }
18.168 + return _resolveOp;
18.169 +}
18.170 +
18.171 +- (void) setAddresses: (NSSet*)addresses
18.172 +{
18.173 + setObj(&_addresses,addresses);
18.174 +}
18.175 +
18.176 +
18.177 +- (void) _finishedResolving: (NSSet*)addresses expireIn: (NSTimeInterval)expirationInterval
18.178 +{
18.179 + _addressesExpireAt = CFAbsoluteTimeGetCurrent() + expirationInterval;
18.180 + self.addresses = addresses;
18.181 + _resolveOp.addresses = addresses;
18.182 + [_resolveOp finish];
18.183 + [_resolveOp release];
18.184 + _resolveOp = nil;
18.185 +}
18.186 +
18.187 +
18.188 +- (void)netServiceDidResolveAddress:(NSNetService *)sender
18.189 +{
18.190 + // Convert the raw sockaddrs into IPAddress objects:
18.191 + NSMutableSet *addresses = [NSMutableSet setWithCapacity: 2];
18.192 + for( NSData *rawAddr in _netService.addresses ) {
18.193 + IPAddress *addr = [[IPAddress alloc] initWithSockAddr: rawAddr.bytes];
18.194 + if( addr ) {
18.195 + [addresses addObject: addr];
18.196 + [addr release];
18.197 + }
18.198 + }
18.199 + LogTo(Bonjour,@"Resolved %@: %@",self,addresses);
18.200 + [self _finishedResolving: addresses expireIn: kAddressExpirationInterval];
18.201 +}
18.202 +
18.203 +- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict
18.204 +{
18.205 + LogTo(Bonjour,@"Error resolving %@ -- %@",self,errorDict);
18.206 + [self _finishedResolving: [NSArray array] expireIn: kAddressErrorRetryInterval];
18.207 +}
18.208 +
18.209 +- (void)netServiceDidStop:(NSNetService *)sender
18.210 +{
18.211 + LogTo(Bonjour,@"Resolve stopped for %@",self);
18.212 + [self _finishedResolving: [NSArray array] expireIn: kAddressErrorRetryInterval];
18.213 +}
18.214 +
18.215 +
18.216 +@end
18.217 +
18.218 +
18.219 +
18.220 +
18.221 +@implementation MYBonjourResolveOperation
18.222 +
18.223 +@synthesize service=_service, addresses=_addresses;
18.224 +
18.225 +- (void) dealloc
18.226 +{
18.227 + [_addresses release];
18.228 + [super dealloc];
18.229 +}
18.230 +
18.231 +@end
18.232 +
18.233 +
18.234 +/*
18.235 + Copyright (c) 2008-2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
18.236 +
18.237 + Redistribution and use in source and binary forms, with or without modification, are permitted
18.238 + provided that the following conditions are met:
18.239 +
18.240 + * Redistributions of source code must retain the above copyright notice, this list of conditions
18.241 + and the following disclaimer.
18.242 + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
18.243 + and the following disclaimer in the documentation and/or other materials provided with the
18.244 + distribution.
18.245 +
18.246 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
18.247 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18.248 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
18.249 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18.250 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18.251 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
18.252 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
18.253 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18.254 + */
19.1 --- a/IPAddress.h Tue Dec 02 22:42:56 2008 -0800
19.2 +++ b/IPAddress.h Wed Apr 22 16:45:39 2009 -0700
19.3 @@ -35,6 +35,10 @@
19.4 /** Initializes an IPAddress from a BSD struct sockaddr. */
19.5 - (id) initWithSockAddr: (const struct sockaddr*)sockaddr;
19.6
19.7 +/** Returns the IP address of this host (plus the specified port number).
19.8 + If multiple network interfaces are active, the main one's address is returned. */
19.9 ++ (IPAddress*) localAddressWithPort: (UInt16)port;
19.10 +
19.11 /** Returns the IP address of this host (with a port number of zero).
19.12 If multiple network interfaces are active, the main one's address is returned. */
19.13 + (IPAddress*) localAddress;
20.1 --- a/IPAddress.m Tue Dec 02 22:42:56 2008 -0800
20.2 +++ b/IPAddress.m Wed Apr 22 16:45:39 2009 -0700
20.3 @@ -160,7 +160,7 @@
20.4 }
20.5
20.6
20.7 -+ (IPAddress*) localAddress
20.8 ++ (IPAddress*) localAddressWithPort: (UInt16)port
20.9 {
20.10 // getifaddrs returns a linked list of interface entries;
20.11 // find the first active non-loopback interface with IPv4:
20.12 @@ -179,7 +179,12 @@
20.13 }
20.14 freeifaddrs(interfaces);
20.15 }
20.16 - return [[[self alloc] initWithIPv4: address] autorelease];
20.17 + return [[[self alloc] initWithIPv4: address port: port] autorelease];
20.18 +}
20.19 +
20.20 ++ (IPAddress*) localAddress
20.21 +{
20.22 + return [self localAddressWithPort: 0];
20.23 }
20.24
20.25
20.26 @@ -339,7 +344,7 @@
20.27 TestCase(IPAddress) {
20.28 RequireTestCase(CollectionUtils);
20.29 IPAddress *addr = [[IPAddress alloc] initWithIPv4: htonl(0x0A0001FE) port: 8080];
20.30 - CAssertEq(addr.ipv4,htonl(0x0A0001FE));
20.31 + CAssertEq(addr.ipv4,(UInt32)htonl(0x0A0001FE));
20.32 CAssertEq(addr.port,8080);
20.33 CAssertEqual(addr.hostname,@"10.0.1.254");
20.34 CAssertEqual(addr.description,@"10.0.1.254:8080");
20.35 @@ -347,7 +352,7 @@
20.36
20.37 addr = [[IPAddress alloc] initWithHostname: @"66.66.0.255" port: 123];
20.38 CAssertEq(addr.class,[IPAddress class]);
20.39 - CAssertEq(addr.ipv4,htonl(0x424200FF));
20.40 + CAssertEq(addr.ipv4,(UInt32)htonl(0x424200FF));
20.41 CAssertEq(addr.port,123);
20.42 CAssertEqual(addr.hostname,@"66.66.0.255");
20.43 CAssertEqual(addr.description,@"66.66.0.255:123");
20.44 @@ -355,8 +360,8 @@
20.45
20.46 addr = [[IPAddress alloc] initWithHostname: @"www.apple.com" port: 80];
20.47 CAssertEq(addr.class,[HostAddress class]);
20.48 - Log(@"www.apple.com = 0x%08X", addr.ipv4);
20.49 - CAssertEq(addr.ipv4,htonl(0x1195A00A));
20.50 + Log(@"www.apple.com = %@ [0x%08X]", addr.ipv4name, ntohl(addr.ipv4));
20.51 + CAssertEq(addr.ipv4,(UInt32)htonl(0x11FBC820));
20.52 CAssertEq(addr.port,80);
20.53 CAssertEqual(addr.hostname,@"www.apple.com");
20.54 CAssertEqual(addr.description,@"www.apple.com:80");
21.1 --- a/MYNetwork-iPhone.xcodeproj/project.pbxproj Tue Dec 02 22:42:56 2008 -0800
21.2 +++ b/MYNetwork-iPhone.xcodeproj/project.pbxproj Wed Apr 22 16:45:39 2009 -0700
21.3 @@ -36,6 +36,11 @@
21.4 270E9B9A0EE64B45003F17CA /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 270E9B970EE64B45003F17CA /* Icon.png */; };
21.5 270E9BA10EE64B4E003F17CA /* HelloWorldAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 270E9B9E0EE64B4E003F17CA /* HelloWorldAppDelegate.m */; };
21.6 270E9BA20EE64B4E003F17CA /* MyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 270E9BA00EE64B4E003F17CA /* MyViewController.m */; };
21.7 + 2777C78D0F75E141007F8D30 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2777C78C0F75E141007F8D30 /* Security.framework */; };
21.8 + 278C1B2E0F9F865800954AE1 /* MYPortMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1B2C0F9F865800954AE1 /* MYPortMapper.m */; };
21.9 + 278C1B2F0F9F865800954AE1 /* PortMapperTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1B2D0F9F865800954AE1 /* PortMapperTest.m */; };
21.10 + 278C1B350F9F86A100954AE1 /* MYUtilities_Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 278C1B330F9F86A100954AE1 /* MYUtilities_Debug.xcconfig */; };
21.11 + 278C1B360F9F86A100954AE1 /* MYUtilities_Release.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 278C1B340F9F86A100954AE1 /* MYUtilities_Release.xcconfig */; };
21.12 280E754F0DD40C5E005A515E /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 280E754C0DD40C5E005A515E /* MainWindow.xib */; };
21.13 /* End PBXBuildFile section */
21.14
21.15 @@ -96,6 +101,12 @@
21.16 270E9B9E0EE64B4E003F17CA /* HelloWorldAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HelloWorldAppDelegate.m; sourceTree = "<group>"; };
21.17 270E9B9F0EE64B4E003F17CA /* MyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyViewController.h; sourceTree = "<group>"; };
21.18 270E9BA00EE64B4E003F17CA /* MyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyViewController.m; sourceTree = "<group>"; };
21.19 + 2777C78C0F75E141007F8D30 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
21.20 + 278C1B2B0F9F865800954AE1 /* MYPortMapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPortMapper.h; sourceTree = "<group>"; };
21.21 + 278C1B2C0F9F865800954AE1 /* MYPortMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPortMapper.m; sourceTree = "<group>"; };
21.22 + 278C1B2D0F9F865800954AE1 /* PortMapperTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PortMapperTest.m; sourceTree = "<group>"; };
21.23 + 278C1B330F9F86A100954AE1 /* MYUtilities_Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = MYUtilities_Debug.xcconfig; sourceTree = "<group>"; };
21.24 + 278C1B340F9F86A100954AE1 /* MYUtilities_Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = MYUtilities_Release.xcconfig; sourceTree = "<group>"; };
21.25 280E754C0DD40C5E005A515E /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; };
21.26 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = iPhone/main.m; sourceTree = "<group>"; };
21.27 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
21.28 @@ -110,6 +121,7 @@
21.29 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
21.30 270E9AE90EE61167003F17CA /* libz.dylib in Frameworks */,
21.31 270E9B4F0EE63F8F003F17CA /* CFNetwork.framework in Frameworks */,
21.32 + 2777C78D0F75E141007F8D30 /* Security.framework in Frameworks */,
21.33 );
21.34 runOnlyForDeploymentPostprocessing = 0;
21.35 };
21.36 @@ -141,6 +153,7 @@
21.37 270E9AA20EE61113003F17CA /* IPAddress.m */,
21.38 270E9AA30EE61113003F17CA /* TCP */,
21.39 270E9AAF0EE61113003F17CA /* BLIP */,
21.40 + 278C1B2A0F9F865800954AE1 /* PortMapper */,
21.41 );
21.42 name = MYNetwork;
21.43 sourceTree = "<group>";
21.44 @@ -201,6 +214,8 @@
21.45 270E9AD70EE6111A003F17CA /* Target.m */,
21.46 270E9AD80EE6111A003F17CA /* Test.h */,
21.47 270E9AD90EE6111A003F17CA /* Test.m */,
21.48 + 278C1B330F9F86A100954AE1 /* MYUtilities_Debug.xcconfig */,
21.49 + 278C1B340F9F86A100954AE1 /* MYUtilities_Release.xcconfig */,
21.50 270E9ADA0EE6111A003F17CA /* GoogleToolboxSubset */,
21.51 );
21.52 name = MYUtilities;
21.53 @@ -228,6 +243,16 @@
21.54 path = Classes;
21.55 sourceTree = "<group>";
21.56 };
21.57 + 278C1B2A0F9F865800954AE1 /* PortMapper */ = {
21.58 + isa = PBXGroup;
21.59 + children = (
21.60 + 278C1B2B0F9F865800954AE1 /* MYPortMapper.h */,
21.61 + 278C1B2C0F9F865800954AE1 /* MYPortMapper.m */,
21.62 + 278C1B2D0F9F865800954AE1 /* PortMapperTest.m */,
21.63 + );
21.64 + path = PortMapper;
21.65 + sourceTree = "<group>";
21.66 + };
21.67 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
21.68 isa = PBXGroup;
21.69 children = (
21.70 @@ -237,6 +262,7 @@
21.71 29B97315FDCFA39411CA2CEA /* Other Sources */,
21.72 29B97323FDCFA39411CA2CEA /* Frameworks */,
21.73 19C28FACFE9D520D11CA2CBB /* Products */,
21.74 + 2777C78C0F75E141007F8D30 /* Security.framework */,
21.75 );
21.76 name = CustomTemplate;
21.77 sourceTree = "<group>";
21.78 @@ -325,6 +351,8 @@
21.79 270E9B950EE64B3C003F17CA /* HelloWorld.xib in Resources */,
21.80 270E9B990EE64B45003F17CA /* Default.png in Resources */,
21.81 270E9B9A0EE64B45003F17CA /* Icon.png in Resources */,
21.82 + 278C1B350F9F86A100954AE1 /* MYUtilities_Debug.xcconfig in Resources */,
21.83 + 278C1B360F9F86A100954AE1 /* MYUtilities_Release.xcconfig in Resources */,
21.84 );
21.85 runOnlyForDeploymentPostprocessing = 0;
21.86 };
21.87 @@ -357,6 +385,8 @@
21.88 270E9AE40EE6111A003F17CA /* GTMNSData+zlib.m in Sources */,
21.89 270E9BA10EE64B4E003F17CA /* HelloWorldAppDelegate.m in Sources */,
21.90 270E9BA20EE64B4E003F17CA /* MyViewController.m in Sources */,
21.91 + 278C1B2E0F9F865800954AE1 /* MYPortMapper.m in Sources */,
21.92 + 278C1B2F0F9F865800954AE1 /* PortMapperTest.m in Sources */,
21.93 );
21.94 runOnlyForDeploymentPostprocessing = 0;
21.95 };
21.96 @@ -366,56 +396,37 @@
21.97 1D6058940D05DD3E006BFB54 /* Debug */ = {
21.98 isa = XCBuildConfiguration;
21.99 buildSettings = {
21.100 - ALWAYS_SEARCH_USER_PATHS = NO;
21.101 - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Jens Alfke";
21.102 - COPY_PHASE_STRIP = NO;
21.103 - GCC_DYNAMIC_NO_PIC = NO;
21.104 - GCC_OPTIMIZATION_LEVEL = 0;
21.105 - GCC_PRECOMPILE_PREFIX_HEADER = YES;
21.106 - GCC_PREFIX_HEADER = iPhone/MYNetwork_iPhone_Prefix.pch;
21.107 INFOPLIST_FILE = iPhone/Info.plist;
21.108 PRODUCT_NAME = BLIPEcho;
21.109 - PROVISIONING_PROFILE = "166C8314-D005-438F-841B-B20D42F71712";
21.110 };
21.111 name = Debug;
21.112 };
21.113 1D6058950D05DD3E006BFB54 /* Release */ = {
21.114 isa = XCBuildConfiguration;
21.115 buildSettings = {
21.116 - ALWAYS_SEARCH_USER_PATHS = NO;
21.117 - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Jens Alfke";
21.118 - COPY_PHASE_STRIP = YES;
21.119 - GCC_PRECOMPILE_PREFIX_HEADER = YES;
21.120 - GCC_PREFIX_HEADER = iPhone/MYNetwork_iPhone_Prefix.pch;
21.121 INFOPLIST_FILE = iPhone/Info.plist;
21.122 PRODUCT_NAME = BLIPEcho;
21.123 - PROVISIONING_PROFILE = "166C8314-D005-438F-841B-B20D42F71712";
21.124 };
21.125 name = Release;
21.126 };
21.127 C01FCF4F08A954540054247B /* Debug */ = {
21.128 isa = XCBuildConfiguration;
21.129 + baseConfigurationReference = 278C1B330F9F86A100954AE1 /* MYUtilities_Debug.xcconfig */;
21.130 buildSettings = {
21.131 ARCHS = "$(ARCHS_STANDARD_32_BIT)";
21.132 "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
21.133 - GCC_C_LANGUAGE_STANDARD = c99;
21.134 - GCC_WARN_ABOUT_RETURN_TYPE = YES;
21.135 - GCC_WARN_UNUSED_VARIABLE = YES;
21.136 + EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = "*.nib *.lproj *.framework *.gch *.xcode* (*) CVS .svn .hg";
21.137 ONLY_ACTIVE_ARCH = YES;
21.138 - PREBINDING = NO;
21.139 SDKROOT = iphonesimulator2.0;
21.140 };
21.141 name = Debug;
21.142 };
21.143 C01FCF5008A954540054247B /* Release */ = {
21.144 isa = XCBuildConfiguration;
21.145 + baseConfigurationReference = 278C1B340F9F86A100954AE1 /* MYUtilities_Release.xcconfig */;
21.146 buildSettings = {
21.147 ARCHS = "$(ARCHS_STANDARD_32_BIT)";
21.148 "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
21.149 - GCC_C_LANGUAGE_STANDARD = c99;
21.150 - GCC_WARN_ABOUT_RETURN_TYPE = YES;
21.151 - GCC_WARN_UNUSED_VARIABLE = YES;
21.152 - PREBINDING = NO;
21.153 SDKROOT = iphonesimulator2.0;
21.154 };
21.155 name = Release;
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/MYNetwork.h Wed Apr 22 16:45:39 2009 -0700
22.3 @@ -0,0 +1,14 @@
22.4 +/*
22.5 + * MYNetwork.h
22.6 + * MYNetwork
22.7 + *
22.8 + * Created by Jens Alfke on 4/21/09.
22.9 + * Copyright 2009 Jens Alfke. All rights reserved.
22.10 + *
22.11 + */
22.12 +
22.13 +#import "BLIP.h"
22.14 +#import "MYBonjourBrowser.h"
22.15 +#import "MYBonjourService.h"
22.16 +#import "IPAddress.h"
22.17 +#import "MYPortMapper.h"
23.1 --- a/MYNetwork.xcodeproj/project.pbxproj Tue Dec 02 22:42:56 2008 -0800
23.2 +++ b/MYNetwork.xcodeproj/project.pbxproj Wed Apr 22 16:45:39 2009 -0700
23.3 @@ -24,60 +24,74 @@
23.4 270461370DE4918D003D9D3F /* ExceptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461350DE4918D003D9D3F /* ExceptionUtils.m */; };
23.5 270461470DE491A6003D9D3F /* Target.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461460DE491A6003D9D3F /* Target.m */; };
23.6 270461890DE49634003D9D3F /* CollectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461870DE49634003D9D3F /* CollectionUtils.m */; };
23.7 - 2704618C0DE49652003D9D3F /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2704618B0DE49652003D9D3F /* libz.dylib */; };
23.8 - 270461920DE4975D003D9D3F /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 270461910DE4975C003D9D3F /* CoreServices.framework */; };
23.9 - 277904330DE91DE600C6D295 /* BLIPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F40DE49030003D9D3F /* BLIPConnection.m */; };
23.10 - 277904340DE91DE700C6D295 /* BLIPDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F60DE49030003D9D3F /* BLIPDispatcher.m */; };
23.11 - 277904350DE91DE800C6D295 /* BLIPEchoClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 277903E90DE8F08100C6D295 /* BLIPEchoClient.m */; };
23.12 - 277904370DE91DEB00C6D295 /* BLIPMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F90DE49030003D9D3F /* BLIPMessage.m */; };
23.13 - 277904380DE91DEC00C6D295 /* BLIPProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460FB0DE49030003D9D3F /* BLIPProperties.m */; };
23.14 - 277904390DE91DEE00C6D295 /* BLIPReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460FD0DE49030003D9D3F /* BLIPReader.m */; };
23.15 - 2779043A0DE91DEF00C6D295 /* BLIPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D5EC060DE5FEDE00CD84FA /* BLIPRequest.m */; };
23.16 - 2779043C0DE91DF100C6D295 /* BLIPWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461000DE49030003D9D3F /* BLIPWriter.m */; };
23.17 - 2779043D0DE91DF300C6D295 /* IPAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461020DE49030003D9D3F /* IPAddress.m */; };
23.18 - 2779043E0DE91DF500C6D295 /* TCPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610A0DE49030003D9D3F /* TCPConnection.m */; };
23.19 - 2779043F0DE91DF800C6D295 /* TCPEndpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610C0DE49030003D9D3F /* TCPEndpoint.m */; };
23.20 - 277904400DE91DF900C6D295 /* TCPListener.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610E0DE49030003D9D3F /* TCPListener.m */; };
23.21 - 277904410DE91DFA00C6D295 /* TCPStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461100DE49030003D9D3F /* TCPStream.m */; };
23.22 - 277904420DE91DFC00C6D295 /* TCPWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461120DE49030003D9D3F /* TCPWriter.m */; };
23.23 - 277904440DE91E3500C6D295 /* CollectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461870DE49634003D9D3F /* CollectionUtils.m */; };
23.24 - 277904450DE91E3600C6D295 /* ExceptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461350DE4918D003D9D3F /* ExceptionUtils.m */; };
23.25 - 277904460DE91E3700C6D295 /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704612A0DE49088003D9D3F /* Logging.m */; };
23.26 - 277904480DE91E3900C6D295 /* Target.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461460DE491A6003D9D3F /* Target.m */; };
23.27 - 277904490DE91E3A00C6D295 /* Test.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461280DE49088003D9D3F /* Test.m */; };
23.28 + 2706F1D90F9D3EF300292CCF /* SecurityInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2706F1D80F9D3EF300292CCF /* SecurityInterface.framework */; };
23.29 + 2777C9110F7602A7007F8D30 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2777C9100F7602A7007F8D30 /* Security.framework */; };
23.30 2779048B0DE9204300C6D295 /* BLIPEchoClient.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2779048A0DE9204300C6D295 /* BLIPEchoClient.xib */; };
23.31 - 277905110DE9E5BC00C6D295 /* BLIPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F40DE49030003D9D3F /* BLIPConnection.m */; };
23.32 - 277905120DE9E5BC00C6D295 /* BLIPDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F60DE49030003D9D3F /* BLIPDispatcher.m */; };
23.33 - 277905130DE9E5BC00C6D295 /* BLIPMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F90DE49030003D9D3F /* BLIPMessage.m */; };
23.34 - 277905140DE9E5BC00C6D295 /* BLIPProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460FB0DE49030003D9D3F /* BLIPProperties.m */; };
23.35 - 277905150DE9E5BC00C6D295 /* BLIPReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460FD0DE49030003D9D3F /* BLIPReader.m */; };
23.36 - 277905160DE9E5BC00C6D295 /* BLIPWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461000DE49030003D9D3F /* BLIPWriter.m */; };
23.37 - 277905170DE9E5BC00C6D295 /* IPAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461020DE49030003D9D3F /* IPAddress.m */; };
23.38 - 277905180DE9E5BC00C6D295 /* TCPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610A0DE49030003D9D3F /* TCPConnection.m */; };
23.39 - 277905190DE9E5BC00C6D295 /* TCPEndpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610C0DE49030003D9D3F /* TCPEndpoint.m */; };
23.40 - 2779051A0DE9E5BC00C6D295 /* TCPListener.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610E0DE49030003D9D3F /* TCPListener.m */; };
23.41 - 2779051B0DE9E5BC00C6D295 /* TCPStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461100DE49030003D9D3F /* TCPStream.m */; };
23.42 - 2779051C0DE9E5BC00C6D295 /* TCPWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461120DE49030003D9D3F /* TCPWriter.m */; };
23.43 - 2779051D0DE9E5BC00C6D295 /* Test.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461280DE49088003D9D3F /* Test.m */; };
23.44 - 2779051E0DE9E5BC00C6D295 /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704612A0DE49088003D9D3F /* Logging.m */; };
23.45 - 2779051F0DE9E5BC00C6D295 /* ExceptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461350DE4918D003D9D3F /* ExceptionUtils.m */; };
23.46 - 277905200DE9E5BC00C6D295 /* Target.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461460DE491A6003D9D3F /* Target.m */; };
23.47 - 277905220DE9E5BC00C6D295 /* CollectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461870DE49634003D9D3F /* CollectionUtils.m */; };
23.48 - 277905230DE9E5BC00C6D295 /* BLIPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D5EC060DE5FEDE00CD84FA /* BLIPRequest.m */; };
23.49 277905240DE9E5BC00C6D295 /* BLIPEchoServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 277903D60DE8EE4800C6D295 /* BLIPEchoServer.m */; };
23.50 - 277905260DE9E5BC00C6D295 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
23.51 - 277905270DE9E5BC00C6D295 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2704618B0DE49652003D9D3F /* libz.dylib */; };
23.52 - 277905280DE9E5BC00C6D295 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 270461910DE4975C003D9D3F /* CoreServices.framework */; };
23.53 277905300DE9ED9100C6D295 /* MYUtilitiesTest_main.m in Sources */ = {isa = PBXBuildFile; fileRef = 270462C10DE4A64B003D9D3F /* MYUtilitiesTest_main.m */; };
23.54 2779053B0DE9EDAA00C6D295 /* BLIPTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460FE0DE49030003D9D3F /* BLIPTest.m */; };
23.55 - 277ECFBC0E2A73A100D756BB /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2704618B0DE49652003D9D3F /* libz.dylib */; };
23.56 + 278C1A3D0F9F687800954AE1 /* PortMapperTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1A340F9F687800954AE1 /* PortMapperTest.m */; };
23.57 + 278C1A3E0F9F687800954AE1 /* MYPortMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1A360F9F687800954AE1 /* MYPortMapper.m */; };
23.58 + 278C1BA60F9F92EA00954AE1 /* MYBonjourBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1B9F0F9F92EA00954AE1 /* MYBonjourBrowser.m */; };
23.59 + 278C1BA70F9F92EA00954AE1 /* MYBonjourService.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1BA10F9F92EA00954AE1 /* MYBonjourService.m */; };
23.60 + 278C1BB90F9F975700954AE1 /* ConcurrentOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1BB60F9F975700954AE1 /* ConcurrentOperation.m */; };
23.61 + 279DDA590F9E2DFA00D75D91 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279DD99E0F9E290500D75D91 /* Foundation.framework */; };
23.62 + 279DDAE00F9E2E0F00D75D91 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279DD99E0F9E290500D75D91 /* Foundation.framework */; };
23.63 + 279DDC4E0F9E2E2700D75D91 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279DD9B30F9E296E00D75D91 /* CoreServices.framework */; };
23.64 + 279DDC520F9E2E3A00D75D91 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 279DD9B10F9E296200D75D91 /* libz.dylib */; };
23.65 + 279DDC970F9E2EF400D75D91 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279DD99E0F9E290500D75D91 /* Foundation.framework */; };
23.66 + 279DDC9B0F9E2F2A00D75D91 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279DDC9A0F9E2F2A00D75D91 /* AppKit.framework */; };
23.67 + 279DDCD10F9E38DD00D75D91 /* BLIPEchoClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 277903E90DE8F08100C6D295 /* BLIPEchoClient.m */; };
23.68 + 279E8FA10F9FDD2600608D8D /* BLIPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F40DE49030003D9D3F /* BLIPConnection.m */; };
23.69 + 279E8FA20F9FDD2600608D8D /* BLIPDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F60DE49030003D9D3F /* BLIPDispatcher.m */; };
23.70 + 279E8FA30F9FDD2600608D8D /* BLIPMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460F90DE49030003D9D3F /* BLIPMessage.m */; };
23.71 + 279E8FA40F9FDD2600608D8D /* BLIPProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460FB0DE49030003D9D3F /* BLIPProperties.m */; };
23.72 + 279E8FA50F9FDD2600608D8D /* BLIPReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460FD0DE49030003D9D3F /* BLIPReader.m */; };
23.73 + 279E8FA60F9FDD2600608D8D /* BLIPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D5EC060DE5FEDE00CD84FA /* BLIPRequest.m */; };
23.74 + 279E8FA70F9FDD2600608D8D /* BLIPWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461000DE49030003D9D3F /* BLIPWriter.m */; };
23.75 + 279E8FA80F9FDD2600608D8D /* IPAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461020DE49030003D9D3F /* IPAddress.m */; };
23.76 + 279E8FA90F9FDD2600608D8D /* TCPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610A0DE49030003D9D3F /* TCPConnection.m */; };
23.77 + 279E8FAA0F9FDD2600608D8D /* TCPEndpoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610C0DE49030003D9D3F /* TCPEndpoint.m */; };
23.78 + 279E8FAB0F9FDD2600608D8D /* TCPListener.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704610E0DE49030003D9D3F /* TCPListener.m */; };
23.79 + 279E8FAC0F9FDD2600608D8D /* TCPStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461100DE49030003D9D3F /* TCPStream.m */; };
23.80 + 279E8FAD0F9FDD2600608D8D /* TCPWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461120DE49030003D9D3F /* TCPWriter.m */; };
23.81 + 279E8FAE0F9FDD2600608D8D /* CollectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461870DE49634003D9D3F /* CollectionUtils.m */; };
23.82 + 279E8FAF0F9FDD2600608D8D /* ExceptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461350DE4918D003D9D3F /* ExceptionUtils.m */; };
23.83 + 279E8FB00F9FDD2600608D8D /* GTMNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E0DBEF0DF3450F00E7F648 /* GTMNSData+zlib.m */; };
23.84 + 279E8FB10F9FDD2600608D8D /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = 2704612A0DE49088003D9D3F /* Logging.m */; };
23.85 + 279E8FB20F9FDD2600608D8D /* Target.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461460DE491A6003D9D3F /* Target.m */; };
23.86 + 279E8FB30F9FDD2600608D8D /* Test.m in Sources */ = {isa = PBXBuildFile; fileRef = 270461280DE49088003D9D3F /* Test.m */; };
23.87 + 279E8FB40F9FDD2600608D8D /* PortMapperTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1A340F9F687800954AE1 /* PortMapperTest.m */; };
23.88 + 279E8FB50F9FDD2600608D8D /* MYPortMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1A360F9F687800954AE1 /* MYPortMapper.m */; };
23.89 + 279E8FB60F9FDD2600608D8D /* MYBonjourBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1B9F0F9F92EA00954AE1 /* MYBonjourBrowser.m */; };
23.90 + 279E8FB70F9FDD2600608D8D /* MYBonjourService.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1BA10F9F92EA00954AE1 /* MYBonjourService.m */; };
23.91 + 279E8FB80F9FDD2600608D8D /* ConcurrentOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 278C1BB60F9F975700954AE1 /* ConcurrentOperation.m */; };
23.92 + 279E8FD70F9FDDE900608D8D /* libMYNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 279E8F9E0F9FDD0800608D8D /* libMYNetwork.a */; };
23.93 + 279E8FEF0F9FDE5A00608D8D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2777C9100F7602A7007F8D30 /* Security.framework */; };
23.94 + 279E8FFA0F9FDEEB00608D8D /* libMYNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 279E8F9E0F9FDD0800608D8D /* libMYNetwork.a */; };
23.95 + 279E8FFC0F9FDEFB00608D8D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279DD9B30F9E296E00D75D91 /* CoreServices.framework */; };
23.96 + 279E8FFE0F9FDF0600608D8D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2777C9100F7602A7007F8D30 /* Security.framework */; };
23.97 27D5EC070DE5FEDE00CD84FA /* BLIPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D5EC060DE5FEDE00CD84FA /* BLIPRequest.m */; };
23.98 - 27E0DBF00DF3450F00E7F648 /* GTMNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E0DBEF0DF3450F00E7F648 /* GTMNSData+zlib.m */; };
23.99 27E0DBF10DF3450F00E7F648 /* GTMNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E0DBEF0DF3450F00E7F648 /* GTMNSData+zlib.m */; };
23.100 - 27E0DBF20DF3450F00E7F648 /* GTMNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E0DBEF0DF3450F00E7F648 /* GTMNSData+zlib.m */; };
23.101 - 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
23.102 /* End PBXBuildFile section */
23.103
23.104 +/* Begin PBXContainerItemProxy section */
23.105 + 279E8FD50F9FDDD900608D8D /* PBXContainerItemProxy */ = {
23.106 + isa = PBXContainerItemProxy;
23.107 + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
23.108 + proxyType = 1;
23.109 + remoteGlobalIDString = 279E8F9D0F9FDD0800608D8D /* Library */;
23.110 + remoteInfo = Library;
23.111 + };
23.112 + 279E8FF80F9FDECD00608D8D /* PBXContainerItemProxy */ = {
23.113 + isa = PBXContainerItemProxy;
23.114 + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
23.115 + proxyType = 1;
23.116 + remoteGlobalIDString = 279E8F9D0F9FDD0800608D8D /* Library */;
23.117 + remoteInfo = Library;
23.118 + };
23.119 +/* End PBXContainerItemProxy section */
23.120 +
23.121 /* Begin PBXCopyFilesBuildPhase section */
23.122 277905290DE9E5BC00C6D295 /* CopyFiles */ = {
23.123 isa = PBXCopyFilesBuildPhase;
23.124 @@ -100,7 +114,6 @@
23.125 /* End PBXCopyFilesBuildPhase section */
23.126
23.127 /* Begin PBXFileReference section */
23.128 - 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
23.129 270460F30DE49030003D9D3F /* BLIPConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLIPConnection.h; sourceTree = "<group>"; };
23.130 270460F40DE49030003D9D3F /* BLIPConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BLIPConnection.m; sourceTree = "<group>"; };
23.131 270460F50DE49030003D9D3F /* BLIPDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLIPDispatcher.h; sourceTree = "<group>"; };
23.132 @@ -112,7 +125,7 @@
23.133 270460FB0DE49030003D9D3F /* BLIPProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BLIPProperties.m; sourceTree = "<group>"; };
23.134 270460FC0DE49030003D9D3F /* BLIPReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLIPReader.h; sourceTree = "<group>"; };
23.135 270460FD0DE49030003D9D3F /* BLIPReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BLIPReader.m; sourceTree = "<group>"; };
23.136 - 270460FE0DE49030003D9D3F /* BLIPTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BLIPTest.m; path = BLIP/BLIPTest.m; sourceTree = "<group>"; };
23.137 + 270460FE0DE49030003D9D3F /* BLIPTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BLIPTest.m; path = ../BLIPTest.m; sourceTree = "<group>"; };
23.138 270460FF0DE49030003D9D3F /* BLIPWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLIPWriter.h; sourceTree = "<group>"; };
23.139 270461000DE49030003D9D3F /* BLIPWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BLIPWriter.m; sourceTree = "<group>"; };
23.140 270461010DE49030003D9D3F /* IPAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IPAddress.h; sourceTree = "<group>"; };
23.141 @@ -139,11 +152,13 @@
23.142 270461720DE49340003D9D3F /* MYNetwork */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MYNetwork; sourceTree = BUILT_PRODUCTS_DIR; };
23.143 270461870DE49634003D9D3F /* CollectionUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollectionUtils.m; sourceTree = "<group>"; };
23.144 270461880DE49634003D9D3F /* CollectionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionUtils.h; sourceTree = "<group>"; };
23.145 - 2704618B0DE49652003D9D3F /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
23.146 - 270461910DE4975C003D9D3F /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
23.147 270462C00DE4A639003D9D3F /* MYUtilities_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYUtilities_Prefix.pch; sourceTree = "<group>"; };
23.148 270462C10DE4A64B003D9D3F /* MYUtilitiesTest_main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYUtilitiesTest_main.m; sourceTree = "<group>"; };
23.149 270462C30DE4A65B003D9D3F /* BLIP Overview.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "BLIP Overview.txt"; path = "BLIP/BLIP Overview.txt"; sourceTree = "<group>"; wrapsLines = 1; };
23.150 + 2706F1D80F9D3EF300292CCF /* SecurityInterface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityInterface.framework; path = System/Library/Frameworks/SecurityInterface.framework; sourceTree = SDKROOT; };
23.151 + 274122DD0F9CDD1600F21842 /* MYUtilities_Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = MYUtilities_Debug.xcconfig; sourceTree = "<group>"; };
23.152 + 274122DE0F9CDD1600F21842 /* MYUtilities_Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = MYUtilities_Release.xcconfig; sourceTree = "<group>"; };
23.153 + 2777C9100F7602A7007F8D30 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
23.154 277903830DE8C2DD00C6D295 /* maindocs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = maindocs.h; sourceTree = "<group>"; wrapsLines = 1; };
23.155 277903D50DE8EE4800C6D295 /* BLIPEchoServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLIPEchoServer.h; sourceTree = "<group>"; };
23.156 277903D60DE8EE4800C6D295 /* BLIPEchoServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BLIPEchoServer.m; sourceTree = "<group>"; };
23.157 @@ -154,6 +169,21 @@
23.158 277904280DE91C7900C6D295 /* BLIP Echo Client-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BLIP Echo Client-Info.plist"; sourceTree = "<group>"; };
23.159 2779048A0DE9204300C6D295 /* BLIPEchoClient.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BLIPEchoClient.xib; sourceTree = "<group>"; };
23.160 2779052D0DE9E5BC00C6D295 /* BLIPEchoServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BLIPEchoServer; sourceTree = BUILT_PRODUCTS_DIR; };
23.161 + 278C1A340F9F687800954AE1 /* PortMapperTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PortMapperTest.m; sourceTree = "<group>"; };
23.162 + 278C1A350F9F687800954AE1 /* MYPortMapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYPortMapper.h; sourceTree = "<group>"; };
23.163 + 278C1A360F9F687800954AE1 /* MYPortMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYPortMapper.m; sourceTree = "<group>"; };
23.164 + 278C1B9E0F9F92EA00954AE1 /* MYBonjourBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYBonjourBrowser.h; sourceTree = "<group>"; };
23.165 + 278C1B9F0F9F92EA00954AE1 /* MYBonjourBrowser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYBonjourBrowser.m; sourceTree = "<group>"; };
23.166 + 278C1BA00F9F92EA00954AE1 /* MYBonjourService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYBonjourService.h; sourceTree = "<group>"; };
23.167 + 278C1BA10F9F92EA00954AE1 /* MYBonjourService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYBonjourService.m; sourceTree = "<group>"; };
23.168 + 278C1BB50F9F975700954AE1 /* ConcurrentOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcurrentOperation.h; sourceTree = "<group>"; };
23.169 + 278C1BB60F9F975700954AE1 /* ConcurrentOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConcurrentOperation.m; sourceTree = "<group>"; };
23.170 + 279DD99E0F9E290500D75D91 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
23.171 + 279DD9B10F9E296200D75D91 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
23.172 + 279DD9B30F9E296E00D75D91 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
23.173 + 279DDC9A0F9E2F2A00D75D91 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
23.174 + 279DDCCB0F9E381500D75D91 /* MYNetwork.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYNetwork.h; sourceTree = "<group>"; };
23.175 + 279E8F9E0F9FDD0800608D8D /* libMYNetwork.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMYNetwork.a; sourceTree = BUILT_PRODUCTS_DIR; };
23.176 27D5EC050DE5FEDE00CD84FA /* BLIPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLIPRequest.h; sourceTree = "<group>"; };
23.177 27D5EC060DE5FEDE00CD84FA /* BLIPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BLIPRequest.m; sourceTree = "<group>"; };
23.178 27E0DBED0DF3450F00E7F648 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDefines.h; sourceTree = "<group>"; };
23.179 @@ -166,7 +196,10 @@
23.180 isa = PBXFrameworksBuildPhase;
23.181 buildActionMask = 2147483647;
23.182 files = (
23.183 - 277ECFBC0E2A73A100D756BB /* libz.dylib in Frameworks */,
23.184 + 279DDC970F9E2EF400D75D91 /* Foundation.framework in Frameworks */,
23.185 + 279DDC9B0F9E2F2A00D75D91 /* AppKit.framework in Frameworks */,
23.186 + 279E8FD70F9FDDE900608D8D /* libMYNetwork.a in Frameworks */,
23.187 + 279E8FEF0F9FDE5A00608D8D /* Security.framework in Frameworks */,
23.188 );
23.189 runOnlyForDeploymentPostprocessing = 0;
23.190 };
23.191 @@ -174,9 +207,17 @@
23.192 isa = PBXFrameworksBuildPhase;
23.193 buildActionMask = 2147483647;
23.194 files = (
23.195 - 277905260DE9E5BC00C6D295 /* Foundation.framework in Frameworks */,
23.196 - 277905270DE9E5BC00C6D295 /* libz.dylib in Frameworks */,
23.197 - 277905280DE9E5BC00C6D295 /* CoreServices.framework in Frameworks */,
23.198 + 279DDAE00F9E2E0F00D75D91 /* Foundation.framework in Frameworks */,
23.199 + 279E8FFA0F9FDEEB00608D8D /* libMYNetwork.a in Frameworks */,
23.200 + 279E8FFC0F9FDEFB00608D8D /* CoreServices.framework in Frameworks */,
23.201 + 279E8FFE0F9FDF0600608D8D /* Security.framework in Frameworks */,
23.202 + );
23.203 + runOnlyForDeploymentPostprocessing = 0;
23.204 + };
23.205 + 279E8F9C0F9FDD0800608D8D /* Frameworks */ = {
23.206 + isa = PBXFrameworksBuildPhase;
23.207 + buildActionMask = 2147483647;
23.208 + files = (
23.209 );
23.210 runOnlyForDeploymentPostprocessing = 0;
23.211 };
23.212 @@ -184,9 +225,11 @@
23.213 isa = PBXFrameworksBuildPhase;
23.214 buildActionMask = 2147483647;
23.215 files = (
23.216 - 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */,
23.217 - 2704618C0DE49652003D9D3F /* libz.dylib in Frameworks */,
23.218 - 270461920DE4975D003D9D3F /* CoreServices.framework in Frameworks */,
23.219 + 2777C9110F7602A7007F8D30 /* Security.framework in Frameworks */,
23.220 + 2706F1D90F9D3EF300292CCF /* SecurityInterface.framework in Frameworks */,
23.221 + 279DDA590F9E2DFA00D75D91 /* Foundation.framework in Frameworks */,
23.222 + 279DDC4E0F9E2E2700D75D91 /* CoreServices.framework in Frameworks */,
23.223 + 279DDC520F9E2E3A00D75D91 /* libz.dylib in Frameworks */,
23.224 );
23.225 runOnlyForDeploymentPostprocessing = 0;
23.226 };
23.227 @@ -200,7 +243,6 @@
23.228 277903830DE8C2DD00C6D295 /* maindocs.h */,
23.229 270460F00DE49030003D9D3F /* MYNetwork */,
23.230 270461220DE49055003D9D3F /* MYUtilities */,
23.231 - 270460FE0DE49030003D9D3F /* BLIPTest.m */,
23.232 277903E70DE8F05F00C6D295 /* Demo */,
23.233 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
23.234 1AB674ADFE9D54B511CA2CBB /* Products */,
23.235 @@ -211,9 +253,12 @@
23.236 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
23.237 isa = PBXGroup;
23.238 children = (
23.239 - 270461910DE4975C003D9D3F /* CoreServices.framework */,
23.240 - 08FB779EFE84155DC02AAC07 /* Foundation.framework */,
23.241 - 2704618B0DE49652003D9D3F /* libz.dylib */,
23.242 + 279DDC9A0F9E2F2A00D75D91 /* AppKit.framework */,
23.243 + 279DD9B30F9E296E00D75D91 /* CoreServices.framework */,
23.244 + 279DD99E0F9E290500D75D91 /* Foundation.framework */,
23.245 + 2777C9100F7602A7007F8D30 /* Security.framework */,
23.246 + 2706F1D80F9D3EF300292CCF /* SecurityInterface.framework */,
23.247 + 279DD9B10F9E296200D75D91 /* libz.dylib */,
23.248 );
23.249 name = "External Frameworks and Libraries";
23.250 sourceTree = "<group>";
23.251 @@ -224,6 +269,7 @@
23.252 270461720DE49340003D9D3F /* MYNetwork */,
23.253 277904260DE91C7900C6D295 /* BLIP Echo Client.app */,
23.254 2779052D0DE9E5BC00C6D295 /* BLIPEchoServer */,
23.255 + 279E8F9E0F9FDD0800608D8D /* libMYNetwork.a */,
23.256 );
23.257 name = Products;
23.258 sourceTree = "<group>";
23.259 @@ -231,10 +277,13 @@
23.260 270460F00DE49030003D9D3F /* MYNetwork */ = {
23.261 isa = PBXGroup;
23.262 children = (
23.263 + 279DDCCB0F9E381500D75D91 /* MYNetwork.h */,
23.264 270461010DE49030003D9D3F /* IPAddress.h */,
23.265 270461020DE49030003D9D3F /* IPAddress.m */,
23.266 270461070DE49030003D9D3F /* TCP */,
23.267 + 278C1A320F9F687800954AE1 /* PortMapper */,
23.268 270460F10DE49030003D9D3F /* BLIP */,
23.269 + 278C1B9D0F9F92D600954AE1 /* Bonjour */,
23.270 );
23.271 name = MYNetwork;
23.272 sourceTree = "<group>";
23.273 @@ -283,6 +332,8 @@
23.274 270461220DE49055003D9D3F /* MYUtilities */ = {
23.275 isa = PBXGroup;
23.276 children = (
23.277 + 278C1BB50F9F975700954AE1 /* ConcurrentOperation.h */,
23.278 + 278C1BB60F9F975700954AE1 /* ConcurrentOperation.m */,
23.279 270462C10DE4A64B003D9D3F /* MYUtilitiesTest_main.m */,
23.280 270462C00DE4A639003D9D3F /* MYUtilities_Prefix.pch */,
23.281 270461880DE49634003D9D3F /* CollectionUtils.h */,
23.282 @@ -295,6 +346,8 @@
23.283 270461460DE491A6003D9D3F /* Target.m */,
23.284 270461290DE49088003D9D3F /* Test.h */,
23.285 270461280DE49088003D9D3F /* Test.m */,
23.286 + 274122DD0F9CDD1600F21842 /* MYUtilities_Debug.xcconfig */,
23.287 + 274122DE0F9CDD1600F21842 /* MYUtilities_Release.xcconfig */,
23.288 27E0DBEC0DF3450F00E7F648 /* GoogleToolboxSubset */,
23.289 );
23.290 name = MYUtilities;
23.291 @@ -304,6 +357,7 @@
23.292 277903E70DE8F05F00C6D295 /* Demo */ = {
23.293 isa = PBXGroup;
23.294 children = (
23.295 + 270460FE0DE49030003D9D3F /* BLIPTest.m */,
23.296 277903D50DE8EE4800C6D295 /* BLIPEchoServer.h */,
23.297 277903D60DE8EE4800C6D295 /* BLIPEchoServer.m */,
23.298 277903E80DE8F08100C6D295 /* BLIPEchoClient.h */,
23.299 @@ -315,6 +369,27 @@
23.300 path = BLIP/Demo;
23.301 sourceTree = "<group>";
23.302 };
23.303 + 278C1A320F9F687800954AE1 /* PortMapper */ = {
23.304 + isa = PBXGroup;
23.305 + children = (
23.306 + 278C1A350F9F687800954AE1 /* MYPortMapper.h */,
23.307 + 278C1A360F9F687800954AE1 /* MYPortMapper.m */,
23.308 + 278C1A340F9F687800954AE1 /* PortMapperTest.m */,
23.309 + );
23.310 + path = PortMapper;
23.311 + sourceTree = "<group>";
23.312 + };
23.313 + 278C1B9D0F9F92D600954AE1 /* Bonjour */ = {
23.314 + isa = PBXGroup;
23.315 + children = (
23.316 + 278C1B9E0F9F92EA00954AE1 /* MYBonjourBrowser.h */,
23.317 + 278C1B9F0F9F92EA00954AE1 /* MYBonjourBrowser.m */,
23.318 + 278C1BA00F9F92EA00954AE1 /* MYBonjourService.h */,
23.319 + 278C1BA10F9F92EA00954AE1 /* MYBonjourService.m */,
23.320 + );
23.321 + path = Bonjour;
23.322 + sourceTree = "<group>";
23.323 + };
23.324 27E0DBEC0DF3450F00E7F648 /* GoogleToolboxSubset */ = {
23.325 isa = PBXGroup;
23.326 children = (
23.327 @@ -327,6 +402,16 @@
23.328 };
23.329 /* End PBXGroup section */
23.330
23.331 +/* Begin PBXHeadersBuildPhase section */
23.332 + 279E8F9A0F9FDD0800608D8D /* Headers */ = {
23.333 + isa = PBXHeadersBuildPhase;
23.334 + buildActionMask = 2147483647;
23.335 + files = (
23.336 + );
23.337 + runOnlyForDeploymentPostprocessing = 0;
23.338 + };
23.339 +/* End PBXHeadersBuildPhase section */
23.340 +
23.341 /* Begin PBXNativeTarget section */
23.342 277904250DE91C7900C6D295 /* BLIP Echo Client */ = {
23.343 isa = PBXNativeTarget;
23.344 @@ -339,6 +424,7 @@
23.345 buildRules = (
23.346 );
23.347 dependencies = (
23.348 + 279E8FD60F9FDDD900608D8D /* PBXTargetDependency */,
23.349 );
23.350 name = "BLIP Echo Client";
23.351 productName = "BLIP Echo Client";
23.352 @@ -356,6 +442,7 @@
23.353 buildRules = (
23.354 );
23.355 dependencies = (
23.356 + 279E8FF90F9FDECD00608D8D /* PBXTargetDependency */,
23.357 );
23.358 name = "BLIP Echo Server";
23.359 productInstallPath = "$(HOME)/bin";
23.360 @@ -363,9 +450,26 @@
23.361 productReference = 2779052D0DE9E5BC00C6D295 /* BLIPEchoServer */;
23.362 productType = "com.apple.product-type.tool";
23.363 };
23.364 - 8DD76F960486AA7600D96B5E /* MYNetwork */ = {
23.365 + 279E8F9D0F9FDD0800608D8D /* Library */ = {
23.366 isa = PBXNativeTarget;
23.367 - buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "MYNetwork" */;
23.368 + buildConfigurationList = 279E8FCC0F9FDD8900608D8D /* Build configuration list for PBXNativeTarget "Library" */;
23.369 + buildPhases = (
23.370 + 279E8F9A0F9FDD0800608D8D /* Headers */,
23.371 + 279E8F9B0F9FDD0800608D8D /* Sources */,
23.372 + 279E8F9C0F9FDD0800608D8D /* Frameworks */,
23.373 + );
23.374 + buildRules = (
23.375 + );
23.376 + dependencies = (
23.377 + );
23.378 + name = Library;
23.379 + productName = Library;
23.380 + productReference = 279E8F9E0F9FDD0800608D8D /* libMYNetwork.a */;
23.381 + productType = "com.apple.product-type.library.static";
23.382 + };
23.383 + 8DD76F960486AA7600D96B5E /* SelfTest */ = {
23.384 + isa = PBXNativeTarget;
23.385 + buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "SelfTest" */;
23.386 buildPhases = (
23.387 8DD76F990486AA7600D96B5E /* Sources */,
23.388 8DD76F9B0486AA7600D96B5E /* Frameworks */,
23.389 @@ -375,7 +479,7 @@
23.390 );
23.391 dependencies = (
23.392 );
23.393 - name = MYNetwork;
23.394 + name = SelfTest;
23.395 productInstallPath = "$(HOME)/bin";
23.396 productName = MYNetwork;
23.397 productReference = 270461720DE49340003D9D3F /* MYNetwork */;
23.398 @@ -393,7 +497,8 @@
23.399 projectDirPath = "";
23.400 projectRoot = "";
23.401 targets = (
23.402 - 8DD76F960486AA7600D96B5E /* MYNetwork */,
23.403 + 279E8F9D0F9FDD0800608D8D /* Library */,
23.404 + 8DD76F960486AA7600D96B5E /* SelfTest */,
23.405 277904250DE91C7900C6D295 /* BLIP Echo Client */,
23.406 2779050F0DE9E5BC00C6D295 /* BLIP Echo Server */,
23.407 );
23.408 @@ -416,26 +521,7 @@
23.409 isa = PBXSourcesBuildPhase;
23.410 buildActionMask = 2147483647;
23.411 files = (
23.412 - 277904330DE91DE600C6D295 /* BLIPConnection.m in Sources */,
23.413 - 277904340DE91DE700C6D295 /* BLIPDispatcher.m in Sources */,
23.414 - 277904350DE91DE800C6D295 /* BLIPEchoClient.m in Sources */,
23.415 - 277904370DE91DEB00C6D295 /* BLIPMessage.m in Sources */,
23.416 - 277904380DE91DEC00C6D295 /* BLIPProperties.m in Sources */,
23.417 - 277904390DE91DEE00C6D295 /* BLIPReader.m in Sources */,
23.418 - 2779043A0DE91DEF00C6D295 /* BLIPRequest.m in Sources */,
23.419 - 2779043C0DE91DF100C6D295 /* BLIPWriter.m in Sources */,
23.420 - 2779043D0DE91DF300C6D295 /* IPAddress.m in Sources */,
23.421 - 2779043E0DE91DF500C6D295 /* TCPConnection.m in Sources */,
23.422 - 2779043F0DE91DF800C6D295 /* TCPEndpoint.m in Sources */,
23.423 - 277904400DE91DF900C6D295 /* TCPListener.m in Sources */,
23.424 - 277904410DE91DFA00C6D295 /* TCPStream.m in Sources */,
23.425 - 277904420DE91DFC00C6D295 /* TCPWriter.m in Sources */,
23.426 - 277904440DE91E3500C6D295 /* CollectionUtils.m in Sources */,
23.427 - 277904450DE91E3600C6D295 /* ExceptionUtils.m in Sources */,
23.428 - 277904460DE91E3700C6D295 /* Logging.m in Sources */,
23.429 - 277904480DE91E3900C6D295 /* Target.m in Sources */,
23.430 - 277904490DE91E3A00C6D295 /* Test.m in Sources */,
23.431 - 27E0DBF00DF3450F00E7F648 /* GTMNSData+zlib.m in Sources */,
23.432 + 279DDCD10F9E38DD00D75D91 /* BLIPEchoClient.m in Sources */,
23.433 );
23.434 runOnlyForDeploymentPostprocessing = 0;
23.435 };
23.436 @@ -443,26 +529,38 @@
23.437 isa = PBXSourcesBuildPhase;
23.438 buildActionMask = 2147483647;
23.439 files = (
23.440 - 277905110DE9E5BC00C6D295 /* BLIPConnection.m in Sources */,
23.441 - 277905120DE9E5BC00C6D295 /* BLIPDispatcher.m in Sources */,
23.442 - 277905130DE9E5BC00C6D295 /* BLIPMessage.m in Sources */,
23.443 - 277905140DE9E5BC00C6D295 /* BLIPProperties.m in Sources */,
23.444 - 277905150DE9E5BC00C6D295 /* BLIPReader.m in Sources */,
23.445 - 277905160DE9E5BC00C6D295 /* BLIPWriter.m in Sources */,
23.446 - 277905170DE9E5BC00C6D295 /* IPAddress.m in Sources */,
23.447 - 277905180DE9E5BC00C6D295 /* TCPConnection.m in Sources */,
23.448 - 277905190DE9E5BC00C6D295 /* TCPEndpoint.m in Sources */,
23.449 - 2779051A0DE9E5BC00C6D295 /* TCPListener.m in Sources */,
23.450 - 2779051B0DE9E5BC00C6D295 /* TCPStream.m in Sources */,
23.451 - 2779051C0DE9E5BC00C6D295 /* TCPWriter.m in Sources */,
23.452 - 2779051D0DE9E5BC00C6D295 /* Test.m in Sources */,
23.453 - 2779051E0DE9E5BC00C6D295 /* Logging.m in Sources */,
23.454 - 2779051F0DE9E5BC00C6D295 /* ExceptionUtils.m in Sources */,
23.455 - 277905200DE9E5BC00C6D295 /* Target.m in Sources */,
23.456 - 277905220DE9E5BC00C6D295 /* CollectionUtils.m in Sources */,
23.457 - 277905230DE9E5BC00C6D295 /* BLIPRequest.m in Sources */,
23.458 277905240DE9E5BC00C6D295 /* BLIPEchoServer.m in Sources */,
23.459 - 27E0DBF20DF3450F00E7F648 /* GTMNSData+zlib.m in Sources */,
23.460 + );
23.461 + runOnlyForDeploymentPostprocessing = 0;
23.462 + };
23.463 + 279E8F9B0F9FDD0800608D8D /* Sources */ = {
23.464 + isa = PBXSourcesBuildPhase;
23.465 + buildActionMask = 2147483647;
23.466 + files = (
23.467 + 279E8FA10F9FDD2600608D8D /* BLIPConnection.m in Sources */,
23.468 + 279E8FA20F9FDD2600608D8D /* BLIPDispatcher.m in Sources */,
23.469 + 279E8FA30F9FDD2600608D8D /* BLIPMessage.m in Sources */,
23.470 + 279E8FA40F9FDD2600608D8D /* BLIPProperties.m in Sources */,
23.471 + 279E8FA50F9FDD2600608D8D /* BLIPReader.m in Sources */,
23.472 + 279E8FA60F9FDD2600608D8D /* BLIPRequest.m in Sources */,
23.473 + 279E8FA70F9FDD2600608D8D /* BLIPWriter.m in Sources */,
23.474 + 279E8FA80F9FDD2600608D8D /* IPAddress.m in Sources */,
23.475 + 279E8FA90F9FDD2600608D8D /* TCPConnection.m in Sources */,
23.476 + 279E8FAA0F9FDD2600608D8D /* TCPEndpoint.m in Sources */,
23.477 + 279E8FAB0F9FDD2600608D8D /* TCPListener.m in Sources */,
23.478 + 279E8FAC0F9FDD2600608D8D /* TCPStream.m in Sources */,
23.479 + 279E8FAD0F9FDD2600608D8D /* TCPWriter.m in Sources */,
23.480 + 279E8FAE0F9FDD2600608D8D /* CollectionUtils.m in Sources */,
23.481 + 279E8FAF0F9FDD2600608D8D /* ExceptionUtils.m in Sources */,
23.482 + 279E8FB00F9FDD2600608D8D /* GTMNSData+zlib.m in Sources */,
23.483 + 279E8FB10F9FDD2600608D8D /* Logging.m in Sources */,
23.484 + 279E8FB20F9FDD2600608D8D /* Target.m in Sources */,
23.485 + 279E8FB30F9FDD2600608D8D /* Test.m in Sources */,
23.486 + 279E8FB40F9FDD2600608D8D /* PortMapperTest.m in Sources */,
23.487 + 279E8FB50F9FDD2600608D8D /* MYPortMapper.m in Sources */,
23.488 + 279E8FB60F9FDD2600608D8D /* MYBonjourBrowser.m in Sources */,
23.489 + 279E8FB70F9FDD2600608D8D /* MYBonjourService.m in Sources */,
23.490 + 279E8FB80F9FDD2600608D8D /* ConcurrentOperation.m in Sources */,
23.491 );
23.492 runOnlyForDeploymentPostprocessing = 0;
23.493 };
23.494 @@ -491,26 +589,33 @@
23.495 277905300DE9ED9100C6D295 /* MYUtilitiesTest_main.m in Sources */,
23.496 2779053B0DE9EDAA00C6D295 /* BLIPTest.m in Sources */,
23.497 27E0DBF10DF3450F00E7F648 /* GTMNSData+zlib.m in Sources */,
23.498 + 278C1A3D0F9F687800954AE1 /* PortMapperTest.m in Sources */,
23.499 + 278C1A3E0F9F687800954AE1 /* MYPortMapper.m in Sources */,
23.500 + 278C1BA60F9F92EA00954AE1 /* MYBonjourBrowser.m in Sources */,
23.501 + 278C1BA70F9F92EA00954AE1 /* MYBonjourService.m in Sources */,
23.502 + 278C1BB90F9F975700954AE1 /* ConcurrentOperation.m in Sources */,
23.503 );
23.504 runOnlyForDeploymentPostprocessing = 0;
23.505 };
23.506 /* End PBXSourcesBuildPhase section */
23.507
23.508 +/* Begin PBXTargetDependency section */
23.509 + 279E8FD60F9FDDD900608D8D /* PBXTargetDependency */ = {
23.510 + isa = PBXTargetDependency;
23.511 + target = 279E8F9D0F9FDD0800608D8D /* Library */;
23.512 + targetProxy = 279E8FD50F9FDDD900608D8D /* PBXContainerItemProxy */;
23.513 + };
23.514 + 279E8FF90F9FDECD00608D8D /* PBXTargetDependency */ = {
23.515 + isa = PBXTargetDependency;
23.516 + target = 279E8F9D0F9FDD0800608D8D /* Library */;
23.517 + targetProxy = 279E8FF80F9FDECD00608D8D /* PBXContainerItemProxy */;
23.518 + };
23.519 +/* End PBXTargetDependency section */
23.520 +
23.521 /* Begin XCBuildConfiguration section */
23.522 1DEB927508733DD40010E9CD /* Debug */ = {
23.523 isa = XCBuildConfiguration;
23.524 buildSettings = {
23.525 - ALWAYS_SEARCH_USER_PATHS = NO;
23.526 - COPY_PHASE_STRIP = NO;
23.527 - GCC_C_LANGUAGE_STANDARD = c99;
23.528 - GCC_DYNAMIC_NO_PIC = NO;
23.529 - GCC_ENABLE_FIX_AND_CONTINUE = YES;
23.530 - GCC_MODEL_TUNING = G5;
23.531 - GCC_OPTIMIZATION_LEVEL = 0;
23.532 - GCC_PRECOMPILE_PREFIX_HEADER = YES;
23.533 - GCC_PREFIX_HEADER = ../MYUtilities/MYUtilities_Prefix.pch;
23.534 - GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
23.535 - INSTALL_PATH = /usr/local/bin;
23.536 PRODUCT_NAME = MYNetwork;
23.537 };
23.538 name = Debug;
23.539 @@ -518,68 +623,31 @@
23.540 1DEB927608733DD40010E9CD /* Release */ = {
23.541 isa = XCBuildConfiguration;
23.542 buildSettings = {
23.543 - ALWAYS_SEARCH_USER_PATHS = NO;
23.544 - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
23.545 - GCC_C_LANGUAGE_STANDARD = c99;
23.546 - GCC_MODEL_TUNING = G5;
23.547 - GCC_PRECOMPILE_PREFIX_HEADER = YES;
23.548 - GCC_PREFIX_HEADER = ../MYUtilities/MYUtilities_Prefix.pch;
23.549 - INSTALL_PATH = /usr/local/bin;
23.550 PRODUCT_NAME = MYNetwork;
23.551 };
23.552 name = Release;
23.553 };
23.554 1DEB927908733DD40010E9CD /* Debug */ = {
23.555 isa = XCBuildConfiguration;
23.556 + baseConfigurationReference = 274122DD0F9CDD1600F21842 /* MYUtilities_Debug.xcconfig */;
23.557 buildSettings = {
23.558 - ARCHS = "$(ARCHS_STANDARD_32_BIT)";
23.559 - GCC_C_LANGUAGE_STANDARD = c99;
23.560 - GCC_OPTIMIZATION_LEVEL = 0;
23.561 - GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
23.562 - GCC_TREAT_WARNINGS_AS_ERRORS = YES;
23.563 - GCC_WARN_ABOUT_RETURN_TYPE = YES;
23.564 - GCC_WARN_UNUSED_VARIABLE = YES;
23.565 - ONLY_ACTIVE_ARCH = YES;
23.566 - PREBINDING = NO;
23.567 SDKROOT = macosx10.5;
23.568 - WARNING_CFLAGS = "-Wall";
23.569 };
23.570 name = Debug;
23.571 };
23.572 1DEB927A08733DD40010E9CD /* Release */ = {
23.573 isa = XCBuildConfiguration;
23.574 + baseConfigurationReference = 274122DE0F9CDD1600F21842 /* MYUtilities_Release.xcconfig */;
23.575 buildSettings = {
23.576 - ARCHS = "$(ARCHS_STANDARD_32_BIT)";
23.577 - GCC_C_LANGUAGE_STANDARD = c99;
23.578 - GCC_TREAT_WARNINGS_AS_ERRORS = YES;
23.579 - GCC_WARN_ABOUT_RETURN_TYPE = YES;
23.580 - GCC_WARN_UNUSED_VARIABLE = YES;
23.581 - PREBINDING = NO;
23.582 SDKROOT = macosx10.5;
23.583 - WARNING_CFLAGS = "-Wall";
23.584 };
23.585 name = Release;
23.586 };
23.587 277904290DE91C7A00C6D295 /* Debug */ = {
23.588 isa = XCBuildConfiguration;
23.589 buildSettings = {
23.590 - ALWAYS_SEARCH_USER_PATHS = NO;
23.591 - COPY_PHASE_STRIP = NO;
23.592 - GCC_DYNAMIC_NO_PIC = NO;
23.593 - GCC_ENABLE_FIX_AND_CONTINUE = YES;
23.594 - GCC_MODEL_TUNING = G5;
23.595 - GCC_OPTIMIZATION_LEVEL = 0;
23.596 - GCC_PRECOMPILE_PREFIX_HEADER = YES;
23.597 - GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
23.598 INFOPLIST_FILE = "BLIP/Demo/BLIP Echo Client-Info.plist";
23.599 INSTALL_PATH = "$(HOME)/Applications";
23.600 - OTHER_LDFLAGS = (
23.601 - "-framework",
23.602 - Foundation,
23.603 - "-framework",
23.604 - AppKit,
23.605 - );
23.606 - PREBINDING = NO;
23.607 PRODUCT_NAME = "BLIP Echo Client";
23.608 };
23.609 name = Debug;
23.610 @@ -587,41 +655,15 @@
23.611 2779042A0DE91C7A00C6D295 /* Release */ = {
23.612 isa = XCBuildConfiguration;
23.613 buildSettings = {
23.614 - ALWAYS_SEARCH_USER_PATHS = NO;
23.615 - COPY_PHASE_STRIP = YES;
23.616 - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
23.617 - GCC_ENABLE_FIX_AND_CONTINUE = NO;
23.618 - GCC_MODEL_TUNING = G5;
23.619 - GCC_PRECOMPILE_PREFIX_HEADER = YES;
23.620 - GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
23.621 INFOPLIST_FILE = "BLIP/Demo/BLIP Echo Client-Info.plist";
23.622 INSTALL_PATH = "$(HOME)/Applications";
23.623 - OTHER_LDFLAGS = (
23.624 - "-framework",
23.625 - Foundation,
23.626 - "-framework",
23.627 - AppKit,
23.628 - );
23.629 - PREBINDING = NO;
23.630 PRODUCT_NAME = "BLIP Echo Client";
23.631 - ZERO_LINK = NO;
23.632 };
23.633 name = Release;
23.634 };
23.635 2779052B0DE9E5BC00C6D295 /* Debug */ = {
23.636 isa = XCBuildConfiguration;
23.637 buildSettings = {
23.638 - ALWAYS_SEARCH_USER_PATHS = NO;
23.639 - COPY_PHASE_STRIP = NO;
23.640 - GCC_C_LANGUAGE_STANDARD = gnu99;
23.641 - GCC_DYNAMIC_NO_PIC = NO;
23.642 - GCC_ENABLE_FIX_AND_CONTINUE = YES;
23.643 - GCC_MODEL_TUNING = G5;
23.644 - GCC_OPTIMIZATION_LEVEL = 0;
23.645 - GCC_PRECOMPILE_PREFIX_HEADER = YES;
23.646 - GCC_PREFIX_HEADER = ../MYUtilities/MYUtilities_Prefix.pch;
23.647 - GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
23.648 - INSTALL_PATH = /usr/local/bin;
23.649 PRODUCT_NAME = BLIPEchoServer;
23.650 };
23.651 name = Debug;
23.652 @@ -629,21 +671,30 @@
23.653 2779052C0DE9E5BC00C6D295 /* Release */ = {
23.654 isa = XCBuildConfiguration;
23.655 buildSettings = {
23.656 - ALWAYS_SEARCH_USER_PATHS = NO;
23.657 - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
23.658 - GCC_C_LANGUAGE_STANDARD = gnu99;
23.659 - GCC_MODEL_TUNING = G5;
23.660 - GCC_PRECOMPILE_PREFIX_HEADER = YES;
23.661 - GCC_PREFIX_HEADER = MYNetwork_Prefix.pch;
23.662 - INSTALL_PATH = /usr/local/bin;
23.663 PRODUCT_NAME = BLIPEchoServer;
23.664 };
23.665 name = Release;
23.666 };
23.667 + 279E8F9F0F9FDD0900608D8D /* Debug */ = {
23.668 + isa = XCBuildConfiguration;
23.669 + buildSettings = {
23.670 + INSTALL_PATH = /usr/local/lib;
23.671 + PRODUCT_NAME = MYNetwork;
23.672 + };
23.673 + name = Debug;
23.674 + };
23.675 + 279E8FA00F9FDD0900608D8D /* Release */ = {
23.676 + isa = XCBuildConfiguration;
23.677 + buildSettings = {
23.678 + INSTALL_PATH = /usr/local/lib;
23.679 + PRODUCT_NAME = MYNetwork;
23.680 + };
23.681 + name = Release;
23.682 + };
23.683 /* End XCBuildConfiguration section */
23.684
23.685 /* Begin XCConfigurationList section */
23.686 - 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "MYNetwork" */ = {
23.687 + 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "SelfTest" */ = {
23.688 isa = XCConfigurationList;
23.689 buildConfigurations = (
23.690 1DEB927508733DD40010E9CD /* Debug */,
23.691 @@ -679,6 +730,15 @@
23.692 defaultConfigurationIsVisible = 0;
23.693 defaultConfigurationName = Release;
23.694 };
23.695 + 279E8FCC0F9FDD8900608D8D /* Build configuration list for PBXNativeTarget "Library" */ = {
23.696 + isa = XCConfigurationList;
23.697 + buildConfigurations = (
23.698 + 279E8F9F0F9FDD0900608D8D /* Debug */,
23.699 + 279E8FA00F9FDD0900608D8D /* Release */,
23.700 + );
23.701 + defaultConfigurationIsVisible = 0;
23.702 + defaultConfigurationName = Release;
23.703 + };
23.704 /* End XCConfigurationList section */
23.705 };
23.706 rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/PortMapper/MYPortMapper.h Wed Apr 22 16:45:39 2009 -0700
24.3 @@ -0,0 +1,119 @@
24.4 +//
24.5 +// MYPortMapper.m
24.6 +// MYNetwork
24.7 +//
24.8 +// Created by Jens Alfke on 1/4/08.
24.9 +// Copyright 2008 Jens Alfke. All rights reserved.
24.10 +//
24.11 +
24.12 +#import <Foundation/Foundation.h>
24.13 +#import <CoreFoundation/CFSocket.h>
24.14 +@class IPAddress;
24.15 +
24.16 +
24.17 +/* MYPortMapper attempts to make a particular network port on this computer publicly reachable
24.18 + for incoming connections, by "opening a hole" through a Network Address Translator
24.19 + (NAT) or firewall that may be in between the computer and the public Internet.
24.20 +
24.21 + The port mapping may fail if:
24.22 + * the NAT/router/firewall does not support either the UPnP or NAT-PMP protocols;
24.23 + * the device doesn't implement the protocols correctly (this happens);
24.24 + * the network administrator has disabled port-mapping;
24.25 + * there is a second layer of NAT/firewall (this happens in some ISP networks.)
24.26 +
24.27 + The PortMapper is asynchronous. It will take a nonzero amount of time to set up the
24.28 + mapping, and the mapping may change in the future as the network configuration changes.
24.29 + To be informed of changes, either use key-value observing to watch the "error" and
24.30 + "publicAddress" properties, or observe the MYPortMapperChangedNotification.
24.31 +
24.32 + Typical usage is to:
24.33 + * Start a network service that listens for incoming connections on a port
24.34 + * Open a MYPortMapper
24.35 + * When the MYPortMapper reports the public address and port of the mapping, you somehow
24.36 + notify other peers of that address and port, so they can connect to you.
24.37 + * When the MYPortMapper reports changes, you (somehow) notify peers of the changes.
24.38 + * When closing the network service, close the MYPortMapper object too.
24.39 +*/
24.40 +@interface MYPortMapper : NSObject
24.41 +{
24.42 + UInt16 _localPort, _desiredPublicPort;
24.43 + BOOL _mapTCP, _mapUDP;
24.44 + SInt32 _error;
24.45 + void* /*DNSServiceRef*/ _service; // Typed void* to avoid having to #include <dnssd.h>
24.46 + CFSocketRef _socket;
24.47 + CFRunLoopSourceRef _socketSource;
24.48 + IPAddress *_publicAddress, *_localAddress;
24.49 +}
24.50 +
24.51 +/** Initializes a PortMapper that will map the given local (private) port.
24.52 + By default it will map TCP and not UDP, and will not suggest a desired public port,
24.53 + but this can be configured by setting properties before opening the PortMapper. */
24.54 +- (id) initWithLocalPort: (UInt16)localPort;
24.55 +
24.56 +/** Initializes a PortMapper that will not map any ports.
24.57 + This is useful if you just want to find out your public IP address.
24.58 + (For a simplified, but synchronous, convenience method for this, see
24.59 + +findPublicAddress.) */
24.60 +- (id) initWithNullMapping;
24.61 +
24.62 +/** Should the TCP or UDP port, or both, be mapped? By default, TCP only.
24.63 + These properties have no effect if changed while the PortMapper is open. */
24.64 +@property BOOL mapTCP, mapUDP;
24.65 +
24.66 +/** You can set this to the public port number you'd like to get.
24.67 + It defaults to 0, which means "no preference".
24.68 + This property has no effect if changed while the PortMapper is open. */
24.69 +@property UInt16 desiredPublicPort;
24.70 +
24.71 +/** Opens the PortMapper, using the current settings of the above properties.
24.72 + Returns immediately; you can find out when the mapping is created or fails
24.73 + by observing the error/publicAddress/publicPort properties, or by listening
24.74 + for the PortMapperChangedNotification.
24.75 + It's very unlikely that this call will fail (return NO). If it does, it
24.76 + probably means that the mDNSResponder process isn't working. */
24.77 +- (BOOL) open;
24.78 +
24.79 +/** Blocks till the PortMapper finishes opening. Returns YES if it opened, NO on error.
24.80 + It's not usually a good idea to use this, as it will lock up your application
24.81 + until a response arrives from the NAT. Listen for asynchronous notifications instead.
24.82 + If called when the PortMapper is closed, it will call -open for you.
24.83 + If called when it's already open, it just returns YES. */
24.84 +- (BOOL) waitTillOpened;
24.85 +
24.86 +/** Closes the PortMapper, terminating any open port mapping. */
24.87 +- (void) close;
24.88 +
24.89 +/** The error status, a DNSServiceErrorType enum; nonzero if something went wrong.
24.90 + The most likely error is kDNSServiceErr_NATPortMappingUnsupported (-65564).
24.91 + This property is KV observable. */
24.92 +@property (readonly) SInt32 error;
24.93 +
24.94 +/** The known public IPv4 address/port, once it's been determined.
24.95 + This property is KV observable. */
24.96 +@property (readonly,retain) IPAddress* publicAddress;
24.97 +
24.98 +/** The current local address/port, as of the time the port mapping was last updated.
24.99 + The address part is of the main interface; the port is the specified local port.
24.100 + This property is KV observable. */
24.101 +@property (readonly,retain) IPAddress* localAddress;
24.102 +
24.103 +/** Returns YES if a non-null port mapping is in effect:
24.104 + that is, if the public address differs from the local one. */
24.105 +@property (readonly) BOOL isMapped;
24.106 +
24.107 +
24.108 +// UTILITY CLASS METHOD:
24.109 +
24.110 +/** Determine the main interface's public IP address, without mapping any ports.
24.111 + This method internally calls -waitTillOpened, so it may take a nontrivial amount
24.112 + of time (and will crank the runloop while it waits.)
24.113 + If you want to do this asynchronously, you should instead create a new
24.114 + MYPortMapper instance using -initWithNullMapping. */
24.115 ++ (IPAddress*) findPublicAddress;
24.116 +
24.117 +@end
24.118 +
24.119 +
24.120 +/** This notification is posted asynchronously when the status of a PortMapper
24.121 + (its error, publicAddress or publicPort) changes. */
24.122 +extern NSString* const MYPortMapperChangedNotification;
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/PortMapper/MYPortMapper.m Wed Apr 22 16:45:39 2009 -0700
25.3 @@ -0,0 +1,303 @@
25.4 +//
25.5 +// MYPortMapper.m
25.6 +// MYNetwork
25.7 +//
25.8 +// Created by Jens Alfke on 1/4/08.
25.9 +// Copyright 2008 Jens Alfke. All rights reserved.
25.10 +//
25.11 +
25.12 +#import "MYPortMapper.h"
25.13 +#import "IPAddress.h"
25.14 +#import "CollectionUtils.h"
25.15 +#import "Logging.h"
25.16 +#import "ExceptionUtils.h"
25.17 +
25.18 +#import <dns_sd.h>
25.19 +#import <sys/types.h>
25.20 +#import <sys/socket.h>
25.21 +#import <net/if.h>
25.22 +#import <netinet/in.h>
25.23 +#import <ifaddrs.h>
25.24 +
25.25 +
25.26 +NSString* const MYPortMapperChangedNotification = @"MYPortMapperChanged";
25.27 +
25.28 +
25.29 +@interface MYPortMapper ()
25.30 +// Redeclare these properties as settable, internally:
25.31 +@property (readwrite) SInt32 error;
25.32 +@property (retain) IPAddress* publicAddress, *localAddress;
25.33 +// Private getter:
25.34 +@property (readonly) void* _service;
25.35 +- (void) priv_updateLocalAddress;
25.36 +- (void) priv_disconnect;
25.37 +@end
25.38 +
25.39 +
25.40 +@implementation MYPortMapper
25.41 +
25.42 +
25.43 +- (id) initWithLocalPort: (UInt16)localPort
25.44 +{
25.45 + self = [super init];
25.46 + if (self != nil) {
25.47 + _localPort = localPort;
25.48 + _mapTCP = YES;
25.49 + [self priv_updateLocalAddress];
25.50 + }
25.51 + return self;
25.52 +}
25.53 +
25.54 +- (id) initWithNullMapping
25.55 +{
25.56 + // A PortMapper with no port or protocols will cause the DNSService to look up
25.57 + // our public address without creating a mapping.
25.58 + if ([self initWithLocalPort: 0]) {
25.59 + _mapTCP = _mapUDP = NO;
25.60 + }
25.61 + return self;
25.62 +}
25.63 +
25.64 +
25.65 +- (void) dealloc
25.66 +{
25.67 + if( _service )
25.68 + [self priv_disconnect];
25.69 + [_publicAddress release];
25.70 + [_localAddress release];
25.71 + [super dealloc];
25.72 +}
25.73 +
25.74 +- (void) finalize
25.75 +{
25.76 + if( _service )
25.77 + [self priv_disconnect];
25.78 + [super finalize];
25.79 +}
25.80 +
25.81 +
25.82 +@synthesize localAddress=_localAddress, publicAddress=_publicAddress,
25.83 + error=_error, _service=_service,
25.84 + mapTCP=_mapTCP, mapUDP=_mapUDP,
25.85 + desiredPublicPort=_desiredPublicPort;
25.86 +
25.87 +
25.88 +- (BOOL) isMapped
25.89 +{
25.90 + return ! $equal(_publicAddress,_localAddress);
25.91 +}
25.92 +
25.93 +- (void) priv_updateLocalAddress
25.94 +{
25.95 + IPAddress *localAddress = [IPAddress localAddressWithPort: _localPort];
25.96 + if (!$equal(localAddress,_localAddress))
25.97 + self.localAddress = localAddress;
25.98 +}
25.99 +
25.100 +
25.101 +static IPAddress* makeIPAddr( UInt32 rawAddr, UInt16 port ) {
25.102 + if (rawAddr)
25.103 + return [[[IPAddress alloc] initWithIPv4: rawAddr port: port] autorelease];
25.104 + else
25.105 + return nil;
25.106 +}
25.107 +
25.108 +/** Called whenever the port mapping changes (see comment for callback, below.) */
25.109 +- (void) priv_portMapStatus: (DNSServiceErrorType)errorCode
25.110 + publicAddress: (UInt32)rawPublicAddress
25.111 + publicPort: (UInt16)publicPort
25.112 +{
25.113 + LogTo(PortMapper,@"Callback got err %i, addr %08X:%hu",
25.114 + errorCode, rawPublicAddress, publicPort);
25.115 + if( errorCode==kDNSServiceErr_NoError ) {
25.116 + if( rawPublicAddress==0 || (publicPort==0 && (_mapTCP || _mapUDP)) ) {
25.117 + LogTo(PortMapper,@"(Callback reported no mapping available)");
25.118 + errorCode = kDNSServiceErr_NATPortMappingUnsupported;
25.119 + }
25.120 + }
25.121 + if( errorCode != self.error )
25.122 + self.error = errorCode;
25.123 +
25.124 + [self priv_updateLocalAddress];
25.125 + IPAddress *publicAddress = makeIPAddr(rawPublicAddress,publicPort);
25.126 + if (!$equal(publicAddress,_publicAddress))
25.127 + self.publicAddress = publicAddress;
25.128 +
25.129 + if( ! errorCode ) {
25.130 + LogTo(PortMapper,@"Callback got %08X:%hu -> %@ (mapped=%i)",
25.131 + rawPublicAddress,publicPort, self.publicAddress, self.isMapped);
25.132 + }
25.133 + [[NSNotificationCenter defaultCenter] postNotificationName: MYPortMapperChangedNotification
25.134 + object: self];
25.135 +}
25.136 +
25.137 +
25.138 +/** Asynchronous callback from DNSServiceNATPortMappingCreate.
25.139 + This is invoked whenever the status of the port mapping changes.
25.140 + All it does is dispatch to the object's priv_portMapStatus:publicAddress:publicPort: method. */
25.141 +static void portMapCallback (
25.142 + DNSServiceRef sdRef,
25.143 + DNSServiceFlags flags,
25.144 + uint32_t interfaceIndex,
25.145 + DNSServiceErrorType errorCode,
25.146 + uint32_t publicAddress, /* four byte IPv4 address in network byte order */
25.147 + DNSServiceProtocol protocol,
25.148 + uint16_t privatePort,
25.149 + uint16_t publicPort, /* may be different than the requested port */
25.150 + uint32_t ttl, /* may be different than the requested ttl */
25.151 + void *context
25.152 + )
25.153 +{
25.154 + NSAutoreleasePool *pool = [NSAutoreleasePool new];
25.155 + @try{
25.156 + [(MYPortMapper*)context priv_portMapStatus: errorCode
25.157 + publicAddress: publicAddress
25.158 + publicPort: ntohs(publicPort)]; // port #s in network byte order!
25.159 + }catchAndReport(@"PortMapper");
25.160 + [pool drain];
25.161 +}
25.162 +
25.163 +
25.164 +/** CFSocket callback, informing us that _socket has data available, which means
25.165 + that the DNS service has an incoming result to be processed. This will end up invoking
25.166 + the portMapCallback. */
25.167 +static void serviceCallback(CFSocketRef s,
25.168 + CFSocketCallBackType type,
25.169 + CFDataRef address, const void *data, void *clientCallBackInfo)
25.170 +{
25.171 + MYPortMapper *mapper = (MYPortMapper*)clientCallBackInfo;
25.172 + DNSServiceRef service = mapper._service;
25.173 + DNSServiceErrorType err = DNSServiceProcessResult(service);
25.174 + if( err ) {
25.175 + // An error here means the socket has failed and should be closed.
25.176 + [mapper priv_portMapStatus: err publicAddress: 0 publicPort: 0];
25.177 + [mapper priv_disconnect];
25.178 + }
25.179 +}
25.180 +
25.181 +
25.182 +
25.183 +- (BOOL) open
25.184 +{
25.185 + NSAssert(!_service,@"Already open");
25.186 + // Create the DNSService:
25.187 + DNSServiceProtocol protocols = 0;
25.188 + if( _mapTCP ) protocols |= kDNSServiceProtocol_TCP;
25.189 + if( _mapUDP ) protocols |= kDNSServiceProtocol_UDP;
25.190 + self.error = DNSServiceNATPortMappingCreate((DNSServiceRef*)&_service,
25.191 + 0 /*flags*/,
25.192 + 0 /*interfaceIndex*/,
25.193 + protocols,
25.194 + htons(_localPort),
25.195 + htons(_desiredPublicPort),
25.196 + 0 /*ttl*/,
25.197 + &portMapCallback,
25.198 + self);
25.199 + if( _error ) {
25.200 + LogTo(PortMapper,@"Error %i creating port mapping",_error);
25.201 + return NO;
25.202 + }
25.203 +
25.204 + // Wrap a CFSocket around the service's socket:
25.205 + CFSocketContext ctxt = { 0, self, CFRetain, CFRelease, NULL };
25.206 + _socket = CFSocketCreateWithNative(NULL,
25.207 + DNSServiceRefSockFD(_service),
25.208 + kCFSocketReadCallBack,
25.209 + &serviceCallback, &ctxt);
25.210 + if( _socket ) {
25.211 + CFSocketSetSocketFlags(_socket, CFSocketGetSocketFlags(_socket) & ~kCFSocketCloseOnInvalidate);
25.212 + // Attach the socket to the runloop so the serviceCallback will be invoked:
25.213 + _socketSource = CFSocketCreateRunLoopSource(NULL, _socket, 0);
25.214 + if( _socketSource )
25.215 + CFRunLoopAddSource(CFRunLoopGetCurrent(), _socketSource, kCFRunLoopCommonModes);
25.216 + }
25.217 + if( _socketSource ) {
25.218 + LogTo(PortMapper,@"Opening");
25.219 + return YES;
25.220 + } else {
25.221 + Warn(@"Failed to open PortMapper");
25.222 + [self close];
25.223 + _error = kDNSServiceErr_Unknown;
25.224 + return NO;
25.225 + }
25.226 +}
25.227 +
25.228 +
25.229 +- (BOOL) waitTillOpened
25.230 +{
25.231 + if( ! _socketSource )
25.232 + if( ! [self open] )
25.233 + return NO;
25.234 + // Run the runloop until there's either an error or a result:
25.235 + while( _error==0 && _publicAddress==nil )
25.236 + if( ! [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
25.237 + beforeDate: [NSDate distantFuture]] )
25.238 + break;
25.239 + return (_error==0);
25.240 +}
25.241 +
25.242 +
25.243 +// Close down, but _without_ clearing the 'error' property
25.244 +- (void) priv_disconnect
25.245 +{
25.246 + if( _socketSource ) {
25.247 + CFRunLoopSourceInvalidate(_socketSource);
25.248 + CFRelease(_socketSource);
25.249 + _socketSource = NULL;
25.250 + }
25.251 + if( _socket ) {
25.252 + CFSocketInvalidate(_socket);
25.253 + CFRelease(_socket);
25.254 + _socket = NULL;
25.255 + }
25.256 + if( _service ) {
25.257 + LogTo(PortMapper,@"Deleting port mapping");
25.258 + DNSServiceRefDeallocate(_service);
25.259 + _service = NULL;
25.260 + self.publicAddress = nil;
25.261 + }
25.262 +}
25.263 +
25.264 +- (void) close
25.265 +{
25.266 + [self priv_disconnect];
25.267 + self.error = 0;
25.268 +}
25.269 +
25.270 +
25.271 ++ (IPAddress*) findPublicAddress
25.272 +{
25.273 + IPAddress *addr = nil;
25.274 + MYPortMapper *mapper = [[self alloc] initWithNullMapping];
25.275 + if( [mapper waitTillOpened] )
25.276 + addr = [mapper.publicAddress retain];
25.277 + [mapper close];
25.278 + [mapper release];
25.279 + return [addr autorelease];
25.280 +}
25.281 +
25.282 +
25.283 +@end
25.284 +
25.285 +
25.286 +/*
25.287 + Copyright (c) 2008-2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
25.288 +
25.289 + Redistribution and use in source and binary forms, with or without modification, are permitted
25.290 + provided that the following conditions are met:
25.291 +
25.292 + * Redistributions of source code must retain the above copyright notice, this list of conditions
25.293 + and the following disclaimer.
25.294 + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
25.295 + and the following disclaimer in the documentation and/or other materials provided with the
25.296 + distribution.
25.297 +
25.298 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
25.299 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
25.300 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
25.301 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25.302 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25.303 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25.304 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
25.305 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25.306 + */
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/PortMapper/PortMapperTest.m Wed Apr 22 16:45:39 2009 -0700
26.3 @@ -0,0 +1,111 @@
26.4 +// PortMapperTest.m
26.5 +// MYNetwork
26.6 +//
26.7 +// Created by Jens Alfke on 1/4/08.
26.8 +// Copyright 2008 Jens Alfke. All rights reserved.
26.9 +//
26.10 +
26.11 +
26.12 +
26.13 +#import "MYPortMapper.h"
26.14 +#import "IPAddress.h"
26.15 +#import "Test.h"
26.16 +#import "Logging.h"
26.17 +
26.18 +#if DEBUG
26.19 +
26.20 +
26.21 +/** A trivial class that just demonstrates how to create a MYPortMapper and listen for changes. */
26.22 +@interface MYPortMapperTest : NSObject
26.23 +{
26.24 + MYPortMapper *_mapper;
26.25 +}
26.26 +
26.27 +@end
26.28 +
26.29 +
26.30 +@implementation MYPortMapperTest
26.31 +
26.32 +
26.33 +- (id) init
26.34 +{
26.35 + self = [super init];
26.36 + if( self ) {
26.37 + // Create MYPortMapper. This example doesn't open a real socket; just pretend that there's
26.38 + // already a TCP socket listening on port 8080. To experiment, you could turn on Web
26.39 + // Sharing, then change this port number to 80 -- that will make your computer's local
26.40 + // Apache web server reachable from the outside world while this program is running.
26.41 + _mapper = [[MYPortMapper alloc] initWithLocalPort: 80];
26.42 +
26.43 + // Optionally, request a public port number.
26.44 + // The NAT is free to ignore this and return a random number instead.
26.45 + _mapper.desiredPublicPort = 22222;
26.46 +
26.47 + // Now open the mapping (asynchronously):
26.48 + if( [_mapper open] ) {
26.49 + Log(@"Opening port mapping...");
26.50 + // Now listen for notifications to find out when the mapping opens, fails, or changes:
26.51 + [[NSNotificationCenter defaultCenter] addObserver: self
26.52 + selector: @selector(portMappingChanged:)
26.53 + name: MYPortMapperChangedNotification
26.54 + object: _mapper];
26.55 + } else {
26.56 + // MYPortMapper failed -- this is unlikely, but be graceful:
26.57 + Log(@"!! Error: MYPortMapper wouldn't start: %i",_mapper.error);
26.58 + [self release];
26.59 + return nil;
26.60 + }
26.61 + }
26.62 + return self;
26.63 +}
26.64 +
26.65 +
26.66 +- (void) portMappingChanged: (NSNotification*)n
26.67 +{
26.68 + // This is where we get notified that the mapping was created, or that no mapping exists,
26.69 + // or that mapping failed.
26.70 + if( _mapper.error )
26.71 + Log(@"!! MYPortMapper error %i", _mapper.error);
26.72 + else {
26.73 + NSString *message = @"";
26.74 + if( !_mapper.isMapped )
26.75 + message = @" (no address translation!)";
26.76 + Log(@"** Public address:port is %@%@", _mapper.publicAddress, message);
26.77 + Log(@" local address:port is %@", _mapper.localAddress);
26.78 + }
26.79 +}
26.80 +
26.81 +
26.82 +- (void) dealloc
26.83 +{
26.84 + [_mapper close];
26.85 + [_mapper release];
26.86 + [super dealloc];
26.87 +}
26.88 +
26.89 +
26.90 +@end
26.91 +
26.92 +
26.93 +
26.94 +TestCase(MYPortMapper) {
26.95 +
26.96 + EnableLogTo(PortMapper,YES);
26.97 + // Here's how to simply obtain your local and public address(es):
26.98 + IPAddress *addr = [IPAddress localAddress];
26.99 + Log(@"** Local address is %@%@ ...getting public addr...",
26.100 + addr, (addr.isPrivate ?@" (private)" :@""));
26.101 + addr = [MYPortMapper findPublicAddress];
26.102 + Log(@"** Public address is %@", addr);
26.103 +
26.104 + // Start up the test class to create a mapping:
26.105 + MYPortMapperTest *test = [[MYPortMapperTest alloc] init];
26.106 +
26.107 + // Now let the runloop run forever...
26.108 + Log(@"Running the runloop forever...");
26.109 + [[NSRunLoop currentRunLoop] run];
26.110 +
26.111 + [test release];
26.112 +}
26.113 +
26.114 +#endif DEBUG
27.1 --- a/TCP/TCPConnection.h Tue Dec 02 22:42:56 2008 -0800
27.2 +++ b/TCP/TCPConnection.h Wed Apr 22 16:45:39 2009 -0700
27.3 @@ -127,6 +127,7 @@
27.4 settings say to check the peer's certificate.
27.5 This happens, if at all, after the -connectionDidOpen: call. */
27.6 - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert;
27.7 -/** Called after the connection closes. */
27.8 +/** Called after the connection closes.
27.9 + You can check the connection's error property to see if it was normal or abnormal. */
27.10 - (void) connectionDidClose: (TCPConnection*)connection;
27.11 @end
28.1 --- a/TCP/TCPConnection.m Tue Dec 02 22:42:56 2008 -0800
28.2 +++ b/TCP/TCPConnection.m Wed Apr 22 16:45:39 2009 -0700
28.3 @@ -14,7 +14,7 @@
28.4 #import "ExceptionUtils.h"
28.5
28.6
28.7 -#if TARGET_OS_IPHONE && TARGET_OS_EMBEDDED
28.8 +#if TARGET_OS_IPHONE && !defined(__SEC_TYPES__)
28.9 // SecureTransport.h is missing on iPhone, with its SSL constants:
28.10 enum{
28.11 errSSLClosedAbort = -9806, /* connection closed via error */
28.12 @@ -348,7 +348,7 @@
28.13 allow = NO; // Server MUST have a cert!
28.14 else {
28.15 SecCertificateRef cert = certs.count ?(SecCertificateRef)[certs objectAtIndex:0] :NULL;
28.16 - LogTo(TCP,@"%@: Peer cert = %@",self,cert);
28.17 + LogTo(TCP,@"%@: Peer cert = %@",self,[TCPEndpoint describeCert: cert]);
28.18 if( [_delegate respondsToSelector: @selector(connection:authorizeSSLPeer:)] )
28.19 allow = [_delegate connection: self authorizeSSLPeer: cert];
28.20 }
29.1 --- a/TCP/TCPEndpoint.h Tue Dec 02 22:42:56 2008 -0800
29.2 +++ b/TCP/TCPEndpoint.h Wed Apr 22 16:45:39 2009 -0700
29.3 @@ -7,6 +7,7 @@
29.4 //
29.5
29.6 #import <Foundation/Foundation.h>
29.7 +#import <Security/SecBase.h>
29.8 #if TARGET_OS_IPHONE
29.9 #include <CFNetwork/CFSocketStream.h>
29.10 #else
29.11 @@ -15,10 +16,26 @@
29.12
29.13
29.14 // SSL properties:
29.15 +
29.16 +/** This defines the SSL identity to be used by this endpoint.
29.17 + The value is an NSArray (or CFArray) whose first item must be a SecIdentityRef;
29.18 + optionally, it can also contain SecCertificateRefs for supporting certificates in the
29.19 + validation chain. */
29.20 #define kTCPPropertySSLCertificates ((NSString*)kCFStreamSSLCertificates)
29.21 +
29.22 +/** If set to YES, the connection will accept self-signed certificates from the peer,
29.23 + or any certificate chain that terminates in an unrecognized root. */
29.24 #define kTCPPropertySSLAllowsAnyRoot ((NSString*)kCFStreamSSLAllowsAnyRoot)
29.25
29.26 -extern NSString* const kTCPPropertySSLClientSideAuthentication; // value is TCPAuthenticate enum
29.27 +/** This sets the hostname that the peer's certificate must have.
29.28 + (The default value is the hostname, if any, that the connection was opened with.)
29.29 + Setting a value of [NSNull null] completely disables host-name checking. */
29.30 +#define kTCPPropertySSLPeerName ((NSString*)kCFStreamSSLPeerName)
29.31 +
29.32 +/** Specifies whether the client (the peer that opened the connection) will use a certificate.
29.33 + The value is a TCPAuthenticate enum value wrapped in an NSNumber. */
29.34 +extern NSString* const kTCPPropertySSLClientSideAuthentication;
29.35 +
29.36 typedef enum {
29.37 kTCPNeverAuthenticate, /* skip client authentication */
29.38 kTCPAlwaysAuthenticate, /* require it */
29.39 @@ -46,6 +63,10 @@
29.40 - (void) setSSLProperty: (id)value
29.41 forKey: (NSString*)key;
29.42
29.43 +/** High-level setup for secure P2P connections. Uses the given identity for SSL,
29.44 + requires peers to use SSL, turns off root checking and peer-name checking. */
29.45 +- (void) setPeerToPeerIdentity: (SecIdentityRef)identity;
29.46 +
29.47 //protected:
29.48 - (void) tellDelegate: (SEL)selector withObject: (id)param;
29.49
30.1 --- a/TCP/TCPEndpoint.m Tue Dec 02 22:42:56 2008 -0800
30.2 +++ b/TCP/TCPEndpoint.m Wed Apr 22 16:45:39 2009 -0700
30.3 @@ -7,8 +7,10 @@
30.4 //
30.5
30.6 #import "TCPEndpoint.h"
30.7 -
30.8 +#import "Test.h"
30.9 +#import "CollectionUtils.h"
30.10 #import "ExceptionUtils.h"
30.11 +#import <Security/Security.h>
30.12
30.13
30.14 NSString* const kTCPPropertySSLClientSideAuthentication = @"kTCPPropertySSLClientSideAuthentication";
30.15 @@ -47,6 +49,15 @@
30.16 - (NSString*) securityLevel {return [_sslProperties objectForKey: (id)kCFStreamSSLLevel];}
30.17 - (void) setSecurityLevel: (NSString*)level {[self setSSLProperty: level forKey: (id)kCFStreamSSLLevel];}
30.18
30.19 +- (void) setPeerToPeerIdentity: (SecIdentityRef)identity {
30.20 + Assert(identity);
30.21 + self.SSLProperties = $mdict(
30.22 + {(id)kCFStreamSSLLevel, NSStreamSocketSecurityLevelTLSv1},
30.23 + {kTCPPropertySSLCertificates, $array((id)identity)},
30.24 + {kTCPPropertySSLAllowsAnyRoot, $true},
30.25 + {kTCPPropertySSLPeerName, [NSNull null]},
30.26 + {kTCPPropertySSLClientSideAuthentication, $object(kTCPAlwaysAuthenticate)});
30.27 +}
30.28
30.29 - (void) tellDelegate: (SEL)selector withObject: (id)param
30.30 {
30.31 @@ -58,6 +69,37 @@
30.32 }
30.33
30.34
30.35 ++ (NSString*) describeCert: (SecCertificateRef)cert {
30.36 + if (!cert)
30.37 + return @"(null)";
30.38 + NSString *desc;
30.39 +#if TARGET_OS_IPHONE && !defined(__SEC_TYPES__)
30.40 + CFStringRef summary = NULL;
30.41 + SecCertificateCopySubjectSummary(cert);
30.42 + desc = $sprintf(@"Certificate[%@]", summary);
30.43 + if(summary) CFRelease(summary);
30.44 +#else
30.45 + CFStringRef name=NULL;
30.46 + CFArrayRef emails=NULL;
30.47 + SecCertificateCopyCommonName(cert, &name);
30.48 + SecCertificateCopyEmailAddresses(cert, &emails);
30.49 + desc = $sprintf(@"Certificate[\"%@\", <%@>]",
30.50 + name, [(NSArray*)emails componentsJoinedByString: @">, <"]);
30.51 + if(name) CFRelease(name);
30.52 + if(emails) CFRelease(emails);
30.53 +#endif
30.54 + return desc;
30.55 +}
30.56 +
30.57 ++ (NSString*) describeIdentity: (SecIdentityRef)identity {
30.58 + if (!identity)
30.59 + return @"(null)";
30.60 + SecCertificateRef cert;
30.61 + SecIdentityCopyCertificate(identity, &cert);
30.62 + return $sprintf(@"Identity[%@]", [self describeCert: cert]);
30.63 +}
30.64 +
30.65 +
30.66 @end
30.67
30.68
31.1 --- a/TCP/TCPListener.m Tue Dec 02 22:42:56 2008 -0800
31.2 +++ b/TCP/TCPListener.m Wed Apr 22 16:45:39 2009 -0700
31.3 @@ -156,10 +156,13 @@
31.4 addr6.sin6_port = htons(_port);
31.5 memcpy(&(addr6.sin6_addr), &in6addr_any, sizeof(addr6.sin6_addr));
31.6
31.7 - _ipv6socket = [self _openProtocol: PF_INET6 address: (struct sockaddr*)&addr6 error: outError];
31.8 + NSError *error;
31.9 + _ipv6socket = [self _openProtocol: PF_INET6 address: (struct sockaddr*)&addr6 error: &error];
31.10 if( ! _ipv6socket ) {
31.11 _ipv4socket = closeSocket(_ipv4socket);
31.12 - return [self _failedToOpen: *outError];
31.13 + [self _failedToOpen: error];
31.14 + if (outError) *outError = error;
31.15 + return NO;
31.16 }
31.17 }
31.18
32.1 --- a/TCP/TCPStream.m Tue Dec 02 22:42:56 2008 -0800
32.2 +++ b/TCP/TCPStream.m Wed Apr 22 16:45:39 2009 -0700
32.3 @@ -96,7 +96,7 @@
32.4 - (void) open
32.5 {
32.6 Assert(_stream);
32.7 - AssertEq(_stream.streamStatus,NSStreamStatusNotOpen);
32.8 + AssertEq(_stream.streamStatus,(NSStreamStatus)NSStreamStatusNotOpen);
32.9 LogTo(TCP,@"Opening %@",self);
32.10 [_stream open];
32.11 }
33.1 --- a/TCP/TCP_Internal.h Tue Dec 02 22:42:56 2008 -0800
33.2 +++ b/TCP/TCP_Internal.h Wed Apr 22 16:45:39 2009 -0700
33.3 @@ -30,3 +30,8 @@
33.4 - (void) _unclose;
33.5 @end
33.6
33.7 +
33.8 +@interface TCPEndpoint ()
33.9 ++ (NSString*) describeCert: (SecCertificateRef)cert;
33.10 ++ (NSString*) describeIdentity: (SecIdentityRef)identity;
33.11 +@end
34.1 --- a/iPhone/Classes/MyViewController.m Tue Dec 02 22:42:56 2008 -0800
34.2 +++ b/iPhone/Classes/MyViewController.m Wed Apr 22 16:45:39 2009 -0700
34.3 @@ -1,49 +1,3 @@
34.4 -/*
34.5 -
34.6 -File: MyViewController.m
34.7 -Abstract: A view controller responsible for managing the Hello World view.
34.8 -
34.9 -Version: 1.7
34.10 -
34.11 -Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
34.12 -("Apple") in consideration of your agreement to the following terms, and your
34.13 -use, installation, modification or redistribution of this Apple software
34.14 -constitutes acceptance of these terms. If you do not agree with these terms,
34.15 -please do not use, install, modify or redistribute this Apple software.
34.16 -
34.17 -In consideration of your agreement to abide by the following terms, and subject
34.18 -to these terms, Apple grants you a personal, non-exclusive license, under
34.19 -Apple's copyrights in this original Apple software (the "Apple Software"), to
34.20 -use, reproduce, modify and redistribute the Apple Software, with or without
34.21 -modifications, in source and/or binary forms; provided that if you redistribute
34.22 -the Apple Software in its entirety and without modifications, you must retain
34.23 -this notice and the following text and disclaimers in all such redistributions
34.24 -of the Apple Software.
34.25 -Neither the name, trademarks, service marks or logos of Apple Inc. may be used
34.26 -to endorse or promote products derived from the Apple Software without specific
34.27 -prior written permission from Apple. Except as expressly stated in this notice,
34.28 -no other rights or licenses, express or implied, are granted by Apple herein,
34.29 -including but not limited to any patent rights that may be infringed by your
34.30 -derivative works or by other works in which the Apple Software may be
34.31 -incorporated.
34.32 -
34.33 -The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
34.34 -WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
34.35 -WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34.36 -PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
34.37 -COMBINATION WITH YOUR PRODUCTS.
34.38 -
34.39 -IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
34.40 -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
34.41 -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34.42 -ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
34.43 -DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
34.44 -CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
34.45 -APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34.46 -
34.47 -Copyright (C) 2008 Apple Inc. All Rights Reserved.
34.48 -
34.49 -*/
34.50
34.51 #import "MyViewController.h"
34.52 #import "BLIP.h"
35.1 --- a/iPhone/main.m Tue Dec 02 22:42:56 2008 -0800
35.2 +++ b/iPhone/main.m Wed Apr 22 16:45:39 2009 -0700
35.3 @@ -46,9 +46,11 @@
35.4 */
35.5
35.6 #import <UIKit/UIKit.h>
35.7 +#import "Test.h"
35.8
35.9 int main(int argc, char *argv[])
35.10 {
35.11 + RunTestCases(argc,(const char**)argv);
35.12 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
35.13 int retVal = UIApplicationMain(argc, argv, nil, nil);
35.14 [pool release];