* 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.
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 }