5 // Created by Jens Alfke on 5/22/08.
6 // Copyright 2008 Jens Alfke. All rights reserved.
9 #import "BLIPRequest.h"
10 #import "BLIP_Internal.h"
11 #import "BLIPWriter.h"
12 #import "BLIPReader.h"
14 #import "ExceptionUtils.h"
17 @implementation BLIPRequest
20 - (id) _initWithConnection: (BLIPConnection*)connection
22 properties: (NSDictionary*)properties
24 self = [self _initWithConnection: connection
34 [self.mutableProperties setAllProperties: properties];
39 + (BLIPRequest*) requestWithBody: (NSData*)body
41 return [[[self alloc] _initWithConnection: nil body: body properties: nil] autorelease];
44 + (BLIPRequest*) requestWithBody: (NSData*)body
45 properties: (NSDictionary*)properties
47 return [[[self alloc] _initWithConnection: nil body: body properties: properties] autorelease];
58 - (BOOL) noReply {return (_flags & kBLIP_NoReply) != 0;}
59 - (void) setNoReply: (BOOL)noReply {[self _setFlag: kBLIP_NoReply value: noReply];}
60 - (BLIPConnection*) connection {return _connection;}
62 - (void) setConnection: (BLIPConnection*)conn
64 Assert(_isMine && !_sent,@"Connection can only be set before sending");
65 setObj(&_connection,conn);
69 - (BLIPResponse*) send
71 Assert(_connection,@"%@ has no connection to send over",self);
72 Assert(!_sent,@"%@ was already sent",self);
74 BLIPResponse *response = self.response;
75 if( [(BLIPWriter*)_connection.writer sendRequest: self response: response] )
83 - (BLIPResponse*) response
85 if( ! _response && ! self.noReply )
86 _response = [[BLIPResponse alloc] _initWithRequest: self];
90 - (void) deferResponse
92 // This will allocate _response, causing -repliedTo to become YES, so BLIPConnection won't
93 // send an automatic empty response after the current request handler returns.
94 LogTo(BLIP,@"Deferring response to %@",self);
100 return _response != nil;
103 - (void) respondWithData: (NSData*)data {self.response.body = data; [self.response send];}
104 - (void) respondWithString: (NSString*)string {[self respondWithData: [string dataUsingEncoding: NSUTF8StringEncoding]];}
105 - (void) respondWithError: (NSError*)error {self.response.error = error; [self.response send];}
107 - (void) respondWithErrorCode: (int)errorCode message: (NSString*)errorMessage
109 [self respondWithError: BLIPMakeError(errorCode, @"%@",errorMessage)];
112 - (void) respondWithException: (NSException*)exception
114 [self respondWithError: BLIPMakeError(kBLIPError_HandlerFailed, @"%@", exception.reason)];
124 @implementation BLIPResponse
126 - (id) _initWithRequest: (BLIPRequest*)request
129 self = [super _initWithConnection: request.connection
130 isMine: !request.isMine
131 flags: kBLIP_RPY | kBLIP_MoreComing
132 number: request.number
138 _flags |= kBLIP_Urgent;
140 _flags |= kBLIP_MoreComing;
149 [_onComplete release];
156 if( ! (_flags & kBLIP_ERR) )
159 NSMutableDictionary *userInfo = [[self.properties allProperties] mutableCopy];
160 NSString *domain = [userInfo objectForKey: @"Error-Domain"];
161 int code = [[userInfo objectForKey: @"Error-Code"] intValue];
162 if( domain==nil || code==0 ) {
163 domain = BLIPErrorDomain;
165 code = kBLIPError_Unspecified;
167 [userInfo removeObjectForKey: @"Error-Domain"];
168 [userInfo removeObjectForKey: @"Error-Code"];
169 return [NSError errorWithDomain: domain code: code userInfo: userInfo];
172 - (void) _setError: (NSError*)error
174 _flags &= ~kBLIP_TypeMask;
176 // Setting this stuff is a PITA because this object might be technically immutable,
177 // in which case the standard setters would barf if I called them.
180 setObj(&_mutableBody,nil);
182 BLIPMutableProperties *errorProps = [self.properties mutableCopy];
183 NSDictionary *userInfo = error.userInfo;
184 for( NSString *key in userInfo ) {
185 id value = $castIf(NSString,[userInfo objectForKey: key]);
187 [errorProps setValue: value ofProperty: key];
189 [errorProps setValue: error.domain ofProperty: @"Error-Domain"];
190 [errorProps setValue: $sprintf(@"%i",error.code) ofProperty: @"Error-Code"];
191 setObj(&_properties,errorProps);
192 [errorProps release];
196 [self.mutableProperties setAllProperties: nil];
200 - (void) setError: (NSError*)error
202 Assert(_isMine && _isMutable);
203 [self _setError: error];
209 Assert(_connection,@"%@ has no connection to send over",self);
210 Assert(!_sent,@"%@ was already sent",self);
212 return (self.sent = [(BLIPWriter*)_connection.writer sendMessage: self]);
216 @synthesize onComplete=_onComplete;
219 - (void) setComplete: (BOOL)complete
221 [super setComplete: complete];
222 if( complete && _onComplete ) {
224 [_onComplete invokeWithSender: self];
225 }catchAndReport(@"BLIPResponse onComplete target");
230 - (void) _connectionClosed
232 [super _connectionClosed];
234 // Change incoming response to an error:
236 [_properties autorelease];
237 _properties = [_properties mutableCopy];
238 [self _setError: BLIPMakeError(kBLIPError_Disconnected,
239 @"Connection closed before response was received")];
249 Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
251 Redistribution and use in source and binary forms, with or without modification, are permitted
252 provided that the following conditions are met:
254 * Redistributions of source code must retain the above copyright notice, this list of conditions
255 and the following disclaimer.
256 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
257 and the following disclaimer in the documentation and/or other materials provided with the
260 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
261 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
262 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
263 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
264 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
265 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
266 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
267 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.