Added -[TCPConnection initToNetService:] to make it easier to use with Bonjour. This allowed me to simplify BLIPEchoClient quite a lot.
authorJens Alfke <jens@mooseyard.com>
Sun May 25 13:43:03 2008 -0700 (2008-05-25)
changeset 75936db2c1987
parent 6 bceeeabb8c34
child 8 6f539dd9921c
Added -[TCPConnection initToNetService:] to make it easier to use with Bonjour. This allowed me to simplify BLIPEchoClient quite a lot.
BLIP/Demo/BLIPEchoClient.h
BLIP/Demo/BLIPEchoClient.m
MYNetwork.xcodeproj/project.pbxproj
TCP/TCPConnection.h
TCP/TCPConnection.m
TCP/TCPStream.h
TCP/TCPStream.m
TCP/TCPWriter.m
     1.1 --- a/BLIP/Demo/BLIPEchoClient.h	Sun May 25 12:33:50 2008 -0700
     1.2 +++ b/BLIP/Demo/BLIPEchoClient.h	Sun May 25 13:43:03 2008 -0700
     1.3 @@ -20,7 +20,7 @@
     1.4      
     1.5      NSNetServiceBrowser * _serviceBrowser;
     1.6      NSMutableArray * _serviceList;
     1.7 -    NSNetService *_resolvingService;
     1.8 +
     1.9      BLIPConnection *_connection;
    1.10  }
    1.11  
     2.1 --- a/BLIP/Demo/BLIPEchoClient.m	Sun May 25 12:33:50 2008 -0700
     2.2 +++ b/BLIP/Demo/BLIPEchoClient.m	Sun May 25 13:43:03 2008 -0700
     2.3 @@ -10,7 +10,6 @@
     2.4  
     2.5  #import "BLIPEchoClient.h"
     2.6  #import "BLIP.h"
     2.7 -#import "IPAddress.h"
     2.8  #import "Target.h"
     2.9  
    2.10  
    2.11 @@ -28,24 +27,6 @@
    2.12  }
    2.13  
    2.14  #pragma mark -
    2.15 -#pragma mark BLIPConnection support
    2.16 -
    2.17 -/* Opens a BLIP connection to the given address. */
    2.18 -- (void)openConnection: (IPAddress*)address 
    2.19 -{
    2.20 -    _connection = [[BLIPConnection alloc] initToAddress: address];
    2.21 -    [_connection open];
    2.22 -}
    2.23 -
    2.24 -/* Closes the currently open BLIP connection. */
    2.25 -- (void)closeConnection
    2.26 -{
    2.27 -    [_connection close];
    2.28 -    [_connection release];
    2.29 -    _connection = nil;
    2.30 -}
    2.31 -
    2.32 -#pragma mark -
    2.33  #pragma mark NSNetServiceBrowser delegate methods
    2.34  
    2.35  // We broadcast the willChangeValueForKey: and didChangeValueForKey: for the NSTableView binding to work.
    2.36 @@ -67,43 +48,24 @@
    2.37  }
    2.38  
    2.39  #pragma mark -
    2.40 -#pragma mark NSNetService delegate methods
    2.41 +#pragma mark BLIPConnection support
    2.42  
    2.43 -/* Stop any current Bonjour address resolution */
    2.44 -- (void)stopResolving
    2.45 +/* Opens a BLIP connection to the given address. */
    2.46 +- (void)openConnection: (NSNetService*)service 
    2.47  {
    2.48 -    if( _resolvingService ) {
    2.49 -        _resolvingService.delegate = nil;
    2.50 -        [_resolvingService stop];
    2.51 -        [_resolvingService release];
    2.52 -        _resolvingService = nil;
    2.53 -    }
    2.54 -}    
    2.55 -
    2.56 -/* Ask Bonjour to resolve (look up) the IP address of the given service. */
    2.57 -- (void)startResolving: (NSNetService*)service
    2.58 -{
    2.59 -    [self stopResolving];
    2.60 -    _resolvingService = [service retain];
    2.61 -    _resolvingService.delegate = self;
    2.62 -    [_resolvingService resolveWithTimeout: 5.0];
    2.63 -    
    2.64 +    _connection = [[BLIPConnection alloc] initToNetService: service];
    2.65 +    if( _connection )
    2.66 +        [_connection open];
    2.67 +    else
    2.68 +        NSBeep();
    2.69  }
    2.70  
    2.71 -/* NSNetService delegate method that will be called when address resolution finishes. */
    2.72 -- (void)netServiceDidResolveAddress:(NSNetService *)sender
    2.73 +/* Closes the currently open BLIP connection. */
    2.74 +- (void)closeConnection
    2.75  {
    2.76 -    if( sender == _resolvingService ) {
    2.77 -        // Get the first address, which is an NSData containing a struct sockaddr:
    2.78 -        NSArray *addresses = _resolvingService.addresses;
    2.79 -        if( addresses.count > 0 ) {
    2.80 -            NSData *addressData = [addresses objectAtIndex: 0];
    2.81 -            IPAddress *address = [[IPAddress alloc] initWithSockAddr: addressData.bytes];
    2.82 -            [self openConnection: address];
    2.83 -            [address release];
    2.84 -        }
    2.85 -        [self stopResolving];
    2.86 -    }
    2.87 +    [_connection close];
    2.88 +    [_connection release];
    2.89 +    _connection = nil;
    2.90  }
    2.91  
    2.92  #pragma mark -
    2.93 @@ -114,17 +76,14 @@
    2.94      int selectedRow = [table selectedRow];
    2.95      
    2.96      [self closeConnection];
    2.97 -    [self stopResolving];
    2.98 -    
    2.99 -    if (-1 != selectedRow) {
   2.100 -        [self startResolving: [_serviceList objectAtIndex:selectedRow]];
   2.101 -    }
   2.102 +    if (-1 != selectedRow)
   2.103 +        [self openConnection: [_serviceList objectAtIndex:selectedRow]];
   2.104  }
   2.105  
   2.106  /* Send a BLIP request containing the string in the textfield */
   2.107  - (IBAction)sendText:(id)sender 
   2.108  {
   2.109 -    BLIPRequest *r = [_connection requestWithBody: nil];
   2.110 +    BLIPRequest *r = [_connection request];
   2.111      r.bodyString = [sender stringValue];
   2.112      BLIPResponse *response = [r send];
   2.113      response.onComplete = $target(self,gotResponse:);
     3.1 --- a/MYNetwork.xcodeproj/project.pbxproj	Sun May 25 12:33:50 2008 -0700
     3.2 +++ b/MYNetwork.xcodeproj/project.pbxproj	Sun May 25 13:43:03 2008 -0700
     3.3 @@ -531,6 +531,7 @@
     3.4  				GCC_C_LANGUAGE_STANDARD = gnu99;
     3.5  				GCC_OPTIMIZATION_LEVEL = 0;
     3.6  				GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
     3.7 +				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
     3.8  				GCC_WARN_ABOUT_RETURN_TYPE = YES;
     3.9  				GCC_WARN_UNUSED_VARIABLE = YES;
    3.10  				ONLY_ACTIVE_ARCH = YES;
    3.11 @@ -545,6 +546,7 @@
    3.12  			buildSettings = {
    3.13  				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
    3.14  				GCC_C_LANGUAGE_STANDARD = gnu99;
    3.15 +				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
    3.16  				GCC_WARN_ABOUT_RETURN_TYPE = YES;
    3.17  				GCC_WARN_UNUSED_VARIABLE = YES;
    3.18  				PREBINDING = NO;
     4.1 --- a/TCP/TCPConnection.h	Sun May 25 12:33:50 2008 -0700
     4.2 +++ b/TCP/TCPConnection.h	Sun May 25 13:43:03 2008 -0700
     4.3 @@ -46,6 +46,10 @@
     4.4  - (id) initToAddress: (IPAddress*)address
     4.5             localPort: (UInt16)localPort;
     4.6  
     4.7 +/** Initializes a TCPConnection to the given NSNetService's address and port.
     4.8 +    If the service's address cannot be resolved, nil is returned. */
     4.9 +- (id) initToNetService: (NSNetService*)service;
    4.10 +
    4.11  /** Initializes a TCPConnection from an incoming TCP socket.
    4.12      You don't usually need to call this; TCPListener does it automatically. */
    4.13  - (id) initIncomingFromSocket: (CFSocketNativeHandle)socket listener: (TCPListener*)listener;
    4.14 @@ -79,7 +83,7 @@
    4.15  + (void) waitTillAllClosed;
    4.16  
    4.17  /** The IP address of the other peer. */
    4.18 -@property (readonly) IPAddress *address;
    4.19 +@property (readonly,retain) IPAddress *address;
    4.20  
    4.21  /** The TCPListener that created this incoming connection, or nil */
    4.22  @property (readonly) TCPListener *server;
     5.1 --- a/TCP/TCPConnection.m	Sun May 25 12:33:50 2008 -0700
     5.2 +++ b/TCP/TCPConnection.m	Sun May 25 13:43:03 2008 -0700
     5.3 @@ -19,6 +19,7 @@
     5.4  
     5.5  @interface TCPConnection ()
     5.6  @property TCPConnectionStatus status;
     5.7 +@property (retain) IPAddress *address;
     5.8  - (BOOL) _checkIfClosed;
     5.9  - (void) _closed;
    5.10  @end
    5.11 @@ -40,7 +41,7 @@
    5.12  {
    5.13      self = [super init];
    5.14      if (self != nil) {
    5.15 -        if( !address || !input || !output ) {
    5.16 +        if( !input || !output ) {
    5.17              LogTo(TCP,@"Failed to create %@: addr=%@, in=%@, out=%@",
    5.18                    self.class,address,input,output);
    5.19              [self release];
    5.20 @@ -49,7 +50,7 @@
    5.21          _address = [address copy];
    5.22          _reader = [[[self readerClass] alloc] initWithConnection: self stream: input];
    5.23          _writer = [[[self writerClass] alloc] initWithConnection: self stream: output];
    5.24 -        LogTo(TCP,@"%@ initialized",self);
    5.25 +        LogTo(TCP,@"%@ initialized, address=%@",self,address);
    5.26      }
    5.27      return self;
    5.28  }
    5.29 @@ -74,6 +75,22 @@
    5.30      return [self initToAddress: address localPort: 0];
    5.31  }
    5.32  
    5.33 +- (id) initToNetService: (NSNetService*)service
    5.34 +{
    5.35 +    IPAddress *address = nil;
    5.36 +    NSInputStream *input;
    5.37 +    NSOutputStream *output;
    5.38 +    if( [service getInputStream: &input outputStream: &output] ) {
    5.39 +        NSArray *addresses = service.addresses;
    5.40 +        if( addresses.count > 0 )
    5.41 +            address = [[[IPAddress alloc] initWithSockAddr: [[addresses objectAtIndex: 0] bytes]] autorelease];
    5.42 +    } else {
    5.43 +        input = nil;
    5.44 +        output = nil;
    5.45 +    }
    5.46 +    return [self _initWithAddress: address inputStream: input outputStream: output];
    5.47 +}
    5.48 +
    5.49  
    5.50  - (id) initIncomingFromSocket: (CFSocketNativeHandle)socket
    5.51                       listener: (TCPListener*)listener
    5.52 @@ -253,8 +270,10 @@
    5.53  
    5.54  - (void) _streamOpened: (TCPStream*)stream
    5.55  {
    5.56 +    if( ! _address )
    5.57 +        self.address = stream.peerAddress;
    5.58      if( _status==kTCP_Opening && _reader.isOpen && _writer.isOpen ) {
    5.59 -        LogTo(TCP,@"%@ opened",self);
    5.60 +        LogTo(TCP,@"%@ opened; address=%@",self,_address);
    5.61          self.status = kTCP_Open;
    5.62          [self tellDelegate: @selector(connectionDidOpen:) withObject: nil];
    5.63      }
     6.1 --- a/TCP/TCPStream.h	Sun May 25 12:33:50 2008 -0700
     6.2 +++ b/TCP/TCPStream.h	Sun May 25 13:43:03 2008 -0700
     6.3 @@ -7,7 +7,7 @@
     6.4  //
     6.5  
     6.6  #import <Foundation/Foundation.h>
     6.7 -@class TCPConnection, TCPWriter;
     6.8 +@class TCPConnection, TCPWriter, IPAddress;
     6.9  
    6.10  
    6.11  /** Abstract superclass for data streams, used by TCPConnection. */
    6.12 @@ -20,6 +20,9 @@
    6.13  
    6.14  - (id) initWithConnection: (TCPConnection*)conn stream: (NSStream*)stream;
    6.15  
    6.16 +/** The IP address this stream is connected to. */
    6.17 +@property (readonly) IPAddress *peerAddress;
    6.18 +
    6.19  /** The connection's security level as reported by the underlying CFStream. */
    6.20  @property (readonly) NSString *securityLevel;
    6.21  
     7.1 --- a/TCP/TCPStream.m	Sun May 25 12:33:50 2008 -0700
     7.2 +++ b/TCP/TCPStream.m	Sun May 25 13:43:03 2008 -0700
     7.3 @@ -8,6 +8,7 @@
     7.4  
     7.5  #import "TCPStream.h"
     7.6  #import "TCP_Internal.h"
     7.7 +#import "IPAddress.h"
     7.8  
     7.9  #import "Logging.h"
    7.10  #import "Test.h"
    7.11 @@ -46,11 +47,20 @@
    7.12  
    7.13  - (id) propertyForKey: (CFStringRef)cfStreamProperty
    7.14  {
    7.15 -    return nil; // abstract -- overridden by TCPReader and TCPWriter
    7.16 +    return [_stream propertyForKey: (NSString*)cfStreamProperty];
    7.17  }
    7.18  
    7.19  - (void) setProperty: (id)value forKey: (CFStringRef)cfStreamProperty
    7.20 -{ // abstract -- overridden by TCPReader and TCPWriter
    7.21 +{
    7.22 +    if( ! [_stream setProperty: value forKey: (NSString*)cfStreamProperty] )
    7.23 +        Warn(@"Failed to set property %@ on %@",cfStreamProperty,self);
    7.24 +}
    7.25 +
    7.26 +
    7.27 +- (IPAddress*) peerAddress
    7.28 +{
    7.29 +    const CFSocketNativeHandle *socketPtr = [[self propertyForKey: kCFStreamPropertySocketNativeHandle] bytes];
    7.30 +    return socketPtr ?[IPAddress addressOfSocket: *socketPtr] :nil;
    7.31  }
    7.32  
    7.33  
    7.34 @@ -225,20 +235,6 @@
    7.35      return _conn.writer;
    7.36  }
    7.37  
    7.38 -
    7.39 -- (id) propertyForKey: (CFStringRef)cfStreamProperty
    7.40 -{
    7.41 -    CFTypeRef value = CFReadStreamCopyProperty((CFReadStreamRef)_stream,cfStreamProperty);
    7.42 -    return [(id)CFMakeCollectable(value) autorelease];
    7.43 -}
    7.44 -
    7.45 -- (void) setProperty: (id)value forKey: (CFStringRef)cfStreamProperty
    7.46 -{
    7.47 -    if( ! CFReadStreamSetProperty((CFReadStreamRef)_stream,cfStreamProperty,(CFTypeRef)value) )
    7.48 -        Warn(@"%@ didn't accept property '%@'", self,cfStreamProperty);
    7.49 -}
    7.50 -
    7.51 -
    7.52  - (NSInteger) read: (void*)dst maxLength: (NSUInteger)maxLength
    7.53  {
    7.54      NSInteger bytesRead = [(NSInputStream*)_stream read:dst maxLength: maxLength];
     8.1 --- a/TCP/TCPWriter.m	Sun May 25 12:33:50 2008 -0700
     8.2 +++ b/TCP/TCPWriter.m	Sun May 25 13:43:03 2008 -0700
     8.3 @@ -30,19 +30,6 @@
     8.4  }
     8.5  
     8.6  
     8.7 -- (id) propertyForKey: (CFStringRef)cfStreamProperty
     8.8 -{
     8.9 -    CFTypeRef value = CFWriteStreamCopyProperty((CFWriteStreamRef)_stream,cfStreamProperty);
    8.10 -    return [(id)CFMakeCollectable(value) autorelease];
    8.11 -}
    8.12 -
    8.13 -- (void) setProperty: (id)value forKey: (CFStringRef)cfStreamProperty
    8.14 -{
    8.15 -    if( ! CFWriteStreamSetProperty((CFWriteStreamRef)_stream,cfStreamProperty,(CFTypeRef)value) )
    8.16 -        Warn(@"%@ didn't accept property '%@'", self,cfStreamProperty);
    8.17 -}
    8.18 -
    8.19 -
    8.20  - (BOOL) isBusy
    8.21  {
    8.22      return _currentData || _queue.count > 0;