* Fixed: Responses still pending when a connection closed were not calling their onComplete targets.
authorJens Alfke <jens@mooseyard.com>
Sun Jul 13 10:42:50 2008 -0700 (2008-07-13)
changeset 228b883753394a
parent 19 16454d63d4c2
child 23 ffdaa33a408a
* Fixed: Responses still pending when a connection closed were not calling their onComplete targets.
* Fixed: BLIPTestClient target failed to build because it didn't link against zlib.
* If TCPListener.bonjourServiceName is changed while the listener is open, it now re-publishes the service with the new name.
* Added a TCPListener.bonjourService property.
* Added a BLIPMessage.representedObject property.
* Fixed a memory leak.
BLIP/BLIPMessage.h
BLIP/BLIPMessage.m
BLIP/BLIPRequest.m
BLIP/BLIPTest.m
MYNetwork.xcodeproj/project.pbxproj
TCP/TCPListener.h
TCP/TCPListener.m
     1.1 --- a/BLIP/BLIPMessage.h	Mon Jun 23 14:02:31 2008 -0700
     1.2 +++ b/BLIP/BLIPMessage.h	Sun Jul 13 10:42:50 2008 -0700
     1.3 @@ -45,6 +45,7 @@
     1.4      NSMutableData *_mutableBody;
     1.5      BOOL _isMine, _isMutable, _sent, _propertiesAvailable, _complete;
     1.6      SInt32 _bytesWritten;
     1.7 +    id _representedObject;
     1.8  };
     1.9  
    1.10  /** The BLIPConnection associated with this message. */
    1.11 @@ -88,6 +89,10 @@
    1.12      The UTF-8 character encoding is used to convert. */
    1.13  @property (copy) NSString *bodyString;
    1.14  
    1.15 +/** An arbitrary object that you can associate with this message for your own purposes.
    1.16 +    The message retains it, but doesn't do anything else with it. */
    1.17 +@property (retain) id representedObject;
    1.18 +
    1.19  #pragma mark PROPERTIES:
    1.20  
    1.21  /** The message's properties, a dictionary-like object.
     2.1 --- a/BLIP/BLIPMessage.m	Mon Jun 23 14:02:31 2008 -0700
     2.2 +++ b/BLIP/BLIPMessage.m	Sun Jul 13 10:42:50 2008 -0700
     2.3 @@ -93,7 +93,8 @@
     2.4  
     2.5  
     2.6  @synthesize connection=_connection, number=_number, isMine=_isMine, isMutable=_isMutable,
     2.7 -            _bytesWritten, sent=_sent, propertiesAvailable=_propertiesAvailable, complete=_complete;
     2.8 +            _bytesWritten, sent=_sent, propertiesAvailable=_propertiesAvailable, complete=_complete,
     2.9 +            representedObject=_representedObject;
    2.10  
    2.11  
    2.12  - (void) _setFlag: (BLIPMessageFlags)flag value: (BOOL)value
     3.1 --- a/BLIP/BLIPRequest.m	Mon Jun 23 14:02:31 2008 -0700
     3.2 +++ b/BLIP/BLIPRequest.m	Sun Jul 13 10:42:50 2008 -0700
     3.3 @@ -175,7 +175,7 @@
     3.4      if( ! (_flags & kBLIP_ERR) )
     3.5          return nil;
     3.6      
     3.7 -    NSMutableDictionary *userInfo = [[self.properties allProperties] mutableCopy];
     3.8 +    NSMutableDictionary *userInfo = [[[self.properties allProperties] mutableCopy] autorelease];
     3.9      NSString *domain = [userInfo objectForKey: @"Error-Domain"];
    3.10      int code = [[userInfo objectForKey: @"Error-Code"] intValue];
    3.11      if( domain==nil || code==0 ) {
    3.12 @@ -255,7 +255,7 @@
    3.13  - (void) _connectionClosed
    3.14  {
    3.15      [super _connectionClosed];
    3.16 -    if( !_isMine ) {
    3.17 +    if( !_isMine && !_complete ) {
    3.18          // Change incoming response to an error:
    3.19          _isMutable = YES;
    3.20          [_properties autorelease];
    3.21 @@ -263,6 +263,7 @@
    3.22          [self _setError: BLIPMakeError(kBLIPError_Disconnected,
    3.23                                           @"Connection closed before response was received")];
    3.24          _isMutable = NO;
    3.25 +        self.complete = YES;    // Calls onComplete target
    3.26      }
    3.27  }
    3.28  
     4.1 --- a/BLIP/BLIPTest.m	Mon Jun 23 14:02:31 2008 -0700
     4.2 +++ b/BLIP/BLIPTest.m	Sun Jul 13 10:42:50 2008 -0700
     4.3 @@ -36,6 +36,7 @@
     4.4  #define kListenerRequiresSSL        NO
     4.5  #define kListenerRequiresClientCert NO
     4.6  #define kListenerCloseAfter         50
     4.7 +#define kClientAcceptCloseRequest   YES
     4.8  
     4.9  
    4.10  static SecIdentityRef GetClientIdentity(void) {
    4.11 @@ -196,7 +197,7 @@
    4.12  
    4.13  - (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection
    4.14  {
    4.15 -    BOOL response = NO;
    4.16 +    BOOL response = kClientAcceptCloseRequest;
    4.17      Log(@"***** %@ received a close request; returning %i",connection,response);
    4.18      return response;
    4.19  }
     5.1 --- a/MYNetwork.xcodeproj/project.pbxproj	Mon Jun 23 14:02:31 2008 -0700
     5.2 +++ b/MYNetwork.xcodeproj/project.pbxproj	Sun Jul 13 10:42:50 2008 -0700
     5.3 @@ -70,6 +70,7 @@
     5.4  		277905280DE9E5BC00C6D295 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 270461910DE4975C003D9D3F /* CoreServices.framework */; };
     5.5  		277905300DE9ED9100C6D295 /* MYUtilitiesTest_main.m in Sources */ = {isa = PBXBuildFile; fileRef = 270462C10DE4A64B003D9D3F /* MYUtilitiesTest_main.m */; };
     5.6  		2779053B0DE9EDAA00C6D295 /* BLIPTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 270460FE0DE49030003D9D3F /* BLIPTest.m */; };
     5.7 +		277ECFBC0E2A73A100D756BB /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2704618B0DE49652003D9D3F /* libz.dylib */; };
     5.8  		27D5EC070DE5FEDE00CD84FA /* BLIPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D5EC060DE5FEDE00CD84FA /* BLIPRequest.m */; };
     5.9  		27E0DBF00DF3450F00E7F648 /* GTMNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E0DBEF0DF3450F00E7F648 /* GTMNSData+zlib.m */; };
    5.10  		27E0DBF10DF3450F00E7F648 /* GTMNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 27E0DBEF0DF3450F00E7F648 /* GTMNSData+zlib.m */; };
    5.11 @@ -165,6 +166,7 @@
    5.12  			isa = PBXFrameworksBuildPhase;
    5.13  			buildActionMask = 2147483647;
    5.14  			files = (
    5.15 +				277ECFBC0E2A73A100D756BB /* libz.dylib in Frameworks */,
    5.16  			);
    5.17  			runOnlyForDeploymentPostprocessing = 0;
    5.18  		};
     6.1 --- a/TCP/TCPListener.h	Mon Jun 23 14:02:31 2008 -0700
     6.2 +++ b/TCP/TCPListener.h	Sun Jul 13 10:42:50 2008 -0700
     6.3 @@ -98,6 +98,9 @@
     6.4  /** Current error status of Bonjour service advertising. See NSNetServicesError for error codes. */
     6.5  @property (readonly) NSInteger /*NSNetServicesError*/ bonjourError;
     6.6  
     6.7 +/** The NSNetService being published. */
     6.8 +@property (readonly) NSNetService* bonjourService;
     6.9 +
    6.10  
    6.11  @end
    6.12  
     7.1 --- a/TCP/TCPListener.m	Mon Jun 23 14:02:31 2008 -0700
     7.2 +++ b/TCP/TCPListener.m	Sun Jul 13 10:42:50 2008 -0700
     7.3 @@ -23,6 +23,8 @@
     7.4                                        CFDataRef address, const void *data, void *info);
     7.5  
     7.6  @interface TCPListener()
     7.7 +- (void) _openBonjour;
     7.8 +- (void) _closeBonjour;
     7.9  @property BOOL bonjourPublished;
    7.10  @property NSInteger bonjourError;
    7.11  - (void) _updateTXTRecord;
    7.12 @@ -51,8 +53,9 @@
    7.13  
    7.14  
    7.15  @synthesize delegate=_delegate, port=_port, useIPv6=_useIPv6,
    7.16 -            bonjourServiceType=_bonjourServiceType, bonjourServiceName=_bonjourServiceName,
    7.17 +            bonjourServiceType=_bonjourServiceType,
    7.18              bonjourPublished=_bonjourPublished, bonjourError=_bonjourError,
    7.19 +            bonjourService=_netService,
    7.20              pickAvailablePort=_pickAvailablePort;
    7.21  
    7.22  
    7.23 @@ -62,7 +65,7 @@
    7.24  }
    7.25  
    7.26  
    7.27 -// Stores the last error from CFSocketCreate or CFSocketSetAddress into *ouError.
    7.28 +// Stores the last error from CFSocketCreate or CFSocketSetAddress into *outError.
    7.29  static void* getLastCFSocketError( NSError **outError ) {
    7.30      if( outError )
    7.31          *outError = [NSError errorWithDomain: NSPOSIXErrorDomain code: errno userInfo: nil];
    7.32 @@ -160,23 +163,7 @@
    7.33          }
    7.34      }
    7.35      
    7.36 -    // Open Bonjour:
    7.37 -    if( _bonjourServiceType && !_netService) {
    7.38 -        // instantiate the NSNetService object that will advertise on our behalf.
    7.39 -        _netService = [[NSNetService alloc] initWithDomain: @"local." 
    7.40 -                                                      type: _bonjourServiceType
    7.41 -                                                      name: _bonjourServiceName ?:@""
    7.42 -                                                      port: _port];
    7.43 -        if( _netService ) {
    7.44 -            [_netService setDelegate:self];
    7.45 -            if( _bonjourTXTRecord )
    7.46 -                [self _updateTXTRecord];
    7.47 -            [_netService publish];
    7.48 -        } else {
    7.49 -            self.bonjourError = -1;
    7.50 -            Warn(@"%@: Failed to create NSNetService",self);
    7.51 -        }
    7.52 -    }
    7.53 +    [self _openBonjour];
    7.54  
    7.55      LogTo(TCP,@"%@ is open",self);
    7.56      [self tellDelegate: @selector(listenerDidOpen:) withObject: nil];
    7.57 @@ -192,14 +179,7 @@
    7.58  - (void) close 
    7.59  {
    7.60      if( _ipv4socket ) {
    7.61 -        if( _netService ) {
    7.62 -            [_netService stop];
    7.63 -            [_netService release];
    7.64 -            _netService = nil;
    7.65 -            self.bonjourPublished = NO;
    7.66 -        }
    7.67 -        self.bonjourError = 0;
    7.68 -
    7.69 +        [self _closeBonjour];
    7.70          _ipv4socket = closeSocket(_ipv4socket);
    7.71          _ipv6socket = closeSocket(_ipv6socket);
    7.72  
    7.73 @@ -266,6 +246,51 @@
    7.74  #pragma mark BONJOUR:
    7.75  
    7.76  
    7.77 +- (void) _openBonjour
    7.78 +{
    7.79 +    if( self.isOpen && _bonjourServiceType && !_netService) {
    7.80 +        // instantiate the NSNetService object that will advertise on our behalf.
    7.81 +        _netService = [[NSNetService alloc] initWithDomain: @"local." 
    7.82 +                                                      type: _bonjourServiceType
    7.83 +                                                      name: _bonjourServiceName ?:@""
    7.84 +                                                      port: _port];
    7.85 +        if( _netService ) {
    7.86 +            [_netService setDelegate:self];
    7.87 +            if( _bonjourTXTRecord )
    7.88 +                [self _updateTXTRecord];
    7.89 +            [_netService publish];
    7.90 +        } else {
    7.91 +            self.bonjourError = -1;
    7.92 +            Warn(@"%@: Failed to create NSNetService",self);
    7.93 +        }
    7.94 +    }
    7.95 +}
    7.96 +
    7.97 +- (void) _closeBonjour
    7.98 +{
    7.99 +    if( _netService ) {
   7.100 +        [_netService stop];
   7.101 +        [_netService release];
   7.102 +        _netService = nil;
   7.103 +        self.bonjourPublished = NO;
   7.104 +    }
   7.105 +    if( self.bonjourError )
   7.106 +        self.bonjourError = 0;
   7.107 +}
   7.108 +
   7.109 +
   7.110 +- (NSString*) bonjourServiceName {return _bonjourServiceName;}
   7.111 +
   7.112 +- (void) setBonjourServiceName: (NSString*)name
   7.113 +{
   7.114 +    if( ! $equal(name,_bonjourServiceName) ) {
   7.115 +        [self _closeBonjour];
   7.116 +        setObj(&_bonjourServiceName,name);
   7.117 +        [self _openBonjour];
   7.118 +    }
   7.119 +}
   7.120 +
   7.121 +
   7.122  - (NSDictionary*) bonjourTXTRecord
   7.123  {
   7.124      return _bonjourTXTRecord;