* Added a timeout property to TCPConnection. Set it before calling -open, if you want a shorter timeout than the default.
authorJens Alfke <jens@mooseyard.com>
Wed Jun 11 14:58:38 2008 -0700 (2008-06-11)
changeset 166f608b552b77
parent 15 f723174fbc24
child 17 70590cc555aa
* Added a timeout property to TCPConnection. Set it before calling -open, if you want a shorter timeout than the default.
* Made the utility function BLIPMakeError public.
BLIP/BLIPMessage.h
BLIP/BLIP_Internal.h
Python/BLIP.py
TCP/TCPConnection.h
TCP/TCPConnection.m
     1.1 --- a/BLIP/BLIPMessage.h	Tue Jun 10 16:14:20 2008 -0700
     1.2 +++ b/BLIP/BLIPMessage.h	Wed Jun 11 14:58:38 2008 -0700
     1.3 @@ -30,6 +30,8 @@
     1.4      kBLIPError_Unspecified = 599            // peer didn't send any detailed error info
     1.5  };
     1.6  
     1.7 +NSError *BLIPMakeError( int errorCode, NSString *message, ... ) __attribute__ ((format (__NSString__, 2, 3)));
     1.8 +
     1.9  
    1.10  /** Abstract superclass for <a href=".#blipdesc">BLIP</a> requests and responses. */
    1.11  @interface BLIPMessage : NSObject 
     2.1 --- a/BLIP/BLIP_Internal.h	Tue Jun 10 16:14:20 2008 -0700
     2.2 +++ b/BLIP/BLIP_Internal.h	Wed Jun 11 14:58:38 2008 -0700
     2.3 @@ -44,9 +44,6 @@
     2.4  #define kBLIPFrameHeaderMagicNumber 0x9B34F205
     2.5  
     2.6  
     2.7 -NSError *BLIPMakeError( int errorCode, NSString *message, ... ) __attribute__ ((format (__NSString__, 2, 3)));
     2.8 -
     2.9 -
    2.10  @interface BLIPConnection ()
    2.11  - (void) _dispatchRequest: (BLIPRequest*)request;
    2.12  - (void) _dispatchResponse: (BLIPResponse*)response;
     3.1 --- a/Python/BLIP.py	Tue Jun 10 16:14:20 2008 -0700
     3.2 +++ b/Python/BLIP.py	Wed Jun 11 14:58:38 2008 -0700
     3.3 @@ -421,7 +421,7 @@
     3.4      
     3.5      @property
     3.6      def sent(self):
     3.7 -        return 'encoded' in self.__dict__
     3.8 +        return hasattr(self,'encoded')
     3.9      
    3.10      def _encode(self):
    3.11          "Generates the message's encoded form, prior to sending it."
     4.1 --- a/TCP/TCPConnection.h	Tue Jun 10 16:14:20 2008 -0700
     4.2 +++ b/TCP/TCPConnection.h	Wed Jun 11 14:58:38 2008 -0700
     4.3 @@ -36,17 +36,13 @@
     4.4      TCPReader *_reader;
     4.5      TCPWriter *_writer;
     4.6      NSError *_error;
     4.7 +    NSTimeInterval _openTimeout;
     4.8  }
     4.9  
    4.10  /** Initializes a TCPConnection to the given IP address.
    4.11      Afer configuring settings, you should call -open to begin the connection. */
    4.12  - (id) initToAddress: (IPAddress*)address;
    4.13  
    4.14 -/** Initializes a TCPConnection to the given IP address, binding to a specific outgoing port
    4.15 -    number. (This is usually only necessary when attempting to tunnel through a NAT.) */
    4.16 -- (id) initToAddress: (IPAddress*)address
    4.17 -           localPort: (UInt16)localPort;
    4.18 -
    4.19  /** Initializes a TCPConnection to the given NSNetService's address and port.
    4.20      If the service's address cannot be resolved, nil is returned. */
    4.21  - (id) initToNetService: (NSNetService*)service;
    4.22 @@ -55,6 +51,9 @@
    4.23      You don't usually need to call this; TCPListener does it automatically. */
    4.24  - (id) initIncomingFromSocket: (CFSocketNativeHandle)socket listener: (TCPListener*)listener;
    4.25  
    4.26 +/** Timeout for waiting to open a connection. (Default is zero, meaning the OS default timeout.) */
    4.27 +@property NSTimeInterval openTimeout;
    4.28 +
    4.29  /** The delegate object that will be called when the connection opens, closes or receives messages. */
    4.30  @property (assign) id<TCPConnectionDelegate> delegate;
    4.31  
     5.1 --- a/TCP/TCPConnection.m	Tue Jun 10 16:14:20 2008 -0700
     5.2 +++ b/TCP/TCPConnection.m	Wed Jun 11 14:58:38 2008 -0700
     5.3 @@ -67,7 +67,6 @@
     5.4  
     5.5  
     5.6  - (id) initToAddress: (IPAddress*)address
     5.7 -           localPort: (UInt16)localPort
     5.8  {
     5.9      NSInputStream *input = nil;
    5.10      NSOutputStream *output = nil;
    5.11 @@ -86,12 +85,6 @@
    5.12                    outputStream: &output];
    5.13  #endif
    5.14      return [self _initWithAddress: address inputStream: input outputStream: output];
    5.15 -    //FIX: Support localPort!
    5.16 -}
    5.17 -
    5.18 -- (id) initToAddress: (IPAddress*)address
    5.19 -{
    5.20 -    return [self initToAddress: address localPort: 0];
    5.21  }
    5.22  
    5.23  - (id) initToNetService: (NSNetService*)service
    5.24 @@ -147,7 +140,7 @@
    5.25  
    5.26  
    5.27  @synthesize address=_address, isIncoming=_isIncoming, status=_status, delegate=_delegate,
    5.28 -            reader=_reader, writer=_writer, server=_server;
    5.29 +            reader=_reader, writer=_writer, server=_server, openTimeout=_openTimeout;
    5.30  
    5.31  
    5.32  - (NSError*) error
    5.33 @@ -189,6 +182,22 @@
    5.34          if( ! [sAllConnections my_containsObjectIdenticalTo: self] )
    5.35              [sAllConnections addObject: self];
    5.36          self.status = kTCP_Opening;
    5.37 +        if( _openTimeout > 0 )
    5.38 +            [self performSelector: @selector(_openTimeoutExpired) withObject: nil afterDelay: _openTimeout];
    5.39 +    }
    5.40 +}
    5.41 +
    5.42 +- (void) _stopOpenTimer
    5.43 +{
    5.44 +    [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(_openTimeoutExpired) object: nil];
    5.45 +}
    5.46 +
    5.47 +- (void) _openTimeoutExpired
    5.48 +{
    5.49 +    if( _status == kTCP_Opening ) {
    5.50 +        LogTo(TCP,@"%@: timed out waiting to open",self);
    5.51 +        [self _stream: _reader gotError: [NSError errorWithDomain: NSPOSIXErrorDomain
    5.52 +                                                             code: ETIMEDOUT userInfo: nil]];
    5.53      }
    5.54  }
    5.55  
    5.56 @@ -203,6 +212,7 @@
    5.57          setObj(&_reader,nil);
    5.58          self.status = kTCP_Disconnected;
    5.59      }
    5.60 +    [self _stopOpenTimer];
    5.61  }
    5.62  
    5.63  
    5.64 @@ -213,6 +223,7 @@
    5.65  
    5.66  - (void) closeWithTimeout: (NSTimeInterval)timeout
    5.67  {
    5.68 +    [self _stopOpenTimer];
    5.69      if( _status == kTCP_Opening ) {
    5.70          LogTo(TCP,@"%@ canceling open",self);
    5.71          [self _closed];
    5.72 @@ -265,6 +276,7 @@
    5.73      [NSObject cancelPreviousPerformRequestsWithTarget: self
    5.74                                               selector: @selector(_closeTimeoutExpired)
    5.75                                                 object: nil];
    5.76 +    [self _stopOpenTimer];
    5.77      [sAllConnections removeObjectIdenticalTo: self];
    5.78  }
    5.79  
    5.80 @@ -297,6 +309,7 @@
    5.81          self.address = stream.peerAddress;
    5.82      if( _status==kTCP_Opening && _reader.isOpen && _writer.isOpen ) {
    5.83          LogTo(TCP,@"%@ opened; address=%@",self,_address);
    5.84 +        [self _stopOpenTimer];
    5.85          self.status = kTCP_Open;
    5.86          [self tellDelegate: @selector(connectionDidOpen:) withObject: nil];
    5.87      }