BLIP/BLIPConnection.m
author Jens Alfke <jens@mooseyard.com>
Fri May 30 13:54:38 2008 -0700 (2008-05-30)
changeset 9 980beba83fb7
parent 2 9fdd8dba529c
child 18 3be241de1630
permissions -rw-r--r--
Fixed a serious bug - a race condition where a data buffer in the writer's queue could be dealloced (not the NSData, but its bytes themselves) before the writer sent it, resulting in an EFAULT error.
     1 //
     2 //  BLIPConnection.m
     3 //  MYNetwork
     4 //
     5 //  Created by Jens Alfke on 5/10/08.
     6 //  Copyright 2008 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "BLIPConnection.h"
    10 #import "BLIP_Internal.h"
    11 #import "BLIPReader.h"
    12 #import "BLIPWriter.h"
    13 #import "BLIPDispatcher.h"
    14 
    15 #import "Logging.h"
    16 #import "Test.h"
    17 #import "ExceptionUtils.h"
    18 
    19 
    20 NSString* const BLIPErrorDomain = @"BLIP";
    21 
    22 NSError *BLIPMakeError( int errorCode, NSString *message, ... )
    23 {
    24     va_list args;
    25     va_start(args,message);
    26     message = [[NSString alloc] initWithFormat: message arguments: args];
    27     va_end(args);
    28     LogTo(BLIP,@"BLIPError #%i: %@",errorCode,message);
    29     NSDictionary *userInfo = [NSDictionary dictionaryWithObject: message
    30                                                          forKey: NSLocalizedDescriptionKey];
    31     [message release];
    32     return [NSError errorWithDomain: BLIPErrorDomain code: errorCode userInfo: userInfo];
    33 }
    34 
    35 
    36 
    37 
    38 @implementation BLIPConnection
    39 
    40 - (void) dealloc
    41 {
    42     [_dispatcher release];
    43     [super dealloc];
    44 }
    45 
    46 - (Class) readerClass                                       {return [BLIPReader class];}
    47 - (Class) writerClass                                       {return [BLIPWriter class];}
    48 - (id<BLIPConnectionDelegate>) delegate                     {return (id)_delegate;}
    49 - (void) setDelegate: (id<BLIPConnectionDelegate>)delegate  {_delegate = delegate;}
    50 
    51 - (BLIPDispatcher*) dispatcher
    52 {
    53     if( ! _dispatcher ) {
    54         _dispatcher = [[BLIPDispatcher alloc] init];
    55         _dispatcher.parent = ((BLIPListener*)self.server).dispatcher;
    56     }
    57     return _dispatcher;
    58 }
    59 
    60 
    61 - (void) _dispatchRequest: (BLIPRequest*)request
    62 {
    63     LogTo(BLIP,@"Received all of %@",request.descriptionWithProperties);
    64     @try{
    65         if( ! [self.dispatcher dispatchMessage: request] )
    66             [self tellDelegate: @selector(connection:receivedRequest:) withObject: request];
    67         if( ! request.noReply && ! request.repliedTo ) {
    68             LogTo(BLIP,@"Returning default empty response to %@",request);
    69             [request respondWithData: nil contentType: nil];
    70         }
    71     }@catch( NSException *x ) {
    72         MYReportException(x,@"Dispatching BLIP request");
    73         [request respondWithException: x];
    74     }
    75 }
    76 
    77 - (void) _dispatchResponse: (BLIPResponse*)response
    78 {
    79     LogTo(BLIP,@"Received all of %@",response);
    80     [self tellDelegate: @selector(connection:receivedResponse:) withObject: response];
    81 }
    82 
    83 
    84 - (BLIPRequest*) request
    85 {
    86     return [[[BLIPRequest alloc] _initWithConnection: self body: nil properties: nil] autorelease];
    87 }
    88 
    89 - (BLIPRequest*) requestWithBody: (NSData*)body
    90                       properties: (NSDictionary*)properties
    91 {
    92     return [[[BLIPRequest alloc] _initWithConnection: self body: body properties: properties] autorelease];
    93 }
    94 
    95 - (BLIPResponse*) sendRequest: (BLIPRequest*)request
    96 {
    97     BLIPConnection *itsConnection = request.connection;
    98     if( itsConnection==nil )
    99         request.connection = self;
   100     else
   101         Assert(itsConnection==self,@"%@ is already assigned to a different BLIPConnection",request);
   102     return [request send];
   103 }
   104 
   105 
   106 @end
   107 
   108 
   109 
   110 
   111 @implementation BLIPListener
   112 
   113 - (id) initWithPort: (UInt16)port
   114 {
   115     self = [super initWithPort: port];
   116     if (self != nil) {
   117         self.connectionClass = [BLIPConnection class];
   118     }
   119     return self;
   120 }
   121 
   122 - (void) dealloc
   123 {
   124     [_dispatcher release];
   125     [super dealloc];
   126 }
   127 
   128 - (BLIPDispatcher*) dispatcher
   129 {
   130     if( ! _dispatcher )
   131         _dispatcher = [[BLIPDispatcher alloc] init];
   132     return _dispatcher;
   133 }
   134 
   135 @end
   136 
   137 
   138 /*
   139  Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   140  
   141  Redistribution and use in source and binary forms, with or without modification, are permitted
   142  provided that the following conditions are met:
   143  
   144  * Redistributions of source code must retain the above copyright notice, this list of conditions
   145  and the following disclaimer.
   146  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   147  and the following disclaimer in the documentation and/or other materials provided with the
   148  distribution.
   149  
   150  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   151  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   152  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   153  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   154  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   155   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   156  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   157  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   158  */