1_0_to_1_1_diffs.diff
author morrowa@betelgeuse.local
Tue Jun 23 11:44:30 2009 -0700 (2009-06-23)
changeset 51 de59ce19f42e
permissions -rw-r--r--
BROKEN COMMIT. Majority of code to handle closing has been added. Listeners do not close correctly.
morrowa@51
     1
diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPConnection.h
morrowa@51
     2
--- a/BLIP/BLIPConnection.h	Thu Jun 19 10:22:19 2008 -0700
morrowa@51
     3
+++ b/BLIP/BLIPConnection.h	Mon Jun 23 14:02:31 2008 -0700
morrowa@51
     4
@@ -20,6 +20,7 @@
morrowa@51
     5
 @interface BLIPConnection : TCPConnection
morrowa@51
     6
 {
morrowa@51
     7
     BLIPDispatcher *_dispatcher;
morrowa@51
     8
+    BOOL _blipClosing;
morrowa@51
     9
 }
morrowa@51
    10
 
morrowa@51
    11
 /** The delegate object that will be called when the connection opens, closes or receives messages. */
morrowa@51
    12
@@ -73,6 +74,13 @@
morrowa@51
    13
 /** Called when a BLIPResponse (to one of your requests) is received from the peer.
morrowa@51
    14
     This is called <i>after</i> the response object's onComplete target, if any, is invoked.*/
morrowa@51
    15
 - (void) connection: (BLIPConnection*)connection receivedResponse: (BLIPResponse*)response;
morrowa@51
    16
+
morrowa@51
    17
+/** Called when the peer wants to close the connection. Return YES to allow, NO to prevent. */
morrowa@51
    18
+- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection;
morrowa@51
    19
+
morrowa@51
    20
+/** Called if the peer refuses a close request. 
morrowa@51
    21
+    The typical error is kBLIPError_Forbidden. */
morrowa@51
    22
+- (void) connection: (BLIPConnection*)connection closeRequestFailedWithError: (NSError*)error;
morrowa@51
    23
 @end
morrowa@51
    24
 
morrowa@51
    25
 
morrowa@51
    26
diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPConnection.m
morrowa@51
    27
--- a/BLIP/BLIPConnection.m	Thu Jun 19 10:22:19 2008 -0700
morrowa@51
    28
+++ b/BLIP/BLIPConnection.m	Mon Jun 23 14:02:31 2008 -0700
morrowa@51
    29
@@ -8,6 +8,7 @@
morrowa@51
    30
 
morrowa@51
    31
 #import "BLIPConnection.h"
morrowa@51
    32
 #import "BLIP_Internal.h"
morrowa@51
    33
+#import "TCP_Internal.h"
morrowa@51
    34
 #import "BLIPReader.h"
morrowa@51
    35
 #import "BLIPWriter.h"
morrowa@51
    36
 #import "BLIPDispatcher.h"
morrowa@51
    37
@@ -15,6 +16,7 @@
morrowa@51
    38
 #import "Logging.h"
morrowa@51
    39
 #import "Test.h"
morrowa@51
    40
 #import "ExceptionUtils.h"
morrowa@51
    41
+#import "Target.h"
morrowa@51
    42
 
morrowa@51
    43
 
morrowa@51
    44
 NSString* const BLIPErrorDomain = @"BLIP";
morrowa@51
    45
@@ -33,10 +35,14 @@
morrowa@51
    46
 }
morrowa@51
    47
 
morrowa@51
    48
 
morrowa@51
    49
+@interface BLIPConnection ()
morrowa@51
    50
+- (void) _handleCloseRequest: (BLIPRequest*)request;
morrowa@51
    51
+@end
morrowa@51
    52
 
morrowa@51
    53
 
morrowa@51
    54
 @implementation BLIPConnection
morrowa@51
    55
 
morrowa@51
    56
+
morrowa@51
    57
 - (void) dealloc
morrowa@51
    58
 {
morrowa@51
    59
     [_dispatcher release];
morrowa@51
    60
@@ -48,6 +54,11 @@
morrowa@51
    61
 - (id<BLIPConnectionDelegate>) delegate                     {return (id)_delegate;}
morrowa@51
    62
 - (void) setDelegate: (id<BLIPConnectionDelegate>)delegate  {_delegate = delegate;}
morrowa@51
    63
 
morrowa@51
    64
+
morrowa@51
    65
+#pragma mark -
morrowa@51
    66
+#pragma mark RECEIVING:
morrowa@51
    67
+
morrowa@51
    68
+
morrowa@51
    69
 - (BLIPDispatcher*) dispatcher
morrowa@51
    70
 {
morrowa@51
    71
     if( ! _dispatcher ) {
morrowa@51
    72
@@ -58,11 +69,23 @@
morrowa@51
    73
 }
morrowa@51
    74
 
morrowa@51
    75
 
morrowa@51
    76
+- (void) _dispatchMetaRequest: (BLIPRequest*)request
morrowa@51
    77
+{
morrowa@51
    78
+    NSString* profile = request.profile;
morrowa@51
    79
+    if( [profile isEqualToString: kBLIPProfile_Bye] )
morrowa@51
    80
+        [self _handleCloseRequest: request];
morrowa@51
    81
+    else
morrowa@51
    82
+        [request respondWithErrorCode: kBLIPError_NotFound message: @"Unknown meta profile"];
morrowa@51
    83
+}
morrowa@51
    84
+
morrowa@51
    85
+
morrowa@51
    86
 - (void) _dispatchRequest: (BLIPRequest*)request
morrowa@51
    87
 {
morrowa@51
    88
     LogTo(BLIP,@"Received all of %@",request.descriptionWithProperties);
morrowa@51
    89
     @try{
morrowa@51
    90
-        if( ! [self.dispatcher dispatchMessage: request] )
morrowa@51
    91
+        if( request._flags & kBLIP_Meta )
morrowa@51
    92
+            [self _dispatchMetaRequest: request];
morrowa@51
    93
+        else if( ! [self.dispatcher dispatchMessage: request] )
morrowa@51
    94
             [self tellDelegate: @selector(connection:receivedRequest:) withObject: request];
morrowa@51
    95
         if( ! request.noReply && ! request.repliedTo ) {
morrowa@51
    96
             LogTo(BLIP,@"Returning default empty response to %@",request);
morrowa@51
    97
@@ -81,6 +104,10 @@
morrowa@51
    98
 }
morrowa@51
    99
 
morrowa@51
   100
 
morrowa@51
   101
+#pragma mark -
morrowa@51
   102
+#pragma mark SENDING:
morrowa@51
   103
+
morrowa@51
   104
+
morrowa@51
   105
 - (BLIPRequest*) request
morrowa@51
   106
 {
morrowa@51
   107
     return [[[BLIPRequest alloc] _initWithConnection: self body: nil properties: nil] autorelease];
morrowa@51
   108
@@ -103,11 +130,61 @@
morrowa@51
   109
 }
morrowa@51
   110
 
morrowa@51
   111
 
morrowa@51
   112
+#pragma mark -
morrowa@51
   113
+#pragma mark CLOSING:
morrowa@51
   114
+
morrowa@51
   115
+
morrowa@51
   116
+- (void) _beginClose
morrowa@51
   117
+{
morrowa@51
   118
+    // Override of TCPConnection method. Instead of closing the socket, send a 'bye' request:
morrowa@51
   119
+    if( ! _blipClosing ) {
morrowa@51
   120
+        LogTo(BLIPVerbose,@"Sending close request...");
morrowa@51
   121
+        BLIPRequest *r = [self request];
morrowa@51
   122
+        [r _setFlag: kBLIP_Meta value: YES];
morrowa@51
   123
+        r.profile = kBLIPProfile_Bye;
morrowa@51
   124
+        BLIPResponse *response = [r send];
morrowa@51
   125
+        response.onComplete = $target(self,_receivedCloseResponse:);
morrowa@51
   126
+    }
morrowa@51
   127
+    // Put the writer in close mode, to prevent client from sending any more requests:
morrowa@51
   128
+    [self.writer close];
morrowa@51
   129
+}
morrowa@51
   130
+
morrowa@51
   131
+- (void) _receivedCloseResponse: (BLIPResponse*)response
morrowa@51
   132
+{
morrowa@51
   133
+    NSError *error = response.error;
morrowa@51
   134
+    LogTo(BLIPVerbose,@"Received close response: error=%@",error);
morrowa@51
   135
+    if( error ) {
morrowa@51
   136
+        [self _unclose];
morrowa@51
   137
+        [self tellDelegate: @selector(connection:closeRequestFailedWithError:) withObject: error];
morrowa@51
   138
+    } else {
morrowa@51
   139
+        // Now finally close the socket:
morrowa@51
   140
+        [super _beginClose];
morrowa@51
   141
+    }
morrowa@51
   142
+}
morrowa@51
   143
+
morrowa@51
   144
+
morrowa@51
   145
+- (void) _handleCloseRequest: (BLIPRequest*)request
morrowa@51
   146
+{
morrowa@51
   147
+    LogTo(BLIPVerbose,@"Received a close request");
morrowa@51
   148
+    if( [_delegate respondsToSelector: @selector(connectionReceivedCloseRequest:)] )
morrowa@51
   149
+        if( ! [_delegate connectionReceivedCloseRequest: self] ) {
morrowa@51
   150
+            LogTo(BLIPVerbose,@"Responding with denial of close request");
morrowa@51
   151
+            [request respondWithErrorCode: kBLIPError_Forbidden message: @"Close request denied"];
morrowa@51
   152
+            return;
morrowa@51
   153
+        }
morrowa@51
   154
+    
morrowa@51
   155
+    LogTo(BLIPVerbose,@"Close request accepted");
morrowa@51
   156
+    _blipClosing = YES; // this prevents _beginClose from sending a close request back
morrowa@51
   157
+    [self close];
morrowa@51
   158
+}
morrowa@51
   159
+
morrowa@51
   160
+
morrowa@51
   161
 @end
morrowa@51
   162
 
morrowa@51
   163
 
morrowa@51
   164
 
morrowa@51
   165
 
morrowa@51
   166
+#pragma mark -
morrowa@51
   167
 @implementation BLIPListener
morrowa@51
   168
 
morrowa@51
   169
 - (id) initWithPort: (UInt16)port
morrowa@51
   170
diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPMessage.m
morrowa@51
   171
--- a/BLIP/BLIPMessage.m	Thu Jun 19 10:22:19 2008 -0700
morrowa@51
   172
+++ b/BLIP/BLIPMessage.m	Mon Jun 23 14:02:31 2008 -0700
morrowa@51
   173
@@ -74,6 +74,8 @@
morrowa@51
   174
         [desc appendString: @", urgent"];
morrowa@51
   175
     if( _flags & kBLIP_NoReply )
morrowa@51
   176
         [desc appendString: @", noreply"];
morrowa@51
   177
+    if( _flags & kBLIP_Meta )
morrowa@51
   178
+        [desc appendString: @", META"];
morrowa@51
   179
     [desc appendString: @"]"];
morrowa@51
   180
     return desc;
morrowa@51
   181
 }
morrowa@51
   182
@@ -103,6 +105,8 @@
morrowa@51
   183
         _flags &= ~flag;
morrowa@51
   184
 }
morrowa@51
   185
 
morrowa@51
   186
+- (BLIPMessageFlags) _flags                 {return _flags;}
morrowa@51
   187
+
morrowa@51
   188
 - (BOOL) compressed                         {return (_flags & kBLIP_Compressed) != 0;}
morrowa@51
   189
 - (BOOL) urgent                             {return (_flags & kBLIP_Urgent) != 0;}
morrowa@51
   190
 - (void) setCompressed: (BOOL)compressed    {[self _setFlag: kBLIP_Compressed value: compressed];}
morrowa@51
   191
diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPReader.m
morrowa@51
   192
--- a/BLIP/BLIPReader.m	Thu Jun 19 10:22:19 2008 -0700
morrowa@51
   193
+++ b/BLIP/BLIPReader.m	Mon Jun 23 14:02:31 2008 -0700
morrowa@51
   194
@@ -93,7 +93,7 @@
morrowa@51
   195
 
morrowa@51
   196
 - (BOOL) isBusy
morrowa@51
   197
 {
morrowa@51
   198
-    return _curBytesRead > 0;
morrowa@51
   199
+    return _curBytesRead > 0 || _pendingRequests.count > 0 || _pendingResponses.count > 0;
morrowa@51
   200
 }
morrowa@51
   201
 
morrowa@51
   202
 
morrowa@51
   203
diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPRequest.m
morrowa@51
   204
--- a/BLIP/BLIPRequest.m	Thu Jun 19 10:22:19 2008 -0700
morrowa@51
   205
+++ b/BLIP/BLIPRequest.m	Mon Jun 23 14:02:31 2008 -0700
morrowa@51
   206
@@ -199,6 +199,8 @@
morrowa@51
   207
         setObj(&_mutableBody,nil);
morrowa@51
   208
         
morrowa@51
   209
         BLIPMutableProperties *errorProps = [self.properties mutableCopy];
morrowa@51
   210
+        if( ! errorProps )
morrowa@51
   211
+            errorProps = [[BLIPMutableProperties alloc] init];
morrowa@51
   212
         NSDictionary *userInfo = error.userInfo;
morrowa@51
   213
         for( NSString *key in userInfo ) {
morrowa@51
   214
             id value = $castIf(NSString,[userInfo objectForKey: key]);
morrowa@51
   215
@@ -227,8 +229,12 @@
morrowa@51
   216
 {
morrowa@51
   217
     Assert(_connection,@"%@ has no connection to send over",self);
morrowa@51
   218
     Assert(!_sent,@"%@ was already sent",self);
morrowa@51
   219
+    BLIPWriter *writer = (BLIPWriter*)_connection.writer;
morrowa@51
   220
+    Assert(writer,@"%@'s connection has no writer (already closed?)",self);
morrowa@51
   221
     [self _encode];
morrowa@51
   222
-    return (self.sent = [(BLIPWriter*)_connection.writer sendMessage: self]);
morrowa@51
   223
+    BOOL sent = self.sent = [writer sendMessage: self];
morrowa@51
   224
+    Assert(sent);
morrowa@51
   225
+    return sent;
morrowa@51
   226
 }
morrowa@51
   227
 
morrowa@51
   228
 
morrowa@51
   229
diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPTest.m
morrowa@51
   230
--- a/BLIP/BLIPTest.m	Thu Jun 19 10:22:19 2008 -0700
morrowa@51
   231
+++ b/BLIP/BLIPTest.m	Mon Jun 23 14:02:31 2008 -0700
morrowa@51
   232
@@ -35,6 +35,7 @@
morrowa@51
   233
 #define kClientUsesSSLCert          NO
morrowa@51
   234
 #define kListenerRequiresSSL        NO
morrowa@51
   235
 #define kListenerRequiresClientCert NO
morrowa@51
   236
+#define kListenerCloseAfter         50
morrowa@51
   237
 
morrowa@51
   238
 
morrowa@51
   239
 static SecIdentityRef GetClientIdentity(void) {
morrowa@51
   240
@@ -100,36 +101,38 @@
morrowa@51
   241
 
morrowa@51
   242
 - (void) sendAMessage
morrowa@51
   243
 {
morrowa@51
   244
-    if(_pending.count<100) {
morrowa@51
   245
-        Log(@"** Sending another %i messages...", kNBatchedMessages);
morrowa@51
   246
-        for( int i=0; i<kNBatchedMessages; i++ ) {
morrowa@51
   247
-            size_t size = random() % 32768;
morrowa@51
   248
-            NSMutableData *body = [NSMutableData dataWithLength: size];
morrowa@51
   249
-            UInt8 *bytes = body.mutableBytes;
morrowa@51
   250
-            for( size_t i=0; i<size; i++ )
morrowa@51
   251
-                bytes[i] = i % 256;
morrowa@51
   252
-            
morrowa@51
   253
-            BLIPRequest *q = [_conn requestWithBody: body
morrowa@51
   254
-                                         properties: $dict({@"Content-Type", @"application/octet-stream"},
morrowa@51
   255
-                                                           {@"User-Agent", @"BLIPConnectionTester"},
morrowa@51
   256
-                                                           {@"Date", [[NSDate date] description]},
morrowa@51
   257
-                                                           {@"Size",$sprintf(@"%u",size)})];
morrowa@51
   258
-            Assert(q);
morrowa@51
   259
-            if( kUseCompression && (random()%2==1) )
morrowa@51
   260
-                q.compressed = YES;
morrowa@51
   261
-            if( random()%16 > 12 )
morrowa@51
   262
-                q.urgent = YES;
morrowa@51
   263
-            BLIPResponse *response = [q send];
morrowa@51
   264
-            Assert(response);
morrowa@51
   265
-            Assert(q.number>0);
morrowa@51
   266
-            Assert(response.number==q.number);
morrowa@51
   267
-            [_pending setObject: $object(size) forKey: $object(q.number)];
morrowa@51
   268
-            response.onComplete = $target(self,responseArrived:);
morrowa@51
   269
+    if( _conn.status==kTCP_Open || _conn.status==kTCP_Opening ) {
morrowa@51
   270
+        if(_pending.count<100) {
morrowa@51
   271
+            Log(@"** Sending another %i messages...", kNBatchedMessages);
morrowa@51
   272
+            for( int i=0; i<kNBatchedMessages; i++ ) {
morrowa@51
   273
+                size_t size = random() % 32768;
morrowa@51
   274
+                NSMutableData *body = [NSMutableData dataWithLength: size];
morrowa@51
   275
+                UInt8 *bytes = body.mutableBytes;
morrowa@51
   276
+                for( size_t i=0; i<size; i++ )
morrowa@51
   277
+                    bytes[i] = i % 256;
morrowa@51
   278
+                
morrowa@51
   279
+                BLIPRequest *q = [_conn requestWithBody: body
morrowa@51
   280
+                                             properties: $dict({@"Content-Type", @"application/octet-stream"},
morrowa@51
   281
+                                                               {@"User-Agent", @"BLIPConnectionTester"},
morrowa@51
   282
+                                                               {@"Date", [[NSDate date] description]},
morrowa@51
   283
+                                                               {@"Size",$sprintf(@"%u",size)})];
morrowa@51
   284
+                Assert(q);
morrowa@51
   285
+                if( kUseCompression && (random()%2==1) )
morrowa@51
   286
+                    q.compressed = YES;
morrowa@51
   287
+                if( random()%16 > 12 )
morrowa@51
   288
+                    q.urgent = YES;
morrowa@51
   289
+                BLIPResponse *response = [q send];
morrowa@51
   290
+                Assert(response);
morrowa@51
   291
+                Assert(q.number>0);
morrowa@51
   292
+                Assert(response.number==q.number);
morrowa@51
   293
+                [_pending setObject: $object(size) forKey: $object(q.number)];
morrowa@51
   294
+                response.onComplete = $target(self,responseArrived:);
morrowa@51
   295
+            }
morrowa@51
   296
+        } else {
morrowa@51
   297
+            Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count);
morrowa@51
   298
         }
morrowa@51
   299
-    } else {
morrowa@51
   300
-        Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count);
morrowa@51
   301
+        [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval];
morrowa@51
   302
     }
morrowa@51
   303
-    [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval];
morrowa@51
   304
 }
morrowa@51
   305
 
morrowa@51
   306
 - (void) responseArrived: (BLIPResponse*)response
morrowa@51
   307
@@ -191,6 +194,13 @@
morrowa@51
   308
     Log(@"Now %u replies pending", _pending.count);
morrowa@51
   309
 }
morrowa@51
   310
 
morrowa@51
   311
+- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection
morrowa@51
   312
+{
morrowa@51
   313
+    BOOL response = NO;
morrowa@51
   314
+    Log(@"***** %@ received a close request; returning %i",connection,response);
morrowa@51
   315
+    return response;
morrowa@51
   316
+}
morrowa@51
   317
+
morrowa@51
   318
 
morrowa@51
   319
 @end
morrowa@51
   320
 
morrowa@51
   321
@@ -217,6 +227,7 @@
morrowa@51
   322
 @interface BLIPTestListener : NSObject <TCPListenerDelegate, BLIPConnectionDelegate>
morrowa@51
   323
 {
morrowa@51
   324
     BLIPListener *_listener;
morrowa@51
   325
+    int _nReceived;
morrowa@51
   326
 }
morrowa@51
   327
 
morrowa@51
   328
 @end
morrowa@51
   329
@@ -277,6 +288,7 @@
morrowa@51
   330
 - (void) connectionDidOpen: (TCPConnection*)connection
morrowa@51
   331
 {
morrowa@51
   332
     Log(@"** %@ didOpen [SSL=%@]",connection,connection.actualSecurityLevel);
morrowa@51
   333
+    _nReceived = 0;
morrowa@51
   334
 }
morrowa@51
   335
 - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert
morrowa@51
   336
 {
morrowa@51
   337
@@ -312,6 +324,22 @@
morrowa@51
   338
     AssertEq([[request valueOfProperty: @"Size"] intValue], size);
morrowa@51
   339
 
morrowa@51
   340
     [request respondWithData: body contentType: request.contentType];
morrowa@51
   341
+    
morrowa@51
   342
+    if( ++ _nReceived == kListenerCloseAfter ) {
morrowa@51
   343
+        Log(@"********** Closing BLIPTestListener after %i requests",_nReceived);
morrowa@51
   344
+        [connection close];
morrowa@51
   345
+    }
morrowa@51
   346
+}
morrowa@51
   347
+
morrowa@51
   348
+- (BOOL) connectionReceivedCloseRequest: (BLIPConnection*)connection;
morrowa@51
   349
+{
morrowa@51
   350
+    Log(@"***** %@ received a close request",connection);
morrowa@51
   351
+    return YES;
morrowa@51
   352
+}
morrowa@51
   353
+
morrowa@51
   354
+- (void) connection: (BLIPConnection*)connection closeRequestFailedWithError: (NSError*)error
morrowa@51
   355
+{
morrowa@51
   356
+    Log(@"***** %@'s close request failed: %@",connection,error);
morrowa@51
   357
 }
morrowa@51
   358
 
morrowa@51
   359
 
morrowa@51
   360
diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIPWriter.m
morrowa@51
   361
--- a/BLIP/BLIPWriter.m	Thu Jun 19 10:22:19 2008 -0700
morrowa@51
   362
+++ b/BLIP/BLIPWriter.m	Mon Jun 23 14:02:31 2008 -0700
morrowa@51
   363
@@ -79,10 +79,6 @@
morrowa@51
   364
 
morrowa@51
   365
 - (BOOL) sendMessage: (BLIPMessage*)message
morrowa@51
   366
 {
morrowa@51
   367
-    if( _shouldClose ) {
morrowa@51
   368
-        Warn(@"%@: Attempt to send a message after the connection has started closing",self);
morrowa@51
   369
-        return NO;
morrowa@51
   370
-    }
morrowa@51
   371
     Assert(!message.sent,@"message has already been sent");
morrowa@51
   372
     [self _queueMessage: message isNew: YES];
morrowa@51
   373
     return YES;
morrowa@51
   374
@@ -91,12 +87,14 @@
morrowa@51
   375
 
morrowa@51
   376
 - (BOOL) sendRequest: (BLIPRequest*)q response: (BLIPResponse*)response
morrowa@51
   377
 {
morrowa@51
   378
-    if( !_shouldClose ) {
morrowa@51
   379
-        [q _assignedNumber: ++_numRequestsSent];
morrowa@51
   380
-        if( response ) {
morrowa@51
   381
-            [response _assignedNumber: _numRequestsSent];
morrowa@51
   382
-            [(BLIPReader*)self.reader _addPendingResponse: response];
morrowa@51
   383
-        }
morrowa@51
   384
+    if( _shouldClose ) {
morrowa@51
   385
+        Warn(@"%@: Attempt to send a request after the connection has started closing: %@",self,q);
morrowa@51
   386
+        return NO;
morrowa@51
   387
+    }
morrowa@51
   388
+    [q _assignedNumber: ++_numRequestsSent];
morrowa@51
   389
+    if( response ) {
morrowa@51
   390
+        [response _assignedNumber: _numRequestsSent];
morrowa@51
   391
+        [(BLIPReader*)self.reader _addPendingResponse: response];
morrowa@51
   392
     }
morrowa@51
   393
     return [self sendMessage: q];
morrowa@51
   394
 }
morrowa@51
   395
diff -r 70590cc555aa -r 16454d63d4c2 BLIP/BLIP_Internal.h
morrowa@51
   396
--- a/BLIP/BLIP_Internal.h	Thu Jun 19 10:22:19 2008 -0700
morrowa@51
   397
+++ b/BLIP/BLIP_Internal.h	Mon Jun 23 14:02:31 2008 -0700
morrowa@51
   398
@@ -29,6 +29,7 @@
morrowa@51
   399
     kBLIP_Urgent    = 0x0020,       // please send sooner/faster
morrowa@51
   400
     kBLIP_NoReply   = 0x0040,       // no RPY needed
morrowa@51
   401
     kBLIP_MoreComing= 0x0080,       // More frames coming (Applies only to individual frame)
morrowa@51
   402
+    kBLIP_Meta      = 0x0100,       // Special message type, handled internally (hello, bye, ...)
morrowa@51
   403
 };
morrowa@51
   404
 typedef UInt16 BLIPMessageFlags;
morrowa@51
   405
 
morrowa@51
   406
@@ -41,7 +42,10 @@
morrowa@51
   407
     UInt16           size;          // total size of frame, _including_ this header
morrowa@51
   408
 } BLIPFrameHeader;
morrowa@51
   409
 
morrowa@51
   410
-#define kBLIPFrameHeaderMagicNumber 0x9B34F205
morrowa@51
   411
+#define kBLIPFrameHeaderMagicNumber 0x9B34F206
morrowa@51
   412
+
morrowa@51
   413
+#define kBLIPProfile_Hi  @"Hi"      // Used for Profile header in meta greeting message
morrowa@51
   414
+#define kBLIPProfile_Bye @"Bye"     // Used for Profile header in meta close-request message
morrowa@51
   415
 
morrowa@51
   416
 
morrowa@51
   417
 @interface BLIPConnection ()
morrowa@51
   418
@@ -52,6 +56,7 @@
morrowa@51
   419
 
morrowa@51
   420
 @interface BLIPMessage ()
morrowa@51
   421
 @property BOOL sent, propertiesAvailable, complete;
morrowa@51
   422
+- (BLIPMessageFlags) _flags;
morrowa@51
   423
 - (void) _setFlag: (BLIPMessageFlags)flag value: (BOOL)value;
morrowa@51
   424
 - (void) _encode;
morrowa@51
   425
 @end