1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/BLIP/BLIPReader.m Fri May 23 17:37:36 2008 -0700
1.3 @@ -0,0 +1,263 @@
1.4 +//
1.5 +// BLIPReader.m
1.6 +// MYNetwork
1.7 +//
1.8 +// Created by Jens Alfke on 5/10/08.
1.9 +// Copyright 2008 Jens Alfke. All rights reserved.
1.10 +//
1.11 +
1.12 +#import "BLIPReader.h"
1.13 +#import "BLIP_Internal.h"
1.14 +#import "BLIPWriter.h"
1.15 +#import "BLIPDispatcher.h"
1.16 +
1.17 +
1.18 +@interface BLIPReader ()
1.19 +- (BOOL) _receivedFrameWithHeader: (const BLIPFrameHeader*)header body: (NSData*)body;
1.20 +@end
1.21 +
1.22 +
1.23 +@implementation BLIPReader
1.24 +
1.25 +
1.26 +#define _blipConn ((BLIPConnection*)_conn)
1.27 +
1.28 +
1.29 +- (id) initWithConnection: (BLIPConnection*)conn stream: (NSStream*)stream
1.30 +{
1.31 + self = [super initWithConnection: conn stream: stream];
1.32 + if (self != nil) {
1.33 + _pendingQueries = [[NSMutableDictionary alloc] init];
1.34 + _pendingReplies = [[NSMutableDictionary alloc] init];
1.35 + }
1.36 + return self;
1.37 +}
1.38 +
1.39 +- (void) dealloc
1.40 +{
1.41 + [_pendingQueries release];
1.42 + [_pendingReplies release];
1.43 + [_curBody release];
1.44 + [super dealloc];
1.45 +}
1.46 +
1.47 +- (void) disconnect
1.48 +{
1.49 + for( BLIPResponse *response in [_pendingReplies allValues] ) {
1.50 + [response _connectionClosed];
1.51 + [_conn tellDelegate: @selector(connection:receivedResponse:) withObject: response];
1.52 + }
1.53 + setObj(&_pendingReplies,nil);
1.54 + [super disconnect];
1.55 +}
1.56 +
1.57 +
1.58 +#pragma mark -
1.59 +#pragma mark READING FRAMES:
1.60 +
1.61 +
1.62 +- (NSString*) _validateHeader
1.63 +{
1.64 + // Convert header to native byte order:
1.65 + _curHeader.magic = EndianU32_BtoN(_curHeader.magic);
1.66 + _curHeader.number= EndianU32_BtoN(_curHeader.number);
1.67 + _curHeader.flags = EndianU16_BtoN(_curHeader.flags);
1.68 + _curHeader.size = EndianU16_BtoN(_curHeader.size);
1.69 +
1.70 + if( _curHeader.magic != kBLIPFrameHeaderMagicNumber )
1.71 + return $sprintf(@"Incorrect magic number (%08X not %08X)",
1.72 + _curHeader.magic,kBLIPFrameHeaderMagicNumber);
1.73 + size_t bodyLength = _curHeader.size;
1.74 + if( bodyLength < sizeof(BLIPFrameHeader) )
1.75 + return @"Length is impossibly short";
1.76 + bodyLength -= sizeof(BLIPFrameHeader);
1.77 + _curBody = [[NSMutableData alloc] initWithLength: bodyLength];
1.78 + return nil;
1.79 +}
1.80 +
1.81 +
1.82 +- (void) _endCurFrame
1.83 +{
1.84 + [self retain];
1.85 + [self _receivedFrameWithHeader: &_curHeader body: _curBody];
1.86 + memset(&_curHeader,0,sizeof(_curHeader));
1.87 + setObj(&_curBody,nil);
1.88 + _curBytesRead = 0;
1.89 + [self release];
1.90 +}
1.91 +
1.92 +
1.93 +- (BOOL) isBusy
1.94 +{
1.95 + return _curBytesRead > 0;
1.96 +}
1.97 +
1.98 +
1.99 +- (void) _canRead
1.100 +{
1.101 + SInt32 headerLeft = sizeof(BLIPFrameHeader) - _curBytesRead;
1.102 + if( headerLeft > 0 ) {
1.103 + // Read (more of) the header:
1.104 + NSInteger bytesRead = [(NSInputStream*)_stream read: (uint8_t*)&_curHeader +_curBytesRead
1.105 + maxLength: headerLeft];
1.106 + if( bytesRead < 0 ) {
1.107 + [self _gotError];
1.108 + } else {
1.109 + _curBytesRead += bytesRead;
1.110 + if( _curBytesRead < sizeof(BLIPFrameHeader) ) {
1.111 + // Incomplete header:
1.112 + LogTo(BLIPVerbose,@"%@ read %u bytes of header (%u left)",
1.113 + self,bytesRead,sizeof(BLIPFrameHeader)-_curBytesRead);
1.114 + } else {
1.115 + // Finished reading the header!
1.116 + headerLeft = 0;
1.117 + NSString *err = [self _validateHeader];
1.118 + if( err ) {
1.119 + Warn(@"%@ read bogus frame header: %@",self,err);
1.120 + return (void)[self _gotError: BLIPMakeError(kBLIPError_BadData, @"%@", err)];
1.121 + }
1.122 + LogTo(BLIPVerbose,@"%@: Read header; next is %u-byte body",self,_curBody.length);
1.123 +
1.124 + if( _curBody.length == 0 ) {
1.125 + // Zero-byte body, so no need to wait for another read
1.126 + [self _endCurFrame];
1.127 + }
1.128 + }
1.129 + }
1.130 +
1.131 + } else {
1.132 + // Read (more of) the current frame's body:
1.133 + SInt32 bodyRemaining = (SInt32)_curBody.length + headerLeft;
1.134 + if( bodyRemaining > 0 ) {
1.135 + uint8_t *dst = _curBody.mutableBytes;
1.136 + dst += _curBody.length - bodyRemaining;
1.137 + NSInteger bytesRead = [(NSInputStream*)_stream read: dst maxLength: bodyRemaining];
1.138 + if( bytesRead < 0 )
1.139 + return (void)[self _gotError];
1.140 + else if( bytesRead > 0 ) {
1.141 + _curBytesRead += bytesRead;
1.142 + bodyRemaining -= bytesRead;
1.143 + LogTo(BLIPVerbose,@"%@: Read %u bytes of frame body (%u left)",self,bytesRead,bodyRemaining);
1.144 + }
1.145 + }
1.146 + if( bodyRemaining==0 ) {
1.147 + // Done reading this frame: give it to the Connection and reset my state
1.148 + [self _endCurFrame];
1.149 + }
1.150 + }
1.151 +}
1.152 +
1.153 +
1.154 +#pragma mark -
1.155 +#pragma mark PROCESSING FRAMES:
1.156 +
1.157 +
1.158 +- (void) _addPendingResponse: (BLIPResponse*)response
1.159 +{
1.160 + [_pendingReplies setObject: response forKey: $object(response.number)];
1.161 +}
1.162 +
1.163 +
1.164 +- (BOOL) _receivedFrameWithHeader: (const BLIPFrameHeader*)header body: (NSData*)body
1.165 +{
1.166 + static const char* kTypeStrs[16] = {"MSG","RPY","ERR","3??","4??","5??","6??","7??"};
1.167 + BLIPMessageType type = header->flags & kBLIP_TypeMask;
1.168 + LogTo(BLIPVerbose,@"%@ rcvd frame of %s #%u, length %u",self,kTypeStrs[type],header->number,body.length);
1.169 +
1.170 + id key = $object(header->number);
1.171 + BOOL complete = ! (header->flags & kBLIP_MoreComing);
1.172 + switch(type) {
1.173 + case kBLIP_MSG: {
1.174 + // Incoming request:
1.175 + BLIPRequest *request = [_pendingQueries objectForKey: key];
1.176 + if( request ) {
1.177 + // Continuation frame of a request:
1.178 + if( complete ) {
1.179 + [[request retain] autorelease];
1.180 + [_pendingQueries removeObjectForKey: key];
1.181 + }
1.182 + } else if( header->number == _numQueriesReceived+1 ) {
1.183 + // Next new request:
1.184 + request = [[[BLIPRequest alloc] _initWithConnection: _blipConn
1.185 + isMine: NO
1.186 + flags: header->flags | kBLIP_MoreComing
1.187 + number: header->number
1.188 + body: nil]
1.189 + autorelease];
1.190 + if( ! complete )
1.191 + [_pendingQueries setObject: request forKey: key];
1.192 + _numQueriesReceived++;
1.193 + } else
1.194 + return [self _gotError: BLIPMakeError(kBLIPError_BadFrame,
1.195 + @"Received bad request frame #%u (next is #%u)",
1.196 + header->number,_numQueriesReceived+1)];
1.197 +
1.198 + if( ! [request _receivedFrameWithHeader: header body: body] )
1.199 + return [self _gotError: BLIPMakeError(kBLIPError_BadFrame,
1.200 + @"Couldn't parse message frame")];
1.201 +
1.202 + if( complete )
1.203 + [_blipConn _dispatchRequest: request];
1.204 + break;
1.205 + }
1.206 +
1.207 + case kBLIP_RPY:
1.208 + case kBLIP_ERR: {
1.209 + BLIPResponse *response = [_pendingReplies objectForKey: key];
1.210 + if( response ) {
1.211 + if( complete ) {
1.212 + [[response retain] autorelease];
1.213 + [_pendingReplies removeObjectForKey: key];
1.214 + }
1.215 +
1.216 + if( ! [response _receivedFrameWithHeader: header body: body] ) {
1.217 + return [self _gotError: BLIPMakeError(kBLIPError_BadFrame,
1.218 + @"Couldn't parse response frame")];
1.219 + } else if( complete )
1.220 + [_blipConn _dispatchResponse: response];
1.221 +
1.222 + } else {
1.223 + if( header->number <= ((BLIPWriter*)self.writer).numQueriesSent )
1.224 + LogTo(BLIP,@"??? %@ got unexpected response frame to my msg #%u",
1.225 + self,header->number); //benign
1.226 + else
1.227 + return [self _gotError: BLIPMakeError(kBLIPError_BadFrame,
1.228 + @"Bogus message number %u in response",
1.229 + header->number)];
1.230 + }
1.231 + break;
1.232 + }
1.233 +
1.234 + default:
1.235 + // To leave room for future expansion, undefined message types are just ignored.
1.236 + Log(@"??? %@ received header with unknown message type %i", self,type);
1.237 + break;
1.238 + }
1.239 + return YES;
1.240 +}
1.241 +
1.242 +
1.243 +@end
1.244 +
1.245 +
1.246 +/*
1.247 + Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
1.248 +
1.249 + Redistribution and use in source and binary forms, with or without modification, are permitted
1.250 + provided that the following conditions are met:
1.251 +
1.252 + * Redistributions of source code must retain the above copyright notice, this list of conditions
1.253 + and the following disclaimer.
1.254 + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
1.255 + and the following disclaimer in the documentation and/or other materials provided with the
1.256 + distribution.
1.257 +
1.258 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
1.259 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
1.260 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
1.261 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1.262 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1.263 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1.264 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
1.265 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.266 + */