diff -r 000000000000 -r de59ce19f42e 1_0_to_1_1_diffs.diff --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/1_0_to_1_1_diffs.diff Tue Jun 23 11:44:30 2009 -0700 @@ -0,0 +1,425 @@ +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPConnection.h +--- a/BLIP/BLIPConnection.h Thu Jun 19 10:22:19 2008 -0700 ++++ b/BLIP/BLIPConnection.h Mon Jun 23 14:02:31 2008 -0700 +@@ -20,6 +20,7 @@ + @interface BLIPConnection : TCPConnection + { + BLIPDispatcher *_dispatcher; ++ BOOL _blipClosing; + } + + /** The delegate object that will be called when the connection opens, closes or receives messages. */ +@@ -73,6 +74,13 @@ + /** Called when a BLIPResponse (to one of your requests) is received from the peer. + This is called after the response object's onComplete target, if any, is invoked.*/ + - (void) connection: (BLIPConnection*)connection receivedResponse: (BLIPResponse*)response; ++ ++/** Called when the peer wants to close the connection. Return YES to allow, NO to prevent. */ ++- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection; ++ ++/** Called if the peer refuses a close request. ++ The typical error is kBLIPError_Forbidden. */ ++- (void) connection: (BLIPConnection*)connection closeRequestFailedWithError: (NSError*)error; + @end + + +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPConnection.m +--- a/BLIP/BLIPConnection.m Thu Jun 19 10:22:19 2008 -0700 ++++ b/BLIP/BLIPConnection.m Mon Jun 23 14:02:31 2008 -0700 +@@ -8,6 +8,7 @@ + + #import "BLIPConnection.h" + #import "BLIP_Internal.h" ++#import "TCP_Internal.h" + #import "BLIPReader.h" + #import "BLIPWriter.h" + #import "BLIPDispatcher.h" +@@ -15,6 +16,7 @@ + #import "Logging.h" + #import "Test.h" + #import "ExceptionUtils.h" ++#import "Target.h" + + + NSString* const BLIPErrorDomain = @"BLIP"; +@@ -33,10 +35,14 @@ + } + + ++@interface BLIPConnection () ++- (void) _handleCloseRequest: (BLIPRequest*)request; ++@end + + + @implementation BLIPConnection + ++ + - (void) dealloc + { + [_dispatcher release]; +@@ -48,6 +54,11 @@ + - (id) delegate {return (id)_delegate;} + - (void) setDelegate: (id)delegate {_delegate = delegate;} + ++ ++#pragma mark - ++#pragma mark RECEIVING: ++ ++ + - (BLIPDispatcher*) dispatcher + { + if( ! _dispatcher ) { +@@ -58,11 +69,23 @@ + } + + ++- (void) _dispatchMetaRequest: (BLIPRequest*)request ++{ ++ NSString* profile = request.profile; ++ if( [profile isEqualToString: kBLIPProfile_Bye] ) ++ [self _handleCloseRequest: request]; ++ else ++ [request respondWithErrorCode: kBLIPError_NotFound message: @"Unknown meta profile"]; ++} ++ ++ + - (void) _dispatchRequest: (BLIPRequest*)request + { + LogTo(BLIP,@"Received all of %@",request.descriptionWithProperties); + @try{ +- if( ! [self.dispatcher dispatchMessage: request] ) ++ if( request._flags & kBLIP_Meta ) ++ [self _dispatchMetaRequest: request]; ++ else if( ! [self.dispatcher dispatchMessage: request] ) + [self tellDelegate: @selector(connection:receivedRequest:) withObject: request]; + if( ! request.noReply && ! request.repliedTo ) { + LogTo(BLIP,@"Returning default empty response to %@",request); +@@ -81,6 +104,10 @@ + } + + ++#pragma mark - ++#pragma mark SENDING: ++ ++ + - (BLIPRequest*) request + { + return [[[BLIPRequest alloc] _initWithConnection: self body: nil properties: nil] autorelease]; +@@ -103,11 +130,61 @@ + } + + ++#pragma mark - ++#pragma mark CLOSING: ++ ++ ++- (void) _beginClose ++{ ++ // Override of TCPConnection method. Instead of closing the socket, send a 'bye' request: ++ if( ! _blipClosing ) { ++ LogTo(BLIPVerbose,@"Sending close request..."); ++ BLIPRequest *r = [self request]; ++ [r _setFlag: kBLIP_Meta value: YES]; ++ r.profile = kBLIPProfile_Bye; ++ BLIPResponse *response = [r send]; ++ response.onComplete = $target(self,_receivedCloseResponse:); ++ } ++ // Put the writer in close mode, to prevent client from sending any more requests: ++ [self.writer close]; ++} ++ ++- (void) _receivedCloseResponse: (BLIPResponse*)response ++{ ++ NSError *error = response.error; ++ LogTo(BLIPVerbose,@"Received close response: error=%@",error); ++ if( error ) { ++ [self _unclose]; ++ [self tellDelegate: @selector(connection:closeRequestFailedWithError:) withObject: error]; ++ } else { ++ // Now finally close the socket: ++ [super _beginClose]; ++ } ++} ++ ++ ++- (void) _handleCloseRequest: (BLIPRequest*)request ++{ ++ LogTo(BLIPVerbose,@"Received a close request"); ++ if( [_delegate respondsToSelector: @selector(connectionReceivedCloseRequest:)] ) ++ if( ! [_delegate connectionReceivedCloseRequest: self] ) { ++ LogTo(BLIPVerbose,@"Responding with denial of close request"); ++ [request respondWithErrorCode: kBLIPError_Forbidden message: @"Close request denied"]; ++ return; ++ } ++ ++ LogTo(BLIPVerbose,@"Close request accepted"); ++ _blipClosing = YES; // this prevents _beginClose from sending a close request back ++ [self close]; ++} ++ ++ + @end + + + + ++#pragma mark - + @implementation BLIPListener + + - (id) initWithPort: (UInt16)port +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPMessage.m +--- a/BLIP/BLIPMessage.m Thu Jun 19 10:22:19 2008 -0700 ++++ b/BLIP/BLIPMessage.m Mon Jun 23 14:02:31 2008 -0700 +@@ -74,6 +74,8 @@ + [desc appendString: @", urgent"]; + if( _flags & kBLIP_NoReply ) + [desc appendString: @", noreply"]; ++ if( _flags & kBLIP_Meta ) ++ [desc appendString: @", META"]; + [desc appendString: @"]"]; + return desc; + } +@@ -103,6 +105,8 @@ + _flags &= ~flag; + } + ++- (BLIPMessageFlags) _flags {return _flags;} ++ + - (BOOL) compressed {return (_flags & kBLIP_Compressed) != 0;} + - (BOOL) urgent {return (_flags & kBLIP_Urgent) != 0;} + - (void) setCompressed: (BOOL)compressed {[self _setFlag: kBLIP_Compressed value: compressed];} +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPReader.m +--- a/BLIP/BLIPReader.m Thu Jun 19 10:22:19 2008 -0700 ++++ b/BLIP/BLIPReader.m Mon Jun 23 14:02:31 2008 -0700 +@@ -93,7 +93,7 @@ + + - (BOOL) isBusy + { +- return _curBytesRead > 0; ++ return _curBytesRead > 0 || _pendingRequests.count > 0 || _pendingResponses.count > 0; + } + + +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPRequest.m +--- a/BLIP/BLIPRequest.m Thu Jun 19 10:22:19 2008 -0700 ++++ b/BLIP/BLIPRequest.m Mon Jun 23 14:02:31 2008 -0700 +@@ -199,6 +199,8 @@ + setObj(&_mutableBody,nil); + + BLIPMutableProperties *errorProps = [self.properties mutableCopy]; ++ if( ! errorProps ) ++ errorProps = [[BLIPMutableProperties alloc] init]; + NSDictionary *userInfo = error.userInfo; + for( NSString *key in userInfo ) { + id value = $castIf(NSString,[userInfo objectForKey: key]); +@@ -227,8 +229,12 @@ + { + Assert(_connection,@"%@ has no connection to send over",self); + Assert(!_sent,@"%@ was already sent",self); ++ BLIPWriter *writer = (BLIPWriter*)_connection.writer; ++ Assert(writer,@"%@'s connection has no writer (already closed?)",self); + [self _encode]; +- return (self.sent = [(BLIPWriter*)_connection.writer sendMessage: self]); ++ BOOL sent = self.sent = [writer sendMessage: self]; ++ Assert(sent); ++ return sent; + } + + +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPTest.m +--- a/BLIP/BLIPTest.m Thu Jun 19 10:22:19 2008 -0700 ++++ b/BLIP/BLIPTest.m Mon Jun 23 14:02:31 2008 -0700 +@@ -35,6 +35,7 @@ + #define kClientUsesSSLCert NO + #define kListenerRequiresSSL NO + #define kListenerRequiresClientCert NO ++#define kListenerCloseAfter 50 + + + static SecIdentityRef GetClientIdentity(void) { +@@ -100,36 +101,38 @@ + + - (void) sendAMessage + { +- if(_pending.count<100) { +- Log(@"** Sending another %i messages...", kNBatchedMessages); +- for( int i=0; i 12 ) +- q.urgent = YES; +- BLIPResponse *response = [q send]; +- Assert(response); +- Assert(q.number>0); +- Assert(response.number==q.number); +- [_pending setObject: $object(size) forKey: $object(q.number)]; +- response.onComplete = $target(self,responseArrived:); ++ if( _conn.status==kTCP_Open || _conn.status==kTCP_Opening ) { ++ if(_pending.count<100) { ++ Log(@"** Sending another %i messages...", kNBatchedMessages); ++ for( int i=0; i 12 ) ++ q.urgent = YES; ++ BLIPResponse *response = [q send]; ++ Assert(response); ++ Assert(q.number>0); ++ Assert(response.number==q.number); ++ [_pending setObject: $object(size) forKey: $object(q.number)]; ++ response.onComplete = $target(self,responseArrived:); ++ } ++ } else { ++ Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count); + } +- } else { +- Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count); ++ [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval]; + } +- [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval]; + } + + - (void) responseArrived: (BLIPResponse*)response +@@ -191,6 +194,13 @@ + Log(@"Now %u replies pending", _pending.count); + } + ++- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection ++{ ++ BOOL response = NO; ++ Log(@"***** %@ received a close request; returning %i",connection,response); ++ return response; ++} ++ + + @end + +@@ -217,6 +227,7 @@ + @interface BLIPTestListener : NSObject + { + BLIPListener *_listener; ++ int _nReceived; + } + + @end +@@ -277,6 +288,7 @@ + - (void) connectionDidOpen: (TCPConnection*)connection + { + Log(@"** %@ didOpen [SSL=%@]",connection,connection.actualSecurityLevel); ++ _nReceived = 0; + } + - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert + { +@@ -312,6 +324,22 @@ + AssertEq([[request valueOfProperty: @"Size"] intValue], size); + + [request respondWithData: body contentType: request.contentType]; ++ ++ if( ++ _nReceived == kListenerCloseAfter ) { ++ Log(@"********** Closing BLIPTestListener after %i requests",_nReceived); ++ [connection close]; ++ } ++} ++ ++- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection; ++{ ++ Log(@"***** %@ received a close request",connection); ++ return YES; ++} ++ ++- (void) connection: (BLIPConnection*)connection closeRequestFailedWithError: (NSError*)error ++{ ++ Log(@"***** %@'s close request failed: %@",connection,error); + } + + +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPWriter.m +--- a/BLIP/BLIPWriter.m Thu Jun 19 10:22:19 2008 -0700 ++++ b/BLIP/BLIPWriter.m Mon Jun 23 14:02:31 2008 -0700 +@@ -79,10 +79,6 @@ + + - (BOOL) sendMessage: (BLIPMessage*)message + { +- if( _shouldClose ) { +- Warn(@"%@: Attempt to send a message after the connection has started closing",self); +- return NO; +- } + Assert(!message.sent,@"message has already been sent"); + [self _queueMessage: message isNew: YES]; + return YES; +@@ -91,12 +87,14 @@ + + - (BOOL) sendRequest: (BLIPRequest*)q response: (BLIPResponse*)response + { +- if( !_shouldClose ) { +- [q _assignedNumber: ++_numRequestsSent]; +- if( response ) { +- [response _assignedNumber: _numRequestsSent]; +- [(BLIPReader*)self.reader _addPendingResponse: response]; +- } ++ if( _shouldClose ) { ++ Warn(@"%@: Attempt to send a request after the connection has started closing: %@",self,q); ++ return NO; ++ } ++ [q _assignedNumber: ++_numRequestsSent]; ++ if( response ) { ++ [response _assignedNumber: _numRequestsSent]; ++ [(BLIPReader*)self.reader _addPendingResponse: response]; + } + return [self sendMessage: q]; + } +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIP_Internal.h +--- a/BLIP/BLIP_Internal.h Thu Jun 19 10:22:19 2008 -0700 ++++ b/BLIP/BLIP_Internal.h Mon Jun 23 14:02:31 2008 -0700 +@@ -29,6 +29,7 @@ + kBLIP_Urgent = 0x0020, // please send sooner/faster + kBLIP_NoReply = 0x0040, // no RPY needed + kBLIP_MoreComing= 0x0080, // More frames coming (Applies only to individual frame) ++ kBLIP_Meta = 0x0100, // Special message type, handled internally (hello, bye, ...) + }; + typedef UInt16 BLIPMessageFlags; + +@@ -41,7 +42,10 @@ + UInt16 size; // total size of frame, _including_ this header + } BLIPFrameHeader; + +-#define kBLIPFrameHeaderMagicNumber 0x9B34F205 ++#define kBLIPFrameHeaderMagicNumber 0x9B34F206 ++ ++#define kBLIPProfile_Hi @"Hi" // Used for Profile header in meta greeting message ++#define kBLIPProfile_Bye @"Bye" // Used for Profile header in meta close-request message + + + @interface BLIPConnection () +@@ -52,6 +56,7 @@ + + @interface BLIPMessage () + @property BOOL sent, propertiesAvailable, complete; ++- (BLIPMessageFlags) _flags; + - (void) _setFlag: (BLIPMessageFlags)flag value: (BOOL)value; + - (void) _encode; + @end