1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/1_0_to_1_1_diffs.diff Tue Jun 23 11:44:30 2009 -0700
1.3 @@ -0,0 +1,425 @@
1.4 +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPConnection.h
1.5 +--- a/BLIP/BLIPConnection.h Thu Jun 19 10:22:19 2008 -0700
1.6 ++++ b/BLIP/BLIPConnection.h Mon Jun 23 14:02:31 2008 -0700
1.7 +@@ -20,6 +20,7 @@
1.8 + @interface BLIPConnection : TCPConnection
1.9 + {
1.10 + BLIPDispatcher *_dispatcher;
1.11 ++ BOOL _blipClosing;
1.12 + }
1.13 +
1.14 + /** The delegate object that will be called when the connection opens, closes or receives messages. */
1.15 +@@ -73,6 +74,13 @@
1.16 + /** Called when a BLIPResponse (to one of your requests) is received from the peer.
1.17 + This is called <i>after</i> the response object's onComplete target, if any, is invoked.*/
1.18 + - (void) connection: (BLIPConnection*)connection receivedResponse: (BLIPResponse*)response;
1.19 ++
1.20 ++/** Called when the peer wants to close the connection. Return YES to allow, NO to prevent. */
1.21 ++- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection;
1.22 ++
1.23 ++/** Called if the peer refuses a close request.
1.24 ++ The typical error is kBLIPError_Forbidden. */
1.25 ++- (void) connection: (BLIPConnection*)connection closeRequestFailedWithError: (NSError*)error;
1.26 + @end
1.27 +
1.28 +
1.29 +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPConnection.m
1.30 +--- a/BLIP/BLIPConnection.m Thu Jun 19 10:22:19 2008 -0700
1.31 ++++ b/BLIP/BLIPConnection.m Mon Jun 23 14:02:31 2008 -0700
1.32 +@@ -8,6 +8,7 @@
1.33 +
1.34 + #import "BLIPConnection.h"
1.35 + #import "BLIP_Internal.h"
1.36 ++#import "TCP_Internal.h"
1.37 + #import "BLIPReader.h"
1.38 + #import "BLIPWriter.h"
1.39 + #import "BLIPDispatcher.h"
1.40 +@@ -15,6 +16,7 @@
1.41 + #import "Logging.h"
1.42 + #import "Test.h"
1.43 + #import "ExceptionUtils.h"
1.44 ++#import "Target.h"
1.45 +
1.46 +
1.47 + NSString* const BLIPErrorDomain = @"BLIP";
1.48 +@@ -33,10 +35,14 @@
1.49 + }
1.50 +
1.51 +
1.52 ++@interface BLIPConnection ()
1.53 ++- (void) _handleCloseRequest: (BLIPRequest*)request;
1.54 ++@end
1.55 +
1.56 +
1.57 + @implementation BLIPConnection
1.58 +
1.59 ++
1.60 + - (void) dealloc
1.61 + {
1.62 + [_dispatcher release];
1.63 +@@ -48,6 +54,11 @@
1.64 + - (id<BLIPConnectionDelegate>) delegate {return (id)_delegate;}
1.65 + - (void) setDelegate: (id<BLIPConnectionDelegate>)delegate {_delegate = delegate;}
1.66 +
1.67 ++
1.68 ++#pragma mark -
1.69 ++#pragma mark RECEIVING:
1.70 ++
1.71 ++
1.72 + - (BLIPDispatcher*) dispatcher
1.73 + {
1.74 + if( ! _dispatcher ) {
1.75 +@@ -58,11 +69,23 @@
1.76 + }
1.77 +
1.78 +
1.79 ++- (void) _dispatchMetaRequest: (BLIPRequest*)request
1.80 ++{
1.81 ++ NSString* profile = request.profile;
1.82 ++ if( [profile isEqualToString: kBLIPProfile_Bye] )
1.83 ++ [self _handleCloseRequest: request];
1.84 ++ else
1.85 ++ [request respondWithErrorCode: kBLIPError_NotFound message: @"Unknown meta profile"];
1.86 ++}
1.87 ++
1.88 ++
1.89 + - (void) _dispatchRequest: (BLIPRequest*)request
1.90 + {
1.91 + LogTo(BLIP,@"Received all of %@",request.descriptionWithProperties);
1.92 + @try{
1.93 +- if( ! [self.dispatcher dispatchMessage: request] )
1.94 ++ if( request._flags & kBLIP_Meta )
1.95 ++ [self _dispatchMetaRequest: request];
1.96 ++ else if( ! [self.dispatcher dispatchMessage: request] )
1.97 + [self tellDelegate: @selector(connection:receivedRequest:) withObject: request];
1.98 + if( ! request.noReply && ! request.repliedTo ) {
1.99 + LogTo(BLIP,@"Returning default empty response to %@",request);
1.100 +@@ -81,6 +104,10 @@
1.101 + }
1.102 +
1.103 +
1.104 ++#pragma mark -
1.105 ++#pragma mark SENDING:
1.106 ++
1.107 ++
1.108 + - (BLIPRequest*) request
1.109 + {
1.110 + return [[[BLIPRequest alloc] _initWithConnection: self body: nil properties: nil] autorelease];
1.111 +@@ -103,11 +130,61 @@
1.112 + }
1.113 +
1.114 +
1.115 ++#pragma mark -
1.116 ++#pragma mark CLOSING:
1.117 ++
1.118 ++
1.119 ++- (void) _beginClose
1.120 ++{
1.121 ++ // Override of TCPConnection method. Instead of closing the socket, send a 'bye' request:
1.122 ++ if( ! _blipClosing ) {
1.123 ++ LogTo(BLIPVerbose,@"Sending close request...");
1.124 ++ BLIPRequest *r = [self request];
1.125 ++ [r _setFlag: kBLIP_Meta value: YES];
1.126 ++ r.profile = kBLIPProfile_Bye;
1.127 ++ BLIPResponse *response = [r send];
1.128 ++ response.onComplete = $target(self,_receivedCloseResponse:);
1.129 ++ }
1.130 ++ // Put the writer in close mode, to prevent client from sending any more requests:
1.131 ++ [self.writer close];
1.132 ++}
1.133 ++
1.134 ++- (void) _receivedCloseResponse: (BLIPResponse*)response
1.135 ++{
1.136 ++ NSError *error = response.error;
1.137 ++ LogTo(BLIPVerbose,@"Received close response: error=%@",error);
1.138 ++ if( error ) {
1.139 ++ [self _unclose];
1.140 ++ [self tellDelegate: @selector(connection:closeRequestFailedWithError:) withObject: error];
1.141 ++ } else {
1.142 ++ // Now finally close the socket:
1.143 ++ [super _beginClose];
1.144 ++ }
1.145 ++}
1.146 ++
1.147 ++
1.148 ++- (void) _handleCloseRequest: (BLIPRequest*)request
1.149 ++{
1.150 ++ LogTo(BLIPVerbose,@"Received a close request");
1.151 ++ if( [_delegate respondsToSelector: @selector(connectionReceivedCloseRequest:)] )
1.152 ++ if( ! [_delegate connectionReceivedCloseRequest: self] ) {
1.153 ++ LogTo(BLIPVerbose,@"Responding with denial of close request");
1.154 ++ [request respondWithErrorCode: kBLIPError_Forbidden message: @"Close request denied"];
1.155 ++ return;
1.156 ++ }
1.157 ++
1.158 ++ LogTo(BLIPVerbose,@"Close request accepted");
1.159 ++ _blipClosing = YES; // this prevents _beginClose from sending a close request back
1.160 ++ [self close];
1.161 ++}
1.162 ++
1.163 ++
1.164 + @end
1.165 +
1.166 +
1.167 +
1.168 +
1.169 ++#pragma mark -
1.170 + @implementation BLIPListener
1.171 +
1.172 + - (id) initWithPort: (UInt16)port
1.173 +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPMessage.m
1.174 +--- a/BLIP/BLIPMessage.m Thu Jun 19 10:22:19 2008 -0700
1.175 ++++ b/BLIP/BLIPMessage.m Mon Jun 23 14:02:31 2008 -0700
1.176 +@@ -74,6 +74,8 @@
1.177 + [desc appendString: @", urgent"];
1.178 + if( _flags & kBLIP_NoReply )
1.179 + [desc appendString: @", noreply"];
1.180 ++ if( _flags & kBLIP_Meta )
1.181 ++ [desc appendString: @", META"];
1.182 + [desc appendString: @"]"];
1.183 + return desc;
1.184 + }
1.185 +@@ -103,6 +105,8 @@
1.186 + _flags &= ~flag;
1.187 + }
1.188 +
1.189 ++- (BLIPMessageFlags) _flags {return _flags;}
1.190 ++
1.191 + - (BOOL) compressed {return (_flags & kBLIP_Compressed) != 0;}
1.192 + - (BOOL) urgent {return (_flags & kBLIP_Urgent) != 0;}
1.193 + - (void) setCompressed: (BOOL)compressed {[self _setFlag: kBLIP_Compressed value: compressed];}
1.194 +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPReader.m
1.195 +--- a/BLIP/BLIPReader.m Thu Jun 19 10:22:19 2008 -0700
1.196 ++++ b/BLIP/BLIPReader.m Mon Jun 23 14:02:31 2008 -0700
1.197 +@@ -93,7 +93,7 @@
1.198 +
1.199 + - (BOOL) isBusy
1.200 + {
1.201 +- return _curBytesRead > 0;
1.202 ++ return _curBytesRead > 0 || _pendingRequests.count > 0 || _pendingResponses.count > 0;
1.203 + }
1.204 +
1.205 +
1.206 +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPRequest.m
1.207 +--- a/BLIP/BLIPRequest.m Thu Jun 19 10:22:19 2008 -0700
1.208 ++++ b/BLIP/BLIPRequest.m Mon Jun 23 14:02:31 2008 -0700
1.209 +@@ -199,6 +199,8 @@
1.210 + setObj(&_mutableBody,nil);
1.211 +
1.212 + BLIPMutableProperties *errorProps = [self.properties mutableCopy];
1.213 ++ if( ! errorProps )
1.214 ++ errorProps = [[BLIPMutableProperties alloc] init];
1.215 + NSDictionary *userInfo = error.userInfo;
1.216 + for( NSString *key in userInfo ) {
1.217 + id value = $castIf(NSString,[userInfo objectForKey: key]);
1.218 +@@ -227,8 +229,12 @@
1.219 + {
1.220 + Assert(_connection,@"%@ has no connection to send over",self);
1.221 + Assert(!_sent,@"%@ was already sent",self);
1.222 ++ BLIPWriter *writer = (BLIPWriter*)_connection.writer;
1.223 ++ Assert(writer,@"%@'s connection has no writer (already closed?)",self);
1.224 + [self _encode];
1.225 +- return (self.sent = [(BLIPWriter*)_connection.writer sendMessage: self]);
1.226 ++ BOOL sent = self.sent = [writer sendMessage: self];
1.227 ++ Assert(sent);
1.228 ++ return sent;
1.229 + }
1.230 +
1.231 +
1.232 +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPTest.m
1.233 +--- a/BLIP/BLIPTest.m Thu Jun 19 10:22:19 2008 -0700
1.234 ++++ b/BLIP/BLIPTest.m Mon Jun 23 14:02:31 2008 -0700
1.235 +@@ -35,6 +35,7 @@
1.236 + #define kClientUsesSSLCert NO
1.237 + #define kListenerRequiresSSL NO
1.238 + #define kListenerRequiresClientCert NO
1.239 ++#define kListenerCloseAfter 50
1.240 +
1.241 +
1.242 + static SecIdentityRef GetClientIdentity(void) {
1.243 +@@ -100,36 +101,38 @@
1.244 +
1.245 + - (void) sendAMessage
1.246 + {
1.247 +- if(_pending.count<100) {
1.248 +- Log(@"** Sending another %i messages...", kNBatchedMessages);
1.249 +- for( int i=0; i<kNBatchedMessages; i++ ) {
1.250 +- size_t size = random() % 32768;
1.251 +- NSMutableData *body = [NSMutableData dataWithLength: size];
1.252 +- UInt8 *bytes = body.mutableBytes;
1.253 +- for( size_t i=0; i<size; i++ )
1.254 +- bytes[i] = i % 256;
1.255 +-
1.256 +- BLIPRequest *q = [_conn requestWithBody: body
1.257 +- properties: $dict({@"Content-Type", @"application/octet-stream"},
1.258 +- {@"User-Agent", @"BLIPConnectionTester"},
1.259 +- {@"Date", [[NSDate date] description]},
1.260 +- {@"Size",$sprintf(@"%u",size)})];
1.261 +- Assert(q);
1.262 +- if( kUseCompression && (random()%2==1) )
1.263 +- q.compressed = YES;
1.264 +- if( random()%16 > 12 )
1.265 +- q.urgent = YES;
1.266 +- BLIPResponse *response = [q send];
1.267 +- Assert(response);
1.268 +- Assert(q.number>0);
1.269 +- Assert(response.number==q.number);
1.270 +- [_pending setObject: $object(size) forKey: $object(q.number)];
1.271 +- response.onComplete = $target(self,responseArrived:);
1.272 ++ if( _conn.status==kTCP_Open || _conn.status==kTCP_Opening ) {
1.273 ++ if(_pending.count<100) {
1.274 ++ Log(@"** Sending another %i messages...", kNBatchedMessages);
1.275 ++ for( int i=0; i<kNBatchedMessages; i++ ) {
1.276 ++ size_t size = random() % 32768;
1.277 ++ NSMutableData *body = [NSMutableData dataWithLength: size];
1.278 ++ UInt8 *bytes = body.mutableBytes;
1.279 ++ for( size_t i=0; i<size; i++ )
1.280 ++ bytes[i] = i % 256;
1.281 ++
1.282 ++ BLIPRequest *q = [_conn requestWithBody: body
1.283 ++ properties: $dict({@"Content-Type", @"application/octet-stream"},
1.284 ++ {@"User-Agent", @"BLIPConnectionTester"},
1.285 ++ {@"Date", [[NSDate date] description]},
1.286 ++ {@"Size",$sprintf(@"%u",size)})];
1.287 ++ Assert(q);
1.288 ++ if( kUseCompression && (random()%2==1) )
1.289 ++ q.compressed = YES;
1.290 ++ if( random()%16 > 12 )
1.291 ++ q.urgent = YES;
1.292 ++ BLIPResponse *response = [q send];
1.293 ++ Assert(response);
1.294 ++ Assert(q.number>0);
1.295 ++ Assert(response.number==q.number);
1.296 ++ [_pending setObject: $object(size) forKey: $object(q.number)];
1.297 ++ response.onComplete = $target(self,responseArrived:);
1.298 ++ }
1.299 ++ } else {
1.300 ++ Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count);
1.301 + }
1.302 +- } else {
1.303 +- Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count);
1.304 ++ [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval];
1.305 + }
1.306 +- [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval];
1.307 + }
1.308 +
1.309 + - (void) responseArrived: (BLIPResponse*)response
1.310 +@@ -191,6 +194,13 @@
1.311 + Log(@"Now %u replies pending", _pending.count);
1.312 + }
1.313 +
1.314 ++- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection
1.315 ++{
1.316 ++ BOOL response = NO;
1.317 ++ Log(@"***** %@ received a close request; returning %i",connection,response);
1.318 ++ return response;
1.319 ++}
1.320 ++
1.321 +
1.322 + @end
1.323 +
1.324 +@@ -217,6 +227,7 @@
1.325 + @interface BLIPTestListener : NSObject <TCPListenerDelegate, BLIPConnectionDelegate>
1.326 + {
1.327 + BLIPListener *_listener;
1.328 ++ int _nReceived;
1.329 + }
1.330 +
1.331 + @end
1.332 +@@ -277,6 +288,7 @@
1.333 + - (void) connectionDidOpen: (TCPConnection*)connection
1.334 + {
1.335 + Log(@"** %@ didOpen [SSL=%@]",connection,connection.actualSecurityLevel);
1.336 ++ _nReceived = 0;
1.337 + }
1.338 + - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert
1.339 + {
1.340 +@@ -312,6 +324,22 @@
1.341 + AssertEq([[request valueOfProperty: @"Size"] intValue], size);
1.342 +
1.343 + [request respondWithData: body contentType: request.contentType];
1.344 ++
1.345 ++ if( ++ _nReceived == kListenerCloseAfter ) {
1.346 ++ Log(@"********** Closing BLIPTestListener after %i requests",_nReceived);
1.347 ++ [connection close];
1.348 ++ }
1.349 ++}
1.350 ++
1.351 ++- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection;
1.352 ++{
1.353 ++ Log(@"***** %@ received a close request",connection);
1.354 ++ return YES;
1.355 ++}
1.356 ++
1.357 ++- (void) connection: (BLIPConnection*)connection closeRequestFailedWithError: (NSError*)error
1.358 ++{
1.359 ++ Log(@"***** %@'s close request failed: %@",connection,error);
1.360 + }
1.361 +
1.362 +
1.363 +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPWriter.m
1.364 +--- a/BLIP/BLIPWriter.m Thu Jun 19 10:22:19 2008 -0700
1.365 ++++ b/BLIP/BLIPWriter.m Mon Jun 23 14:02:31 2008 -0700
1.366 +@@ -79,10 +79,6 @@
1.367 +
1.368 + - (BOOL) sendMessage: (BLIPMessage*)message
1.369 + {
1.370 +- if( _shouldClose ) {
1.371 +- Warn(@"%@: Attempt to send a message after the connection has started closing",self);
1.372 +- return NO;
1.373 +- }
1.374 + Assert(!message.sent,@"message has already been sent");
1.375 + [self _queueMessage: message isNew: YES];
1.376 + return YES;
1.377 +@@ -91,12 +87,14 @@
1.378 +
1.379 + - (BOOL) sendRequest: (BLIPRequest*)q response: (BLIPResponse*)response
1.380 + {
1.381 +- if( !_shouldClose ) {
1.382 +- [q _assignedNumber: ++_numRequestsSent];
1.383 +- if( response ) {
1.384 +- [response _assignedNumber: _numRequestsSent];
1.385 +- [(BLIPReader*)self.reader _addPendingResponse: response];
1.386 +- }
1.387 ++ if( _shouldClose ) {
1.388 ++ Warn(@"%@: Attempt to send a request after the connection has started closing: %@",self,q);
1.389 ++ return NO;
1.390 ++ }
1.391 ++ [q _assignedNumber: ++_numRequestsSent];
1.392 ++ if( response ) {
1.393 ++ [response _assignedNumber: _numRequestsSent];
1.394 ++ [(BLIPReader*)self.reader _addPendingResponse: response];
1.395 + }
1.396 + return [self sendMessage: q];
1.397 + }
1.398 +diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIP_Internal.h
1.399 +--- a/BLIP/BLIP_Internal.h Thu Jun 19 10:22:19 2008 -0700
1.400 ++++ b/BLIP/BLIP_Internal.h Mon Jun 23 14:02:31 2008 -0700
1.401 +@@ -29,6 +29,7 @@
1.402 + kBLIP_Urgent = 0x0020, // please send sooner/faster
1.403 + kBLIP_NoReply = 0x0040, // no RPY needed
1.404 + kBLIP_MoreComing= 0x0080, // More frames coming (Applies only to individual frame)
1.405 ++ kBLIP_Meta = 0x0100, // Special message type, handled internally (hello, bye, ...)
1.406 + };
1.407 + typedef UInt16 BLIPMessageFlags;
1.408 +
1.409 +@@ -41,7 +42,10 @@
1.410 + UInt16 size; // total size of frame, _including_ this header
1.411 + } BLIPFrameHeader;
1.412 +
1.413 +-#define kBLIPFrameHeaderMagicNumber 0x9B34F205
1.414 ++#define kBLIPFrameHeaderMagicNumber 0x9B34F206
1.415 ++
1.416 ++#define kBLIPProfile_Hi @"Hi" // Used for Profile header in meta greeting message
1.417 ++#define kBLIPProfile_Bye @"Bye" // Used for Profile header in meta close-request message
1.418 +
1.419 +
1.420 + @interface BLIPConnection ()
1.421 +@@ -52,6 +56,7 @@
1.422 +
1.423 + @interface BLIPMessage ()
1.424 + @property BOOL sent, propertiesAvailable, complete;
1.425 ++- (BLIPMessageFlags) _flags;
1.426 + - (void) _setFlag: (BLIPMessageFlags)flag value: (BOOL)value;
1.427 + - (void) _encode;
1.428 + @end