# HG changeset patch # User Jens Alfke # Date 1211748183 25200 # Node ID 5936db2c1987a3af5bb992070fbc3a9e0de84589 # Parent bceeeabb8c3400bd6f17b4e6c197bcfca0da16b1 Added -[TCPConnection initToNetService:] to make it easier to use with Bonjour. This allowed me to simplify BLIPEchoClient quite a lot. diff -r bceeeabb8c34 -r 5936db2c1987 BLIP/Demo/BLIPEchoClient.h --- a/BLIP/Demo/BLIPEchoClient.h Sun May 25 12:33:50 2008 -0700 +++ b/BLIP/Demo/BLIPEchoClient.h Sun May 25 13:43:03 2008 -0700 @@ -20,7 +20,7 @@ NSNetServiceBrowser * _serviceBrowser; NSMutableArray * _serviceList; - NSNetService *_resolvingService; + BLIPConnection *_connection; } diff -r bceeeabb8c34 -r 5936db2c1987 BLIP/Demo/BLIPEchoClient.m --- a/BLIP/Demo/BLIPEchoClient.m Sun May 25 12:33:50 2008 -0700 +++ b/BLIP/Demo/BLIPEchoClient.m Sun May 25 13:43:03 2008 -0700 @@ -10,7 +10,6 @@ #import "BLIPEchoClient.h" #import "BLIP.h" -#import "IPAddress.h" #import "Target.h" @@ -28,24 +27,6 @@ } #pragma mark - -#pragma mark BLIPConnection support - -/* Opens a BLIP connection to the given address. */ -- (void)openConnection: (IPAddress*)address -{ - _connection = [[BLIPConnection alloc] initToAddress: address]; - [_connection open]; -} - -/* Closes the currently open BLIP connection. */ -- (void)closeConnection -{ - [_connection close]; - [_connection release]; - _connection = nil; -} - -#pragma mark - #pragma mark NSNetServiceBrowser delegate methods // We broadcast the willChangeValueForKey: and didChangeValueForKey: for the NSTableView binding to work. @@ -67,43 +48,24 @@ } #pragma mark - -#pragma mark NSNetService delegate methods +#pragma mark BLIPConnection support -/* Stop any current Bonjour address resolution */ -- (void)stopResolving +/* Opens a BLIP connection to the given address. */ +- (void)openConnection: (NSNetService*)service { - if( _resolvingService ) { - _resolvingService.delegate = nil; - [_resolvingService stop]; - [_resolvingService release]; - _resolvingService = nil; - } -} - -/* Ask Bonjour to resolve (look up) the IP address of the given service. */ -- (void)startResolving: (NSNetService*)service -{ - [self stopResolving]; - _resolvingService = [service retain]; - _resolvingService.delegate = self; - [_resolvingService resolveWithTimeout: 5.0]; - + _connection = [[BLIPConnection alloc] initToNetService: service]; + if( _connection ) + [_connection open]; + else + NSBeep(); } -/* NSNetService delegate method that will be called when address resolution finishes. */ -- (void)netServiceDidResolveAddress:(NSNetService *)sender +/* Closes the currently open BLIP connection. */ +- (void)closeConnection { - if( sender == _resolvingService ) { - // Get the first address, which is an NSData containing a struct sockaddr: - NSArray *addresses = _resolvingService.addresses; - if( addresses.count > 0 ) { - NSData *addressData = [addresses objectAtIndex: 0]; - IPAddress *address = [[IPAddress alloc] initWithSockAddr: addressData.bytes]; - [self openConnection: address]; - [address release]; - } - [self stopResolving]; - } + [_connection close]; + [_connection release]; + _connection = nil; } #pragma mark - @@ -114,17 +76,14 @@ int selectedRow = [table selectedRow]; [self closeConnection]; - [self stopResolving]; - - if (-1 != selectedRow) { - [self startResolving: [_serviceList objectAtIndex:selectedRow]]; - } + if (-1 != selectedRow) + [self openConnection: [_serviceList objectAtIndex:selectedRow]]; } /* Send a BLIP request containing the string in the textfield */ - (IBAction)sendText:(id)sender { - BLIPRequest *r = [_connection requestWithBody: nil]; + BLIPRequest *r = [_connection request]; r.bodyString = [sender stringValue]; BLIPResponse *response = [r send]; response.onComplete = $target(self,gotResponse:); diff -r bceeeabb8c34 -r 5936db2c1987 MYNetwork.xcodeproj/project.pbxproj --- a/MYNetwork.xcodeproj/project.pbxproj Sun May 25 12:33:50 2008 -0700 +++ b/MYNetwork.xcodeproj/project.pbxproj Sun May 25 13:43:03 2008 -0700 @@ -531,6 +531,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = DEBUG; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; @@ -545,6 +546,7 @@ buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; diff -r bceeeabb8c34 -r 5936db2c1987 TCP/TCPConnection.h --- a/TCP/TCPConnection.h Sun May 25 12:33:50 2008 -0700 +++ b/TCP/TCPConnection.h Sun May 25 13:43:03 2008 -0700 @@ -46,6 +46,10 @@ - (id) initToAddress: (IPAddress*)address localPort: (UInt16)localPort; +/** Initializes a TCPConnection to the given NSNetService's address and port. + If the service's address cannot be resolved, nil is returned. */ +- (id) initToNetService: (NSNetService*)service; + /** Initializes a TCPConnection from an incoming TCP socket. You don't usually need to call this; TCPListener does it automatically. */ - (id) initIncomingFromSocket: (CFSocketNativeHandle)socket listener: (TCPListener*)listener; @@ -79,7 +83,7 @@ + (void) waitTillAllClosed; /** The IP address of the other peer. */ -@property (readonly) IPAddress *address; +@property (readonly,retain) IPAddress *address; /** The TCPListener that created this incoming connection, or nil */ @property (readonly) TCPListener *server; diff -r bceeeabb8c34 -r 5936db2c1987 TCP/TCPConnection.m --- a/TCP/TCPConnection.m Sun May 25 12:33:50 2008 -0700 +++ b/TCP/TCPConnection.m Sun May 25 13:43:03 2008 -0700 @@ -19,6 +19,7 @@ @interface TCPConnection () @property TCPConnectionStatus status; +@property (retain) IPAddress *address; - (BOOL) _checkIfClosed; - (void) _closed; @end @@ -40,7 +41,7 @@ { self = [super init]; if (self != nil) { - if( !address || !input || !output ) { + if( !input || !output ) { LogTo(TCP,@"Failed to create %@: addr=%@, in=%@, out=%@", self.class,address,input,output); [self release]; @@ -49,7 +50,7 @@ _address = [address copy]; _reader = [[[self readerClass] alloc] initWithConnection: self stream: input]; _writer = [[[self writerClass] alloc] initWithConnection: self stream: output]; - LogTo(TCP,@"%@ initialized",self); + LogTo(TCP,@"%@ initialized, address=%@",self,address); } return self; } @@ -74,6 +75,22 @@ return [self initToAddress: address localPort: 0]; } +- (id) initToNetService: (NSNetService*)service +{ + IPAddress *address = nil; + NSInputStream *input; + NSOutputStream *output; + if( [service getInputStream: &input outputStream: &output] ) { + NSArray *addresses = service.addresses; + if( addresses.count > 0 ) + address = [[[IPAddress alloc] initWithSockAddr: [[addresses objectAtIndex: 0] bytes]] autorelease]; + } else { + input = nil; + output = nil; + } + return [self _initWithAddress: address inputStream: input outputStream: output]; +} + - (id) initIncomingFromSocket: (CFSocketNativeHandle)socket listener: (TCPListener*)listener @@ -253,8 +270,10 @@ - (void) _streamOpened: (TCPStream*)stream { + if( ! _address ) + self.address = stream.peerAddress; if( _status==kTCP_Opening && _reader.isOpen && _writer.isOpen ) { - LogTo(TCP,@"%@ opened",self); + LogTo(TCP,@"%@ opened; address=%@",self,_address); self.status = kTCP_Open; [self tellDelegate: @selector(connectionDidOpen:) withObject: nil]; } diff -r bceeeabb8c34 -r 5936db2c1987 TCP/TCPStream.h --- a/TCP/TCPStream.h Sun May 25 12:33:50 2008 -0700 +++ b/TCP/TCPStream.h Sun May 25 13:43:03 2008 -0700 @@ -7,7 +7,7 @@ // #import -@class TCPConnection, TCPWriter; +@class TCPConnection, TCPWriter, IPAddress; /** Abstract superclass for data streams, used by TCPConnection. */ @@ -20,6 +20,9 @@ - (id) initWithConnection: (TCPConnection*)conn stream: (NSStream*)stream; +/** The IP address this stream is connected to. */ +@property (readonly) IPAddress *peerAddress; + /** The connection's security level as reported by the underlying CFStream. */ @property (readonly) NSString *securityLevel; diff -r bceeeabb8c34 -r 5936db2c1987 TCP/TCPStream.m --- a/TCP/TCPStream.m Sun May 25 12:33:50 2008 -0700 +++ b/TCP/TCPStream.m Sun May 25 13:43:03 2008 -0700 @@ -8,6 +8,7 @@ #import "TCPStream.h" #import "TCP_Internal.h" +#import "IPAddress.h" #import "Logging.h" #import "Test.h" @@ -46,11 +47,20 @@ - (id) propertyForKey: (CFStringRef)cfStreamProperty { - return nil; // abstract -- overridden by TCPReader and TCPWriter + return [_stream propertyForKey: (NSString*)cfStreamProperty]; } - (void) setProperty: (id)value forKey: (CFStringRef)cfStreamProperty -{ // abstract -- overridden by TCPReader and TCPWriter +{ + if( ! [_stream setProperty: value forKey: (NSString*)cfStreamProperty] ) + Warn(@"Failed to set property %@ on %@",cfStreamProperty,self); +} + + +- (IPAddress*) peerAddress +{ + const CFSocketNativeHandle *socketPtr = [[self propertyForKey: kCFStreamPropertySocketNativeHandle] bytes]; + return socketPtr ?[IPAddress addressOfSocket: *socketPtr] :nil; } @@ -225,20 +235,6 @@ return _conn.writer; } - -- (id) propertyForKey: (CFStringRef)cfStreamProperty -{ - CFTypeRef value = CFReadStreamCopyProperty((CFReadStreamRef)_stream,cfStreamProperty); - return [(id)CFMakeCollectable(value) autorelease]; -} - -- (void) setProperty: (id)value forKey: (CFStringRef)cfStreamProperty -{ - if( ! CFReadStreamSetProperty((CFReadStreamRef)_stream,cfStreamProperty,(CFTypeRef)value) ) - Warn(@"%@ didn't accept property '%@'", self,cfStreamProperty); -} - - - (NSInteger) read: (void*)dst maxLength: (NSUInteger)maxLength { NSInteger bytesRead = [(NSInputStream*)_stream read:dst maxLength: maxLength]; diff -r bceeeabb8c34 -r 5936db2c1987 TCP/TCPWriter.m --- a/TCP/TCPWriter.m Sun May 25 12:33:50 2008 -0700 +++ b/TCP/TCPWriter.m Sun May 25 13:43:03 2008 -0700 @@ -30,19 +30,6 @@ } -- (id) propertyForKey: (CFStringRef)cfStreamProperty -{ - CFTypeRef value = CFWriteStreamCopyProperty((CFWriteStreamRef)_stream,cfStreamProperty); - return [(id)CFMakeCollectable(value) autorelease]; -} - -- (void) setProperty: (id)value forKey: (CFStringRef)cfStreamProperty -{ - if( ! CFWriteStreamSetProperty((CFWriteStreamRef)_stream,cfStreamProperty,(CFTypeRef)value) ) - Warn(@"%@ didn't accept property '%@'", self,cfStreamProperty); -} - - - (BOOL) isBusy { return _currentData || _queue.count > 0;