Moved _handleCloseRequest to a new method. Added warning messages.
1 diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPConnection.h
2 --- a/BLIP/BLIPConnection.h Thu Jun 19 10:22:19 2008 -0700
3 +++ b/BLIP/BLIPConnection.h Mon Jun 23 14:02:31 2008 -0700
5 @interface BLIPConnection : TCPConnection
7 BLIPDispatcher *_dispatcher;
11 /** The delegate object that will be called when the connection opens, closes or receives messages. */
13 /** Called when a BLIPResponse (to one of your requests) is received from the peer.
14 This is called <i>after</i> the response object's onComplete target, if any, is invoked.*/
15 - (void) connection: (BLIPConnection*)connection receivedResponse: (BLIPResponse*)response;
17 +/** Called when the peer wants to close the connection. Return YES to allow, NO to prevent. */
18 +- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection;
20 +/** Called if the peer refuses a close request.
21 + The typical error is kBLIPError_Forbidden. */
22 +- (void) connection: (BLIPConnection*)connection closeRequestFailedWithError: (NSError*)error;
26 diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPConnection.m
27 --- a/BLIP/BLIPConnection.m Thu Jun 19 10:22:19 2008 -0700
28 +++ b/BLIP/BLIPConnection.m Mon Jun 23 14:02:31 2008 -0700
31 #import "BLIPConnection.h"
32 #import "BLIP_Internal.h"
33 +#import "TCP_Internal.h"
34 #import "BLIPReader.h"
35 #import "BLIPWriter.h"
36 #import "BLIPDispatcher.h"
40 #import "ExceptionUtils.h"
44 NSString* const BLIPErrorDomain = @"BLIP";
49 +@interface BLIPConnection ()
50 +- (void) _handleCloseRequest: (BLIPRequest*)request;
54 @implementation BLIPConnection
59 [_dispatcher release];
61 - (id<BLIPConnectionDelegate>) delegate {return (id)_delegate;}
62 - (void) setDelegate: (id<BLIPConnectionDelegate>)delegate {_delegate = delegate;}
66 +#pragma mark RECEIVING:
69 - (BLIPDispatcher*) dispatcher
76 +- (void) _dispatchMetaRequest: (BLIPRequest*)request
78 + NSString* profile = request.profile;
79 + if( [profile isEqualToString: kBLIPProfile_Bye] )
80 + [self _handleCloseRequest: request];
82 + [request respondWithErrorCode: kBLIPError_NotFound message: @"Unknown meta profile"];
86 - (void) _dispatchRequest: (BLIPRequest*)request
88 LogTo(BLIP,@"Received all of %@",request.descriptionWithProperties);
90 - if( ! [self.dispatcher dispatchMessage: request] )
91 + if( request._flags & kBLIP_Meta )
92 + [self _dispatchMetaRequest: request];
93 + else if( ! [self.dispatcher dispatchMessage: request] )
94 [self tellDelegate: @selector(connection:receivedRequest:) withObject: request];
95 if( ! request.noReply && ! request.repliedTo ) {
96 LogTo(BLIP,@"Returning default empty response to %@",request);
102 +#pragma mark SENDING:
105 - (BLIPRequest*) request
107 return [[[BLIPRequest alloc] _initWithConnection: self body: nil properties: nil] autorelease];
108 @@ -103,11 +130,61 @@
113 +#pragma mark CLOSING:
116 +- (void) _beginClose
118 + // Override of TCPConnection method. Instead of closing the socket, send a 'bye' request:
119 + if( ! _blipClosing ) {
120 + LogTo(BLIPVerbose,@"Sending close request...");
121 + BLIPRequest *r = [self request];
122 + [r _setFlag: kBLIP_Meta value: YES];
123 + r.profile = kBLIPProfile_Bye;
124 + BLIPResponse *response = [r send];
125 + response.onComplete = $target(self,_receivedCloseResponse:);
127 + // Put the writer in close mode, to prevent client from sending any more requests:
128 + [self.writer close];
131 +- (void) _receivedCloseResponse: (BLIPResponse*)response
133 + NSError *error = response.error;
134 + LogTo(BLIPVerbose,@"Received close response: error=%@",error);
137 + [self tellDelegate: @selector(connection:closeRequestFailedWithError:) withObject: error];
139 + // Now finally close the socket:
140 + [super _beginClose];
145 +- (void) _handleCloseRequest: (BLIPRequest*)request
147 + LogTo(BLIPVerbose,@"Received a close request");
148 + if( [_delegate respondsToSelector: @selector(connectionReceivedCloseRequest:)] )
149 + if( ! [_delegate connectionReceivedCloseRequest: self] ) {
150 + LogTo(BLIPVerbose,@"Responding with denial of close request");
151 + [request respondWithErrorCode: kBLIPError_Forbidden message: @"Close request denied"];
155 + LogTo(BLIPVerbose,@"Close request accepted");
156 + _blipClosing = YES; // this prevents _beginClose from sending a close request back
167 @implementation BLIPListener
169 - (id) initWithPort: (UInt16)port
170 diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPMessage.m
171 --- a/BLIP/BLIPMessage.m Thu Jun 19 10:22:19 2008 -0700
172 +++ b/BLIP/BLIPMessage.m Mon Jun 23 14:02:31 2008 -0700
174 [desc appendString: @", urgent"];
175 if( _flags & kBLIP_NoReply )
176 [desc appendString: @", noreply"];
177 + if( _flags & kBLIP_Meta )
178 + [desc appendString: @", META"];
179 [desc appendString: @"]"];
186 +- (BLIPMessageFlags) _flags {return _flags;}
188 - (BOOL) compressed {return (_flags & kBLIP_Compressed) != 0;}
189 - (BOOL) urgent {return (_flags & kBLIP_Urgent) != 0;}
190 - (void) setCompressed: (BOOL)compressed {[self _setFlag: kBLIP_Compressed value: compressed];}
191 diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPReader.m
192 --- a/BLIP/BLIPReader.m Thu Jun 19 10:22:19 2008 -0700
193 +++ b/BLIP/BLIPReader.m Mon Jun 23 14:02:31 2008 -0700
198 - return _curBytesRead > 0;
199 + return _curBytesRead > 0 || _pendingRequests.count > 0 || _pendingResponses.count > 0;
203 diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPRequest.m
204 --- a/BLIP/BLIPRequest.m Thu Jun 19 10:22:19 2008 -0700
205 +++ b/BLIP/BLIPRequest.m Mon Jun 23 14:02:31 2008 -0700
207 setObj(&_mutableBody,nil);
209 BLIPMutableProperties *errorProps = [self.properties mutableCopy];
211 + errorProps = [[BLIPMutableProperties alloc] init];
212 NSDictionary *userInfo = error.userInfo;
213 for( NSString *key in userInfo ) {
214 id value = $castIf(NSString,[userInfo objectForKey: key]);
217 Assert(_connection,@"%@ has no connection to send over",self);
218 Assert(!_sent,@"%@ was already sent",self);
219 + BLIPWriter *writer = (BLIPWriter*)_connection.writer;
220 + Assert(writer,@"%@'s connection has no writer (already closed?)",self);
222 - return (self.sent = [(BLIPWriter*)_connection.writer sendMessage: self]);
223 + BOOL sent = self.sent = [writer sendMessage: self];
229 diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPTest.m
230 --- a/BLIP/BLIPTest.m Thu Jun 19 10:22:19 2008 -0700
231 +++ b/BLIP/BLIPTest.m Mon Jun 23 14:02:31 2008 -0700
233 #define kClientUsesSSLCert NO
234 #define kListenerRequiresSSL NO
235 #define kListenerRequiresClientCert NO
236 +#define kListenerCloseAfter 50
239 static SecIdentityRef GetClientIdentity(void) {
240 @@ -100,36 +101,38 @@
242 - (void) sendAMessage
244 - if(_pending.count<100) {
245 - Log(@"** Sending another %i messages...", kNBatchedMessages);
246 - for( int i=0; i<kNBatchedMessages; i++ ) {
247 - size_t size = random() % 32768;
248 - NSMutableData *body = [NSMutableData dataWithLength: size];
249 - UInt8 *bytes = body.mutableBytes;
250 - for( size_t i=0; i<size; i++ )
251 - bytes[i] = i % 256;
253 - BLIPRequest *q = [_conn requestWithBody: body
254 - properties: $dict({@"Content-Type", @"application/octet-stream"},
255 - {@"User-Agent", @"BLIPConnectionTester"},
256 - {@"Date", [[NSDate date] description]},
257 - {@"Size",$sprintf(@"%u",size)})];
259 - if( kUseCompression && (random()%2==1) )
260 - q.compressed = YES;
261 - if( random()%16 > 12 )
263 - BLIPResponse *response = [q send];
265 - Assert(q.number>0);
266 - Assert(response.number==q.number);
267 - [_pending setObject: $object(size) forKey: $object(q.number)];
268 - response.onComplete = $target(self,responseArrived:);
269 + if( _conn.status==kTCP_Open || _conn.status==kTCP_Opening ) {
270 + if(_pending.count<100) {
271 + Log(@"** Sending another %i messages...", kNBatchedMessages);
272 + for( int i=0; i<kNBatchedMessages; i++ ) {
273 + size_t size = random() % 32768;
274 + NSMutableData *body = [NSMutableData dataWithLength: size];
275 + UInt8 *bytes = body.mutableBytes;
276 + for( size_t i=0; i<size; i++ )
277 + bytes[i] = i % 256;
279 + BLIPRequest *q = [_conn requestWithBody: body
280 + properties: $dict({@"Content-Type", @"application/octet-stream"},
281 + {@"User-Agent", @"BLIPConnectionTester"},
282 + {@"Date", [[NSDate date] description]},
283 + {@"Size",$sprintf(@"%u",size)})];
285 + if( kUseCompression && (random()%2==1) )
286 + q.compressed = YES;
287 + if( random()%16 > 12 )
289 + BLIPResponse *response = [q send];
291 + Assert(q.number>0);
292 + Assert(response.number==q.number);
293 + [_pending setObject: $object(size) forKey: $object(q.number)];
294 + response.onComplete = $target(self,responseArrived:);
297 + Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count);
300 - Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count);
301 + [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval];
303 - [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval];
306 - (void) responseArrived: (BLIPResponse*)response
308 Log(@"Now %u replies pending", _pending.count);
311 +- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection
313 + BOOL response = NO;
314 + Log(@"***** %@ received a close request; returning %i",connection,response);
322 @interface BLIPTestListener : NSObject <TCPListenerDelegate, BLIPConnectionDelegate>
324 BLIPListener *_listener;
330 - (void) connectionDidOpen: (TCPConnection*)connection
332 Log(@"** %@ didOpen [SSL=%@]",connection,connection.actualSecurityLevel);
335 - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert
338 AssertEq([[request valueOfProperty: @"Size"] intValue], size);
340 [request respondWithData: body contentType: request.contentType];
342 + if( ++ _nReceived == kListenerCloseAfter ) {
343 + Log(@"********** Closing BLIPTestListener after %i requests",_nReceived);
344 + [connection close];
348 +- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection;
350 + Log(@"***** %@ received a close request",connection);
354 +- (void) connection: (BLIPConnection*)connection closeRequestFailedWithError: (NSError*)error
356 + Log(@"***** %@'s close request failed: %@",connection,error);
360 diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPWriter.m
361 --- a/BLIP/BLIPWriter.m Thu Jun 19 10:22:19 2008 -0700
362 +++ b/BLIP/BLIPWriter.m Mon Jun 23 14:02:31 2008 -0700
365 - (BOOL) sendMessage: (BLIPMessage*)message
367 - if( _shouldClose ) {
368 - Warn(@"%@: Attempt to send a message after the connection has started closing",self);
371 Assert(!message.sent,@"message has already been sent");
372 [self _queueMessage: message isNew: YES];
376 - (BOOL) sendRequest: (BLIPRequest*)q response: (BLIPResponse*)response
378 - if( !_shouldClose ) {
379 - [q _assignedNumber: ++_numRequestsSent];
381 - [response _assignedNumber: _numRequestsSent];
382 - [(BLIPReader*)self.reader _addPendingResponse: response];
384 + if( _shouldClose ) {
385 + Warn(@"%@: Attempt to send a request after the connection has started closing: %@",self,q);
388 + [q _assignedNumber: ++_numRequestsSent];
390 + [response _assignedNumber: _numRequestsSent];
391 + [(BLIPReader*)self.reader _addPendingResponse: response];
393 return [self sendMessage: q];
395 diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIP_Internal.h
396 --- a/BLIP/BLIP_Internal.h Thu Jun 19 10:22:19 2008 -0700
397 +++ b/BLIP/BLIP_Internal.h Mon Jun 23 14:02:31 2008 -0700
399 kBLIP_Urgent = 0x0020, // please send sooner/faster
400 kBLIP_NoReply = 0x0040, // no RPY needed
401 kBLIP_MoreComing= 0x0080, // More frames coming (Applies only to individual frame)
402 + kBLIP_Meta = 0x0100, // Special message type, handled internally (hello, bye, ...)
404 typedef UInt16 BLIPMessageFlags;
407 UInt16 size; // total size of frame, _including_ this header
410 -#define kBLIPFrameHeaderMagicNumber 0x9B34F205
411 +#define kBLIPFrameHeaderMagicNumber 0x9B34F206
413 +#define kBLIPProfile_Hi @"Hi" // Used for Profile header in meta greeting message
414 +#define kBLIPProfile_Bye @"Bye" // Used for Profile header in meta close-request message
417 @interface BLIPConnection ()
420 @interface BLIPMessage ()
421 @property BOOL sent, propertiesAvailable, complete;
422 +- (BLIPMessageFlags) _flags;
423 - (void) _setFlag: (BLIPMessageFlags)flag value: (BOOL)value;