Added a BLIP port of Apple's "CocoaEcho" sample code.
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"
17 #import "ExceptionUtils.h"
20 @implementation BLIPRequest
23 - (id) _initWithConnection: (BLIPConnection*)connection
25 properties: (NSDictionary*)properties
27 self = [self _initWithConnection: connection
37 [self.mutableProperties setAllProperties: properties];
42 + (BLIPRequest*) requestWithBody: (NSData*)body
44 return [[[self alloc] _initWithConnection: nil body: body properties: nil] autorelease];
47 + (BLIPRequest*) requestWithBody: (NSData*)body
48 properties: (NSDictionary*)properties
50 return [[[self alloc] _initWithConnection: nil body: body properties: properties] autorelease];
61 - (BOOL) noReply {return (_flags & kBLIP_NoReply) != 0;}
62 - (void) setNoReply: (BOOL)noReply {[self _setFlag: kBLIP_NoReply value: noReply];}
63 - (BLIPConnection*) connection {return _connection;}
65 - (void) setConnection: (BLIPConnection*)conn
67 Assert(_isMine && !_sent,@"Connection can only be set before sending");
68 setObj(&_connection,conn);
72 - (BLIPResponse*) send
74 Assert(_connection,@"%@ has no connection to send over",self);
75 Assert(!_sent,@"%@ was already sent",self);
77 BLIPResponse *response = self.response;
78 if( [(BLIPWriter*)_connection.writer sendRequest: self response: response] )
86 - (BLIPResponse*) response
88 if( ! _response && ! self.noReply )
89 _response = [[BLIPResponse alloc] _initWithRequest: self];
93 - (void) deferResponse
95 // This will allocate _response, causing -repliedTo to become YES, so BLIPConnection won't
96 // send an automatic empty response after the current request handler returns.
97 LogTo(BLIP,@"Deferring response to %@",self);
103 return _response != nil;
106 - (void) respondWithData: (NSData*)data contentType: (NSString*)contentType
108 BLIPResponse *response = self.response;
109 response.body = data;
110 response.contentType = contentType;
114 - (void) respondWithString: (NSString*)string
116 [self respondWithData: [string dataUsingEncoding: NSUTF8StringEncoding]
117 contentType: @"text/plain; charset=UTF-8"];
120 - (void) respondWithError: (NSError*)error
122 self.response.error = error;
123 [self.response send];
126 - (void) respondWithErrorCode: (int)errorCode message: (NSString*)errorMessage
128 [self respondWithError: BLIPMakeError(errorCode, @"%@",errorMessage)];
131 - (void) respondWithException: (NSException*)exception
133 [self respondWithError: BLIPMakeError(kBLIPError_HandlerFailed, @"%@", exception.reason)];
143 @implementation BLIPResponse
145 - (id) _initWithRequest: (BLIPRequest*)request
148 self = [super _initWithConnection: request.connection
149 isMine: !request.isMine
150 flags: kBLIP_RPY | kBLIP_MoreComing
151 number: request.number
157 _flags |= kBLIP_Urgent;
159 _flags |= kBLIP_MoreComing;
168 [_onComplete release];
175 if( ! (_flags & kBLIP_ERR) )
178 NSMutableDictionary *userInfo = [[self.properties allProperties] mutableCopy];
179 NSString *domain = [userInfo objectForKey: @"Error-Domain"];
180 int code = [[userInfo objectForKey: @"Error-Code"] intValue];
181 if( domain==nil || code==0 ) {
182 domain = BLIPErrorDomain;
184 code = kBLIPError_Unspecified;
186 [userInfo removeObjectForKey: @"Error-Domain"];
187 [userInfo removeObjectForKey: @"Error-Code"];
188 return [NSError errorWithDomain: domain code: code userInfo: userInfo];
191 - (void) _setError: (NSError*)error
193 _flags &= ~kBLIP_TypeMask;
195 // Setting this stuff is a PITA because this object might be technically immutable,
196 // in which case the standard setters would barf if I called them.
199 setObj(&_mutableBody,nil);
201 BLIPMutableProperties *errorProps = [self.properties mutableCopy];
202 NSDictionary *userInfo = error.userInfo;
203 for( NSString *key in userInfo ) {
204 id value = $castIf(NSString,[userInfo objectForKey: key]);
206 [errorProps setValue: value ofProperty: key];
208 [errorProps setValue: error.domain ofProperty: @"Error-Domain"];
209 [errorProps setValue: $sprintf(@"%i",error.code) ofProperty: @"Error-Code"];
210 setObj(&_properties,errorProps);
211 [errorProps release];
215 [self.mutableProperties setAllProperties: nil];
219 - (void) setError: (NSError*)error
221 Assert(_isMine && _isMutable);
222 [self _setError: error];
228 Assert(_connection,@"%@ has no connection to send over",self);
229 Assert(!_sent,@"%@ was already sent",self);
231 return (self.sent = [(BLIPWriter*)_connection.writer sendMessage: self]);
235 @synthesize onComplete=_onComplete;
238 - (void) setComplete: (BOOL)complete
240 [super setComplete: complete];
241 if( complete && _onComplete ) {
243 [_onComplete invokeWithSender: self];
244 }catchAndReport(@"BLIPResponse onComplete target");
249 - (void) _connectionClosed
251 [super _connectionClosed];
253 // Change incoming response to an error:
255 [_properties autorelease];
256 _properties = [_properties mutableCopy];
257 [self _setError: BLIPMakeError(kBLIPError_Disconnected,
258 @"Connection closed before response was received")];
268 Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
270 Redistribution and use in source and binary forms, with or without modification, are permitted
271 provided that the following conditions are met:
273 * Redistributions of source code must retain the above copyright notice, this list of conditions
274 and the following disclaimer.
275 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
276 and the following disclaimer in the documentation and/or other materials provided with the
279 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
280 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
281 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
282 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
283 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
284 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
285 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
286 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.