|
Wired Networking
2.0
Objective-C implementation of the Wired 2.0 protocol
|
00001 /* $Id$ */ 00002 00003 /* 00004 * Copyright (c) 2008-2009 Axel Andersson 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00017 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 00020 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00022 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00023 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 00024 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00025 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00026 * POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00029 // ugly !!! 00030 #define WI_RSA 1 00031 00032 #import <WiredNetworking/NSString-WINetworking.h> 00033 #import <WiredNetworking/WIError.h> 00034 #import <WiredNetworking/WIP7Message.h> 00035 #import <WiredNetworking/WIP7Socket.h> 00036 #import <WiredNetworking/WIP7Spec.h> 00037 #import <WiredNetworking/WISocket.h> 00038 00039 static void _WIP7SocketReadMessage(wi_p7_socket_t *, wi_p7_message_t *, void *); 00040 static void _WIP7SocketWroteMessage(wi_p7_socket_t *, wi_p7_message_t *, void *); 00041 00042 00043 static void _WIP7SocketReadMessage(wi_p7_socket_t *p7Socket, wi_p7_message_t *p7Message, void *contextInfo) { 00044 [[(id) contextInfo delegate] P7Socket:contextInfo readMessage:[WIP7Message messageWithMessage:p7Message spec:[(id) contextInfo spec]]]; 00045 } 00046 00047 00048 00049 static void _WIP7SocketWroteMessage(wi_p7_socket_t *p7Socket, wi_p7_message_t *p7Message, void *contextInfo) { 00050 [[(id) contextInfo delegate] P7Socket:contextInfo wroteMessage:[WIP7Message messageWithMessage:p7Message spec:[(id) contextInfo spec]]]; 00051 } 00052 00053 00054 00055 @interface WIP7Socket(Private) 00056 00057 - (WIError *)_errorWithCode:(NSInteger)code; 00058 00059 @end 00060 00061 00062 @implementation WIP7Socket(Private) 00063 00064 - (WIError *)_errorWithCode:(NSInteger)code { 00065 return [WIError errorWithDomain:WIWiredNetworkingErrorDomain 00066 code:code 00067 userInfo:[NSDictionary dictionaryWithObjectsAndKeys: 00068 [WIError errorWithDomain:WILibWiredErrorDomain], 00069 WILibWiredErrorKey, 00070 [[_socket address] string], 00071 WIArgumentErrorKey, 00072 NULL]]; 00073 } 00074 00075 @end 00076 00077 00078 00079 @implementation WIP7Socket 00080 00081 + (void)initialize { 00082 // wi_p7_socket_debug = true; 00083 } 00084 00085 00086 00087 #pragma mark - 00088 00089 - (id)initWithSocket:(WISocket *)socket spec:(WIP7Spec *)spec { 00090 self = [super init]; 00091 00092 _socket = [socket retain]; 00093 _spec = [spec retain]; 00094 00095 _p7Socket = wi_p7_socket_init_with_socket(wi_p7_socket_alloc(), [_socket socket], [_spec spec]); 00096 00097 return self; 00098 } 00099 00100 00101 00102 - (void)dealloc { 00103 [_socket release]; 00104 [_spec release]; 00105 00106 [_readTimeoutError release]; 00107 00108 wi_release(_p7Socket); 00109 00110 [super dealloc]; 00111 } 00112 00113 00114 00115 #pragma mark - 00116 00117 - (void)setDelegate:(id)aDelegate { 00118 delegate = aDelegate; 00119 00120 if([delegate respondsToSelector:@selector(P7Socket:readMessage:)]) 00121 wi_p7_socket_set_read_message_callback(_p7Socket, _WIP7SocketReadMessage, self); 00122 else 00123 wi_p7_socket_set_read_message_callback(_p7Socket, NULL, NULL); 00124 00125 if([delegate respondsToSelector:@selector(P7Socket:wroteMessage:)]) 00126 wi_p7_socket_set_wrote_message_callback(_p7Socket, _WIP7SocketWroteMessage, self); 00127 else 00128 wi_p7_socket_set_wrote_message_callback(_p7Socket, NULL, NULL); 00129 } 00130 00131 00132 00133 - (id)delegate { 00134 return delegate; 00135 } 00136 00137 00138 00139 #pragma mark - 00140 00141 - (WISocket *)socket { 00142 return _socket; 00143 } 00144 00145 00146 00147 - (wi_p7_socket_t *)P7Socket { 00148 return _p7Socket; 00149 } 00150 00151 00152 00153 - (WIP7Spec *)spec { 00154 return _spec; 00155 } 00156 00157 00158 00159 - (NSUInteger)options { 00160 return wi_p7_socket_options(_p7Socket); 00161 } 00162 00163 00164 00165 - (WIP7Serialization)serialization { 00166 return wi_p7_socket_serialization(_p7Socket); 00167 } 00168 00169 00170 00171 - (NSString *)remoteProtocolName { 00172 return [NSString stringWithWiredString:wi_p7_socket_remote_protocol_name(_p7Socket)]; 00173 } 00174 00175 00176 00177 - (NSString *)remoteProtocolVersion { 00178 return [NSString stringWithWiredString:wi_p7_socket_remote_protocol_version(_p7Socket)]; 00179 } 00180 00181 00182 00183 - (BOOL)usesEncryption { 00184 return WI_P7_ENCRYPTION_ENABLED([self options]); 00185 } 00186 00187 00188 00189 - (NSString *)cipherName { 00190 00191 #ifdef WI_RSA 00192 wi_cipher_t *cipher; 00193 cipher = wi_p7_socket_cipher(_p7Socket); 00194 00195 return cipher ? [NSString stringWithWiredString:wi_cipher_name(cipher)] : NULL; 00196 #else 00197 return NULL; 00198 #endif 00199 } 00200 00201 00202 00203 - (NSUInteger)cipherBits { 00204 #ifdef WI_RSA 00205 wi_cipher_t *cipher; 00206 00207 cipher = wi_p7_socket_cipher(_p7Socket); 00208 00209 return cipher ? wi_cipher_bits(cipher) : 0; 00210 #else 00211 return 0; 00212 #endif 00213 } 00214 00215 00216 00217 - (BOOL)usesCompression { 00218 return WI_P7_COMPRESSION_ENABLED([self options]); 00219 } 00220 00221 00222 00223 - (double)compressionRatio { 00224 return wi_p7_socket_compression_ratio(_p7Socket); 00225 } 00226 00227 00228 00229 #pragma mark - 00230 00231 - (BOOL)verifyMessage:(WIP7Message *)message error:(WIError **)error { 00232 wi_pool_t *pool; 00233 wi_boolean_t result; 00234 00235 pool = wi_pool_init(wi_pool_alloc()); 00236 result = wi_p7_socket_verify_message(_p7Socket, [message message]); 00237 wi_release(pool); 00238 00239 if(!result) { 00240 if(error) 00241 *error = [WIError errorWithDomain:WILibWiredErrorDomain]; 00242 00243 return NO; 00244 } 00245 00246 return YES; 00247 } 00248 00249 00250 00251 #pragma mark - 00252 00253 - (BOOL)connectWithOptions:(NSUInteger)options serialization:(WIP7Serialization)serialization username:(NSString *)username password:(NSString *)password timeout:(NSTimeInterval)timeout error:(WIError **)error { 00254 wi_pool_t *pool; 00255 wi_boolean_t result; 00256 00257 pool = wi_pool_init(wi_pool_alloc()); 00258 result = wi_p7_socket_connect(_p7Socket, timeout, options, serialization, [username wiredString], [password wiredString]); 00259 wi_release(pool); 00260 00261 if(!result) { 00262 if(error) 00263 *error = [self _errorWithCode:WISocketConnectFailed]; 00264 00265 return NO; 00266 } 00267 00268 return YES; 00269 } 00270 00271 00272 00273 - (BOOL)acceptWithOptions:(NSUInteger)options timeout:(NSTimeInterval)timeout error:(WIError **)error { 00274 wi_pool_t *pool; 00275 wi_boolean_t result; 00276 00277 pool = wi_pool_init(wi_pool_alloc()); 00278 result = wi_p7_socket_accept(_p7Socket, timeout, options); 00279 wi_release(pool); 00280 00281 if(!result) { 00282 if(error) 00283 *error = [self _errorWithCode:WISocketConnectFailed]; 00284 00285 return NO; 00286 } 00287 00288 return YES; 00289 } 00290 00291 00292 00293 - (void)close { 00294 wi_p7_socket_close(_p7Socket); 00295 } 00296 00297 00298 00299 #pragma mark - 00300 00301 - (BOOL)writeMessage:(WIP7Message *)message timeout:(NSTimeInterval)timeout error:(WIError **)error { 00302 wi_pool_t *pool; 00303 wi_boolean_t result; 00304 00305 pool = wi_pool_init(wi_pool_alloc()); 00306 result = wi_p7_socket_write_message(_p7Socket, timeout, [message message]); 00307 wi_release(pool); 00308 00309 if(!result) { 00310 if(error) 00311 *error = [self _errorWithCode:WISocketWriteFailed]; 00312 00313 return NO; 00314 } 00315 00316 return YES; 00317 } 00318 00319 00320 00321 - (WIP7Message *)readMessageWithTimeout:(NSTimeInterval)timeout error:(WIError **)error { 00322 wi_pool_t *pool; 00323 wi_p7_message_t *result; 00324 WIP7Message *message; 00325 00326 pool = wi_pool_init(wi_pool_alloc()); 00327 result = wi_p7_socket_read_message(_p7Socket, timeout); 00328 00329 if(!result) { 00330 if(error) { 00331 if(wi_error_domain() == WI_ERROR_DOMAIN_ERRNO && wi_error_code() == ETIMEDOUT) { 00332 if(!_readTimeoutError) 00333 _readTimeoutError = [[self _errorWithCode:WISocketReadFailed] retain]; 00334 00335 *error = _readTimeoutError; 00336 } else { 00337 *error = [self _errorWithCode:WISocketReadFailed]; 00338 } 00339 } 00340 00341 wi_release(pool); 00342 00343 return NULL; 00344 } 00345 00346 message = [WIP7Message messageWithMessage:result spec:_spec]; 00347 00348 wi_release(pool); 00349 00350 return message; 00351 } 00352 00353 00354 00355 - (BOOL)writeOOBData:(const void *)data length:(NSUInteger)length timeout:(NSTimeInterval)timeout error:(WIError **)error { 00356 wi_boolean_t result; 00357 00358 result = wi_p7_socket_write_oobdata(_p7Socket, timeout, data, length); 00359 00360 if(!result) { 00361 if(error) 00362 *error = [self _errorWithCode:WISocketWriteFailed]; 00363 00364 return NO; 00365 } 00366 00367 return YES; 00368 } 00369 00370 00371 00372 - (NSInteger)readOOBData:(void **)data timeout:(NSTimeInterval)timeout error:(WIError **)error { 00373 wi_integer_t result; 00374 00375 result = wi_p7_socket_read_oobdata(_p7Socket, timeout, data); 00376 00377 if(result < 0) { 00378 if(wi_error_domain() == WI_ERROR_DOMAIN_ERRNO && wi_error_code() == ETIMEDOUT) { 00379 if(!_readTimeoutError) 00380 _readTimeoutError = [[self _errorWithCode:WISocketReadFailed] retain]; 00381 00382 *error = _readTimeoutError; 00383 } else { 00384 *error = [self _errorWithCode:WISocketReadFailed]; 00385 } 00386 00387 return result; 00388 } 00389 00390 return result; 00391 } 00392 00393 @end