# HG changeset patch # User Jens Alfke # Date 1213221518 25200 # Node ID 6f608b552b77b81fbe21cec8fea2b04cda3bc504 # Parent f723174fbc24592513dcf1ad6d8ccc9d8a7c16a9 * 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. diff -r f723174fbc24 -r 6f608b552b77 BLIP/BLIPMessage.h --- a/BLIP/BLIPMessage.h Tue Jun 10 16:14:20 2008 -0700 +++ b/BLIP/BLIPMessage.h Wed Jun 11 14:58:38 2008 -0700 @@ -30,6 +30,8 @@ kBLIPError_Unspecified = 599 // peer didn't send any detailed error info }; +NSError *BLIPMakeError( int errorCode, NSString *message, ... ) __attribute__ ((format (__NSString__, 2, 3))); + /** Abstract superclass for BLIP requests and responses. */ @interface BLIPMessage : NSObject diff -r f723174fbc24 -r 6f608b552b77 BLIP/BLIP_Internal.h --- a/BLIP/BLIP_Internal.h Tue Jun 10 16:14:20 2008 -0700 +++ b/BLIP/BLIP_Internal.h Wed Jun 11 14:58:38 2008 -0700 @@ -44,9 +44,6 @@ #define kBLIPFrameHeaderMagicNumber 0x9B34F205 -NSError *BLIPMakeError( int errorCode, NSString *message, ... ) __attribute__ ((format (__NSString__, 2, 3))); - - @interface BLIPConnection () - (void) _dispatchRequest: (BLIPRequest*)request; - (void) _dispatchResponse: (BLIPResponse*)response; diff -r f723174fbc24 -r 6f608b552b77 Python/BLIP.py --- a/Python/BLIP.py Tue Jun 10 16:14:20 2008 -0700 +++ b/Python/BLIP.py Wed Jun 11 14:58:38 2008 -0700 @@ -421,7 +421,7 @@ @property def sent(self): - return 'encoded' in self.__dict__ + return hasattr(self,'encoded') def _encode(self): "Generates the message's encoded form, prior to sending it." diff -r f723174fbc24 -r 6f608b552b77 TCP/TCPConnection.h --- a/TCP/TCPConnection.h Tue Jun 10 16:14:20 2008 -0700 +++ b/TCP/TCPConnection.h Wed Jun 11 14:58:38 2008 -0700 @@ -36,17 +36,13 @@ TCPReader *_reader; TCPWriter *_writer; NSError *_error; + NSTimeInterval _openTimeout; } /** Initializes a TCPConnection to the given IP address. Afer configuring settings, you should call -open to begin the connection. */ - (id) initToAddress: (IPAddress*)address; -/** Initializes a TCPConnection to the given IP address, binding to a specific outgoing port - number. (This is usually only necessary when attempting to tunnel through a NAT.) */ -- (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; @@ -55,6 +51,9 @@ You don't usually need to call this; TCPListener does it automatically. */ - (id) initIncomingFromSocket: (CFSocketNativeHandle)socket listener: (TCPListener*)listener; +/** Timeout for waiting to open a connection. (Default is zero, meaning the OS default timeout.) */ +@property NSTimeInterval openTimeout; + /** The delegate object that will be called when the connection opens, closes or receives messages. */ @property (assign) id delegate; diff -r f723174fbc24 -r 6f608b552b77 TCP/TCPConnection.m --- a/TCP/TCPConnection.m Tue Jun 10 16:14:20 2008 -0700 +++ b/TCP/TCPConnection.m Wed Jun 11 14:58:38 2008 -0700 @@ -67,7 +67,6 @@ - (id) initToAddress: (IPAddress*)address - localPort: (UInt16)localPort { NSInputStream *input = nil; NSOutputStream *output = nil; @@ -86,12 +85,6 @@ outputStream: &output]; #endif return [self _initWithAddress: address inputStream: input outputStream: output]; - //FIX: Support localPort! -} - -- (id) initToAddress: (IPAddress*)address -{ - return [self initToAddress: address localPort: 0]; } - (id) initToNetService: (NSNetService*)service @@ -147,7 +140,7 @@ @synthesize address=_address, isIncoming=_isIncoming, status=_status, delegate=_delegate, - reader=_reader, writer=_writer, server=_server; + reader=_reader, writer=_writer, server=_server, openTimeout=_openTimeout; - (NSError*) error @@ -189,6 +182,22 @@ if( ! [sAllConnections my_containsObjectIdenticalTo: self] ) [sAllConnections addObject: self]; self.status = kTCP_Opening; + if( _openTimeout > 0 ) + [self performSelector: @selector(_openTimeoutExpired) withObject: nil afterDelay: _openTimeout]; + } +} + +- (void) _stopOpenTimer +{ + [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(_openTimeoutExpired) object: nil]; +} + +- (void) _openTimeoutExpired +{ + if( _status == kTCP_Opening ) { + LogTo(TCP,@"%@: timed out waiting to open",self); + [self _stream: _reader gotError: [NSError errorWithDomain: NSPOSIXErrorDomain + code: ETIMEDOUT userInfo: nil]]; } } @@ -203,6 +212,7 @@ setObj(&_reader,nil); self.status = kTCP_Disconnected; } + [self _stopOpenTimer]; } @@ -213,6 +223,7 @@ - (void) closeWithTimeout: (NSTimeInterval)timeout { + [self _stopOpenTimer]; if( _status == kTCP_Opening ) { LogTo(TCP,@"%@ canceling open",self); [self _closed]; @@ -265,6 +276,7 @@ [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(_closeTimeoutExpired) object: nil]; + [self _stopOpenTimer]; [sAllConnections removeObjectIdenticalTo: self]; } @@ -297,6 +309,7 @@ self.address = stream.peerAddress; if( _status==kTCP_Opening && _reader.isOpen && _writer.isOpen ) { LogTo(TCP,@"%@ opened; address=%@",self,_address); + [self _stopOpenTimer]; self.status = kTCP_Open; [self tellDelegate: @selector(connectionDidOpen:) withObject: nil]; }