|
Wired Networking
2.0
Objective-C implementation of the Wired 2.0 protocol
|
00001 /* $Id$ */ 00002 00003 /* 00004 * Copyright (c) 2006-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 #import <WiredNetworking/NSString-WINetworking.h> 00030 #import <WiredNetworking/WIAddress.h> 00031 #import <WiredNetworking/WIError.h> 00032 #import <WiredNetworking/WISocket.h> 00033 00034 #define _WISocketBufferMaxSize 131072 00035 00036 00037 static void _WISocketCallback(CFSocketRef, CFSocketCallBackType, CFDataRef, const void *, void *); 00038 00039 static void _WISocketCallback(CFSocketRef socketRef, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) { 00040 WISocket *socket = info; 00041 00042 [[socket delegate] socket:socket handleEvent:callbackType]; 00043 } 00044 00045 00046 00047 @interface WISocketTLS(Private) 00048 00049 - (id)_initForClient; 00050 00051 @end 00052 00053 00054 @implementation WISocketTLS(Private) 00055 00056 - (id)_initForClient { 00057 #ifdef WI_SSL 00058 wi_pool_t *pool; 00059 00060 self = [super init]; 00061 00062 pool = wi_pool_init(wi_pool_alloc()); 00063 _tls = wi_socket_tls_init_with_type(wi_socket_tls_alloc(), WI_SOCKET_TLS_CLIENT); 00064 wi_release(pool); 00065 00066 return self; 00067 #else 00068 [self release]; 00069 00070 return NULL; 00071 #endif 00072 } 00073 00074 @end 00075 00076 00077 00078 @implementation WISocketTLS 00079 00080 + (WISocketTLS *)socketTLSForClient { 00081 return [[[self alloc] _initForClient] autorelease]; 00082 } 00083 00084 00085 00086 - (void)dealloc { 00087 wi_release(_tls); 00088 00089 [super dealloc]; 00090 } 00091 00092 00093 00094 #pragma mark - 00095 00096 - (wi_socket_tls_t *)TLS { 00097 return _tls; 00098 } 00099 00100 00101 00102 #pragma mark - 00103 00104 - (void)setSSLCiphers:(NSString *)ciphers { 00105 #ifdef WI_SSL 00106 wi_pool_t *pool; 00107 00108 pool = wi_pool_init(wi_pool_alloc()); 00109 wi_socket_tls_set_ciphers(_tls, [ciphers wiredString]); 00110 wi_release(pool); 00111 #endif 00112 } 00113 00114 @end 00115 00116 00117 00118 @interface WISocket(Private) 00119 00120 - (id)_initWithSocket:(wi_socket_t *)socket address:(WIAddress *)address; 00121 00122 - (WIError *)_errorWithCode:(NSInteger)code; 00123 00124 @end 00125 00126 00127 @implementation WISocket(Private) 00128 00129 - (id)_initWithSocket:(wi_socket_t *)socket address:(WIAddress *)address { 00130 self = [self init]; 00131 00132 _socket = wi_retain(socket); 00133 _address = [address retain]; 00134 00135 return self; 00136 } 00137 00138 00139 00140 #pragma mark - 00141 00142 - (WIError *)_errorWithCode:(NSInteger)code { 00143 return [WIError errorWithDomain:WIWiredNetworkingErrorDomain 00144 code:code 00145 userInfo:[NSDictionary dictionaryWithObjectsAndKeys: 00146 [WIError errorWithDomain:WILibWiredErrorDomain], 00147 WILibWiredErrorKey, 00148 [_address string], 00149 WIArgumentErrorKey, 00150 NULL]]; 00151 } 00152 00153 @end 00154 00155 00156 00157 @implementation WISocket 00158 00159 + (WISocket *)socketWithAddress:(WIAddress *)address type:(WISocketType)type { 00160 return [[[self alloc] initWithAddress:address type:type] autorelease]; 00161 } 00162 00163 00164 00165 + (WISocket *)socketWithFileDescriptor:(int)sd { 00166 return [[[self alloc] initWithFileDescriptor:sd] autorelease]; 00167 } 00168 00169 00170 00171 - (id)initWithAddress:(WIAddress *)address type:(WISocketType)type { 00172 wi_pool_t *pool; 00173 wi_socket_t *socket; 00174 00175 pool = wi_pool_init(wi_pool_alloc()); 00176 socket = wi_socket_init_with_address(wi_socket_alloc(), [address address], type); 00177 00178 self = [self _initWithSocket:socket address:address]; 00179 00180 wi_release(socket); 00181 wi_release(pool); 00182 00183 return self; 00184 } 00185 00186 00187 00188 - (id)initWithFileDescriptor:(int)sd { 00189 WIAddress *address; 00190 wi_pool_t *pool; 00191 wi_socket_t *socket; 00192 00193 pool = wi_pool_init(wi_pool_alloc()); 00194 socket = wi_socket_init_with_descriptor(wi_socket_alloc(), sd); 00195 address = [[WIAddress alloc] initWithAddress:wi_socket_address(socket)]; 00196 00197 self = [self _initWithSocket:socket address:address]; 00198 00199 [address release]; 00200 wi_release(socket); 00201 wi_release(pool); 00202 00203 return self; 00204 } 00205 00206 00207 00208 - (id)init { 00209 self = [super init]; 00210 00211 _buffer = [[NSMutableString alloc] initWithCapacity:WISocketBufferSize]; 00212 00213 return self; 00214 } 00215 00216 00217 00218 - (void)dealloc { 00219 wi_pool_t *pool; 00220 00221 pool = wi_pool_init(wi_pool_alloc()); 00222 wi_release(_socket); 00223 wi_release(pool); 00224 00225 [_address release]; 00226 [_buffer release]; 00227 00228 [super dealloc]; 00229 } 00230 00231 00232 00233 #pragma mark - 00234 00235 - (WIAddress *)address { 00236 return _address; 00237 } 00238 00239 00240 00241 - (int)fileDescriptor { 00242 return wi_socket_descriptor(_socket); 00243 } 00244 00245 00246 00247 - (void *)SSL { 00248 return wi_socket_ssl(_socket); 00249 } 00250 00251 00252 00253 - (wi_socket_t *)socket { 00254 return _socket; 00255 } 00256 00257 00258 00259 - (NSString *)cipherVersion { 00260 NSString *string; 00261 wi_pool_t *pool; 00262 00263 pool = wi_pool_init(wi_pool_alloc()); 00264 string = [NSString stringWithWiredString:wi_socket_cipher_version(_socket)]; 00265 wi_release(pool); 00266 00267 return string; 00268 } 00269 00270 00271 00272 - (NSString *)cipherName { 00273 NSString *string; 00274 wi_pool_t *pool; 00275 00276 pool = wi_pool_init(wi_pool_alloc()); 00277 string = [NSString stringWithWiredString:wi_socket_cipher_name(_socket)]; 00278 wi_release(pool); 00279 00280 return string; 00281 } 00282 00283 00284 00285 - (NSUInteger)cipherBits { 00286 return wi_socket_cipher_bits(_socket); 00287 } 00288 00289 00290 00291 - (NSString *)certificateName { 00292 NSString *string = NULL; 00293 wi_pool_t *pool; 00294 wi_string_t *wstring; 00295 00296 pool = wi_pool_init(wi_pool_alloc()); 00297 wstring = wi_socket_certificate_name(_socket); 00298 00299 if(wstring) 00300 string = [NSString stringWithWiredString:wstring]; 00301 00302 wi_release(pool); 00303 00304 return string; 00305 } 00306 00307 00308 00309 - (NSUInteger)certificateBits { 00310 return wi_socket_certificate_bits(_socket); 00311 } 00312 00313 00314 00315 - (NSString *)certificateHostname { 00316 NSString *string = NULL; 00317 wi_pool_t *pool; 00318 wi_string_t *wstring; 00319 00320 pool = wi_pool_init(wi_pool_alloc()); 00321 wstring = wi_socket_certificate_hostname(_socket); 00322 00323 if(wstring) 00324 string = [NSString stringWithWiredString:wstring]; 00325 00326 wi_release(pool); 00327 00328 return string; 00329 } 00330 00331 00332 00333 #pragma mark - 00334 00335 - (void)setDelegate:(id <WISocketDelegate>)newDelegate { 00336 delegate = newDelegate; 00337 } 00338 00339 00340 00341 - (id <WISocketDelegate>)delegate { 00342 return delegate; 00343 } 00344 00345 00346 00347 - (void)setPort:(NSUInteger)port { 00348 wi_socket_set_port(_socket, port); 00349 00350 [_address setPort:port]; 00351 } 00352 00353 00354 00355 - (NSUInteger)port { 00356 return wi_socket_port(_socket); 00357 } 00358 00359 00360 00361 - (void)setDirection:(WISocketDirection)direction { 00362 wi_socket_set_direction(_socket, (wi_socket_direction_t) direction); 00363 } 00364 00365 00366 00367 - (WISocketDirection)direction { 00368 return (WISocketDirection) wi_socket_direction(_socket); 00369 } 00370 00371 00372 00373 - (void)setBlocking:(BOOL)blocking { 00374 wi_socket_set_blocking(_socket, blocking); 00375 } 00376 00377 00378 00379 - (BOOL)blocking { 00380 return wi_socket_blocking(_socket); 00381 } 00382 00383 00384 00385 - (void)setInteractive:(BOOL)interactive { 00386 wi_socket_set_interactive(_socket, interactive); 00387 } 00388 00389 00390 00391 - (BOOL)interactive { 00392 return wi_socket_interactive(_socket); 00393 } 00394 00395 00396 00397 #pragma mark - 00398 00399 - (BOOL)waitWithTimeout:(NSTimeInterval)timeout { 00400 wi_pool_t *pool; 00401 wi_socket_state_t state; 00402 00403 pool = wi_pool_init(wi_pool_alloc()); 00404 state = wi_socket_wait(_socket, timeout); 00405 wi_release(pool); 00406 00407 return (state == WI_SOCKET_READY); 00408 } 00409 00410 00411 00412 #pragma mark - 00413 00414 - (BOOL)connectWithTimeout:(NSTimeInterval)timeout error:(WIError **)error { 00415 wi_pool_t *pool; 00416 BOOL result = YES; 00417 00418 pool = wi_pool_init(wi_pool_alloc()); 00419 00420 if(!wi_socket_connect(_socket, timeout)) { 00421 if(error) 00422 *error = [self _errorWithCode:WISocketConnectFailed]; 00423 00424 result = NO; 00425 } 00426 00427 wi_release(pool); 00428 00429 return result; 00430 } 00431 00432 00433 00434 - (BOOL)connectWithTLS:(WISocketTLS *)tls timeout:(NSTimeInterval)timeout error:(WIError **)error { 00435 #ifdef WI_SSL 00436 wi_pool_t *pool; 00437 BOOL result = YES; 00438 00439 pool = wi_pool_init(wi_pool_alloc()); 00440 00441 if(!wi_socket_connect_tls(_socket, [tls TLS], timeout)) { 00442 if(error) 00443 *error = [self _errorWithCode:WISocketConnectFailed]; 00444 00445 result = NO; 00446 } 00447 00448 wi_release(pool); 00449 00450 return result; 00451 #else 00452 return NO; 00453 #endif 00454 } 00455 00456 00457 00458 - (BOOL)listenWithError:(WIError **)error { 00459 wi_pool_t *pool; 00460 BOOL result = YES; 00461 00462 pool = wi_pool_init(wi_pool_alloc()); 00463 00464 if(!wi_socket_listen(_socket)) { 00465 if(error) 00466 *error = [self _errorWithCode:WISocketListenFailed]; 00467 00468 result = NO; 00469 } 00470 00471 if([_address port] == 0) 00472 [_address setPort:wi_socket_port(_socket)]; 00473 00474 wi_release(pool); 00475 00476 return result; 00477 } 00478 00479 00480 00481 - (WISocket *)acceptWithTimeout:(NSTimeInterval)timeout error:(WIError **)error { 00482 WISocket *remoteSocket = NULL; 00483 wi_pool_t *pool; 00484 wi_socket_t *socket; 00485 wi_address_t *address; 00486 00487 pool = wi_pool_init(wi_pool_alloc()); 00488 00489 socket = wi_socket_accept(_socket, timeout, &address); 00490 00491 if(socket) 00492 remoteSocket = [[[WISocket alloc] _initWithSocket:socket address:[[[WIAddress alloc] initWithAddress:address] autorelease]] autorelease]; 00493 else if(error) 00494 *error = [self _errorWithCode:WISocketListenFailed]; 00495 00496 wi_release(pool); 00497 00498 return remoteSocket; 00499 } 00500 00501 00502 00503 - (void)close { 00504 wi_pool_t *pool; 00505 00506 pool = wi_pool_init(wi_pool_alloc()); 00507 wi_socket_close(_socket); 00508 wi_release(pool); 00509 } 00510 00511 00512 00513 #pragma mark - 00514 00515 - (BOOL)writeString:(NSString *)string encoding:(NSStringEncoding)encoding timeout:(NSTimeInterval)timeout error:(WIError **)error { 00516 NSData *data; 00517 wi_pool_t *pool; 00518 BOOL result = NO; 00519 00520 pool = wi_pool_init(wi_pool_alloc()); 00521 data = [string dataUsingEncoding:encoding]; 00522 00523 if(wi_socket_write_buffer(_socket, timeout, [data bytes], [data length]) < 0) { 00524 if(error) 00525 *error = [self _errorWithCode:WISocketWriteFailed]; 00526 00527 result = NO; 00528 } 00529 00530 wi_release(pool); 00531 00532 return result; 00533 } 00534 00535 00536 00537 #pragma mark - 00538 00539 - (NSString *)readStringOfLength:(NSUInteger)length encoding:(NSStringEncoding)encoding timeout:(NSTimeInterval)timeout error:(WIError **)error { 00540 NSMutableString *string, *substring; 00541 wi_pool_t *pool; 00542 char buffer[WISocketBufferSize]; 00543 wi_integer_t bytes = -1; 00544 00545 pool = wi_pool_init(wi_pool_alloc()); 00546 string = [[NSMutableString alloc] initWithCapacity:length]; 00547 00548 while(length > sizeof(buffer)) { 00549 bytes = wi_socket_read_buffer(_socket, timeout, buffer, sizeof(buffer)); 00550 00551 if(bytes <= 0) 00552 goto end; 00553 00554 substring = [[NSString alloc] initWithBytes:buffer length:bytes encoding:encoding]; 00555 00556 if(substring) { 00557 [string appendString:substring]; 00558 [substring release]; 00559 00560 length -= bytes; 00561 } 00562 } 00563 00564 if(length > 0) { 00565 do { 00566 bytes = wi_socket_read_buffer(_socket, timeout, buffer, length); 00567 00568 if(bytes <= 0) 00569 goto end; 00570 00571 substring = [[NSString alloc] initWithBytes:buffer length:bytes encoding:encoding]; 00572 00573 if(substring) { 00574 [string appendString:substring]; 00575 [substring release]; 00576 } 00577 } while(!substring); 00578 } 00579 00580 end: 00581 if([string length] == 0) { 00582 if(bytes < 0) { 00583 if(error) { 00584 if(wi_error_domain() == WI_ERROR_DOMAIN_ERRNO && wi_error_code() == ETIMEDOUT) { 00585 if(!_readTimeoutError) 00586 _readTimeoutError = [[self _errorWithCode:WISocketReadFailed] retain]; 00587 00588 *error = _readTimeoutError; 00589 } else { 00590 *error = [self _errorWithCode:WISocketReadFailed]; 00591 } 00592 } 00593 00594 [string release]; 00595 00596 string = NULL; 00597 } 00598 } 00599 00600 wi_release(pool); 00601 00602 return [string autorelease]; 00603 } 00604 00605 00606 00607 - (NSString *)readStringUpToString:(NSString *)separator encoding:(NSStringEncoding)encoding timeout:(NSTimeInterval)timeout error:(WIError **)error { 00608 NSString *string, *substring; 00609 NSUInteger index; 00610 00611 index = [_buffer rangeOfString:separator].location; 00612 00613 if(index != NSNotFound) { 00614 substring = [_buffer substringToIndex:index + [separator length]]; 00615 00616 [_buffer deleteCharactersInRange:NSMakeRange(0, [substring length])]; 00617 00618 return substring; 00619 } 00620 00621 while((string = [self readStringOfLength:WISocketBufferSize encoding:encoding timeout:timeout error:error])) { 00622 if([string length] == 0) 00623 return string; 00624 00625 [_buffer appendString:string]; 00626 00627 index = [_buffer rangeOfString:separator].location; 00628 00629 if(index == NSNotFound) { 00630 if([_buffer length] > _WISocketBufferMaxSize) { 00631 substring = [_buffer substringToIndex:_WISocketBufferMaxSize]; 00632 00633 [_buffer deleteCharactersInRange:NSMakeRange(0, [substring length])]; 00634 00635 return substring; 00636 } 00637 } else { 00638 substring = [_buffer substringToIndex:index + [separator length]]; 00639 00640 [_buffer deleteCharactersInRange:NSMakeRange(0, [substring length])]; 00641 00642 return substring; 00643 } 00644 } 00645 00646 return NULL; 00647 } 00648 00649 00650 00651 - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode { 00652 CFSocketContext context; 00653 CFSocketCallBackType type; 00654 00655 if(!_sourceRef) { 00656 context.version = 0; 00657 context.info = self; 00658 context.retain = NULL; 00659 context.release = NULL; 00660 context.copyDescription = NULL; 00661 00662 type = kCFSocketNoCallBack; 00663 00664 if([self direction] & WISocketRead) 00665 type |= kCFSocketReadCallBack; 00666 00667 if([self direction] & WISocketWrite) 00668 type |= kCFSocketWriteCallBack; 00669 00670 _socketRef = CFSocketCreateWithNative(NULL, 00671 wi_socket_descriptor(_socket), 00672 type, 00673 _WISocketCallback, 00674 &context); 00675 00676 _sourceRef = CFSocketCreateRunLoopSource(NULL, _socketRef, 0); 00677 } 00678 00679 CFRunLoopAddSource([runLoop getCFRunLoop], _sourceRef, (CFStringRef) mode); 00680 } 00681 00682 00683 00684 - (void)removeFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode { 00685 if(_sourceRef) { 00686 CFRunLoopRemoveSource([runLoop getCFRunLoop], _sourceRef, (CFStringRef) mode); 00687 00688 if(_sourceRef) { 00689 CFRelease(_sourceRef); 00690 _sourceRef = NULL; 00691 } 00692 00693 if(_socketRef) { 00694 CFSocketInvalidate(_socketRef); 00695 CFRelease(_socketRef); 00696 _socketRef = NULL; 00697 } 00698 } 00699 } 00700 00701 @end