DNS NULL record support in MYBonjourRegistration. Minor fix to IPAddress init. Force 4-char indent in source files.
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*) requestWithBodyString: (NSString*)bodyString {
48 return [self requestWithBody: [bodyString dataUsingEncoding: NSUTF8StringEncoding]];
51 + (BLIPRequest*) requestWithBody: (NSData*)body
52 properties: (NSDictionary*)properties
54 return [[[self alloc] _initWithConnection: nil body: body properties: properties] autorelease];
57 - (id)mutableCopyWithZone:(NSZone *)zone
59 Assert(self.complete);
60 BLIPRequest *copy = [[self class] requestWithBody: self.body
61 properties: self.properties.allProperties];
62 copy.compressed = self.compressed;
63 copy.urgent = self.urgent;
64 copy.noReply = self.noReply;
76 - (BOOL) noReply {return (_flags & kBLIP_NoReply) != 0;}
77 - (void) setNoReply: (BOOL)noReply {[self _setFlag: kBLIP_NoReply value: noReply];}
78 - (BLIPConnection*) connection {return _connection;}
80 - (void) setConnection: (BLIPConnection*)conn
82 Assert(_isMine && !_sent,@"Connection can only be set before sending");
83 setObj(&_connection,conn);
87 - (BLIPResponse*) send
89 Assert(_connection,@"%@ has no connection to send over",self);
90 Assert(!_sent,@"%@ was already sent",self);
92 BLIPResponse *response = self.response;
93 if( [(BLIPWriter*)_connection.writer sendRequest: self response: response] )
101 - (BLIPResponse*) response
103 if( ! _response && ! self.noReply )
104 _response = [[BLIPResponse alloc] _initWithRequest: self];
108 - (void) deferResponse
110 // This will allocate _response, causing -repliedTo to become YES, so BLIPConnection won't
111 // send an automatic empty response after the current request handler returns.
112 LogTo(BLIP,@"Deferring response to %@",self);
118 return _response != nil;
121 - (void) respondWithData: (NSData*)data contentType: (NSString*)contentType
123 BLIPResponse *response = self.response;
124 response.body = data;
125 response.contentType = contentType;
129 - (void) respondWithString: (NSString*)string
131 [self respondWithData: [string dataUsingEncoding: NSUTF8StringEncoding]
132 contentType: @"text/plain; charset=UTF-8"];
135 - (void) respondWithError: (NSError*)error
137 self.response.error = error;
138 [self.response send];
141 - (void) respondWithErrorCode: (int)errorCode message: (NSString*)errorMessage
143 [self respondWithError: BLIPMakeError(errorCode, @"%@",errorMessage)];
146 - (void) respondWithException: (NSException*)exception
148 [self respondWithError: BLIPMakeError(kBLIPError_HandlerFailed, @"%@", exception.reason)];
158 @implementation BLIPResponse
160 - (id) _initWithRequest: (BLIPRequest*)request
163 self = [super _initWithConnection: request.connection
164 isMine: !request.isMine
165 flags: kBLIP_RPY | kBLIP_MoreComing
166 number: request.number
172 _flags |= kBLIP_Urgent;
174 _flags |= kBLIP_MoreComing;
183 [_onComplete release];
190 if( ! (_flags & kBLIP_ERR) )
193 NSMutableDictionary *userInfo = [[[self.properties allProperties] mutableCopy] autorelease];
194 NSString *domain = [userInfo objectForKey: @"Error-Domain"];
195 int code = [[userInfo objectForKey: @"Error-Code"] intValue];
196 if( domain==nil || code==0 ) {
197 domain = BLIPErrorDomain;
199 code = kBLIPError_Unspecified;
201 [userInfo removeObjectForKey: @"Error-Domain"];
202 [userInfo removeObjectForKey: @"Error-Code"];
203 return [NSError errorWithDomain: domain code: code userInfo: userInfo];
206 - (void) _setError: (NSError*)error
208 _flags &= ~kBLIP_TypeMask;
210 // Setting this stuff is a PITA because this object might be technically immutable,
211 // in which case the standard setters would barf if I called them.
214 setObj(&_mutableBody,nil);
216 BLIPMutableProperties *errorProps = [self.properties mutableCopy];
218 errorProps = [[BLIPMutableProperties alloc] init];
219 NSDictionary *userInfo = error.userInfo;
220 for( NSString *key in userInfo ) {
221 id value = $castIf(NSString,[userInfo objectForKey: key]);
223 [errorProps setValue: value ofProperty: key];
225 [errorProps setValue: error.domain ofProperty: @"Error-Domain"];
226 [errorProps setValue: $sprintf(@"%i",error.code) ofProperty: @"Error-Code"];
227 setObj(&_properties,errorProps);
228 [errorProps release];
232 [self.mutableProperties setAllProperties: nil];
236 - (void) setError: (NSError*)error
238 Assert(_isMine && _isMutable);
239 [self _setError: error];
245 Assert(_connection,@"%@ has no connection to send over",self);
246 Assert(!_sent,@"%@ was already sent",self);
247 BLIPWriter *writer = (BLIPWriter*)_connection.writer;
248 Assert(writer,@"%@'s connection has no writer (already closed?)",self);
250 BOOL sent = self.sent = [writer sendMessage: self];
256 @synthesize onComplete=_onComplete;
259 - (void) setComplete: (BOOL)complete
261 [super setComplete: complete];
262 if( complete && _onComplete ) {
264 [_onComplete invokeWithSender: self];
265 }catchAndReport(@"BLIPRequest onComplete target");
270 - (void) _connectionClosed
272 [super _connectionClosed];
273 if( !_isMine && !_complete ) {
274 // Change incoming response to an error:
276 [_properties autorelease];
277 _properties = [_properties mutableCopy];
278 [self _setError: BLIPMakeError(kBLIPError_Disconnected,
279 @"Connection closed before response was received")];
281 self.complete = YES; // Calls onComplete target
290 Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
292 Redistribution and use in source and binary forms, with or without modification, are permitted
293 provided that the following conditions are met:
295 * Redistributions of source code must retain the above copyright notice, this list of conditions
296 and the following disclaimer.
297 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
298 and the following disclaimer in the documentation and/or other materials provided with the
301 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
302 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
303 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
304 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
305 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
306 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
307 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
308 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.