jens@0: // jens@0: // BLIPTest.m jens@0: // MYNetwork jens@0: // jens@0: // Created by Jens Alfke on 5/13/08. jens@0: // Copyright 2008 Jens Alfke. All rights reserved. jens@0: // jens@0: jens@0: #ifndef NDEBUG jens@0: jens@0: jens@0: #import "BLIPRequest.h" jens@0: #import "BLIPProperties.h" jens@0: #import "BLIPConnection.h" jens@1: jens@0: #import "IPAddress.h" jens@0: #import "Target.h" jens@1: #import "CollectionUtils.h" jens@1: #import "Logging.h" jens@1: #import "Test.h" jens@0: jens@0: #define HAVE_KEYCHAIN_FRAMEWORK 0 jens@0: #if HAVE_KEYCHAIN_FRAMEWORK jens@0: #import jens@0: #endif jens@0: jens@1: jens@11: #define kListenerHost @"localhost" jens@0: #define kListenerPort 46353 jens@0: #define kSendInterval 0.5 jens@0: #define kNBatchedMessages 20 jens@0: #define kUseCompression YES jens@0: #define kUrgentEvery 4 jens@0: #define kClientRequiresSSL NO jens@0: #define kClientUsesSSLCert NO jens@0: #define kListenerRequiresSSL NO jens@0: #define kListenerRequiresClientCert NO jens@0: jens@0: jens@0: static SecIdentityRef GetClientIdentity(void) { jens@0: return NULL; // Make this return a valid identity to test client-side certs jens@0: } jens@0: jens@0: static SecIdentityRef GetListenerIdentity(void) { jens@0: return NULL; // Make this return a valid identity to test client-side certs jens@0: } jens@0: jens@0: jens@0: #pragma mark - jens@0: #pragma mark CLIENT TEST: jens@0: jens@0: jens@0: @interface BLIPConnectionTester : NSObject jens@0: { jens@0: BLIPConnection *_conn; jens@0: NSMutableDictionary *_pending; jens@0: } jens@0: jens@0: @end jens@0: jens@0: jens@0: @implementation BLIPConnectionTester jens@0: jens@0: - (id) init jens@0: { jens@0: self = [super init]; jens@0: if (self != nil) { jens@0: Log(@"** INIT %@",self); jens@0: _pending = [[NSMutableDictionary alloc] init]; jens@11: IPAddress *addr = [[IPAddress alloc] initWithHostname: kListenerHost port: kListenerPort]; jens@0: _conn = [[BLIPConnection alloc] initToAddress: addr]; jens@0: if( ! _conn ) { jens@0: [self release]; jens@0: return nil; jens@0: } jens@0: if( kClientRequiresSSL ) { jens@0: _conn.SSLProperties = $mdict({kTCPPropertySSLAllowsAnyRoot, $true}); jens@0: if( kClientUsesSSLCert ) { jens@0: SecIdentityRef clientIdentity = GetClientIdentity(); jens@0: if( clientIdentity ) { jens@0: [_conn setSSLProperty: $array((id)clientIdentity) jens@0: forKey: kTCPPropertySSLCertificates]; jens@0: } jens@0: } jens@0: } jens@0: _conn.delegate = self; jens@0: Log(@"** Opening connection..."); jens@0: [_conn open]; jens@0: } jens@0: return self; jens@0: } jens@0: jens@0: - (void) dealloc jens@0: { jens@0: Log(@"** %@ closing",self); jens@0: [_conn close]; jens@0: [_conn release]; jens@0: [super dealloc]; jens@0: } jens@0: jens@0: - (void) sendAMessage jens@0: { jens@11: if(_pending.count<100) { jens@11: Log(@"** Sending another %i messages...", kNBatchedMessages); jens@11: for( int i=0; i 12 ) jens@11: q.urgent = YES; jens@11: BLIPResponse *response = [q send]; jens@11: Assert(response); jens@11: Assert(q.number>0); jens@11: Assert(response.number==q.number); jens@11: [_pending setObject: $object(size) forKey: $object(q.number)]; jens@11: response.onComplete = $target(self,responseArrived:); jens@11: } jens@11: } else { jens@11: Warn(@"There are %u pending messages; waiting for the listener to catch up...",_pending.count); jens@0: } jens@0: [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval]; jens@0: } jens@0: jens@0: - (void) responseArrived: (BLIPResponse*)response jens@0: { jens@0: Log(@"********** called responseArrived: %@",response); jens@0: } jens@0: jens@0: - (void) connectionDidOpen: (TCPConnection*)connection jens@0: { jens@0: Log(@"** %@ didOpen",connection); jens@0: [self sendAMessage]; jens@0: } jens@0: - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert jens@0: { jens@0: #if HAVE_KEYCHAIN_FRAMEWORK jens@0: Certificate *cert = peerCert ?[Certificate certificateWithCertificateRef: peerCert] :nil; jens@0: Log(@"** %@ authorizeSSLPeer: %@",self,cert); jens@0: #else jens@0: Log(@"** %@ authorizeSSLPeer: %@",self,peerCert); jens@0: #endif jens@0: return peerCert != nil; jens@0: } jens@0: - (void) connection: (TCPConnection*)connection failedToOpen: (NSError*)error jens@0: { jens@0: Log(@"** %@ failedToOpen: %@",connection,error); jens@0: CFRunLoopStop(CFRunLoopGetCurrent()); jens@0: } jens@0: - (void) connectionDidClose: (TCPConnection*)connection jens@0: { jens@0: Log(@"** %@ didClose",connection); jens@0: setObj(&_conn,nil); jens@0: [NSObject cancelPreviousPerformRequestsWithTarget: self]; jens@0: CFRunLoopStop(CFRunLoopGetCurrent()); jens@0: } jens@0: - (void) connection: (BLIPConnection*)connection receivedRequest: (BLIPRequest*)request jens@0: { jens@0: Log(@"***** %@ received %@",connection,request); jens@2: [request respondWithData: request.body contentType: request.contentType]; jens@0: } jens@0: jens@0: - (void) connection: (BLIPConnection*)connection receivedResponse: (BLIPResponse*)response jens@0: { jens@0: Log(@"********** %@ received %@",connection,response); jens@0: NSNumber *sizeObj = [_pending objectForKey: $object(response.number)]; jens@0: jens@0: if( response.error ) jens@0: Warn(@"Got error response: %@",response.error); jens@0: else { jens@0: NSData *body = response.body; jens@0: size_t size = body.length; jens@0: Assert(size<32768); jens@0: const UInt8 *bytes = body.bytes; jens@0: for( size_t i=0; i jens@0: { jens@0: BLIPListener *_listener; jens@0: } jens@0: jens@0: @end jens@0: jens@0: jens@0: @implementation BLIPTestListener jens@0: jens@0: - (id) init jens@0: { jens@0: self = [super init]; jens@0: if (self != nil) { jens@0: _listener = [[BLIPListener alloc] initWithPort: kListenerPort]; jens@0: _listener.delegate = self; jens@0: _listener.pickAvailablePort = YES; jens@0: _listener.bonjourServiceType = @"_bliptest._tcp"; jens@0: if( kListenerRequiresSSL ) { jens@0: SecIdentityRef listenerIdentity = GetListenerIdentity(); jens@0: Assert(listenerIdentity); jens@0: _listener.SSLProperties = $mdict({kTCPPropertySSLCertificates, $array((id)listenerIdentity)}, jens@0: {kTCPPropertySSLAllowsAnyRoot,$true}, jens@8: {kTCPPropertySSLClientSideAuthentication, $object(kTCPTryAuthenticate)}); jens@0: } jens@0: Assert( [_listener open] ); jens@0: Log(@"%@ is listening...",self); jens@0: } jens@0: return self; jens@0: } jens@0: jens@0: - (void) dealloc jens@0: { jens@0: Log(@"%@ closing",self); jens@0: [_listener close]; jens@0: [_listener release]; jens@0: [super dealloc]; jens@0: } jens@0: jens@0: - (void) listener: (TCPListener*)listener didAcceptConnection: (TCPConnection*)connection jens@0: { jens@0: Log(@"** %@ accepted %@",self,connection); jens@0: connection.delegate = self; jens@0: } jens@0: jens@0: - (void) listener: (TCPListener*)listener failedToOpen: (NSError*)error jens@0: { jens@0: Log(@"** BLIPTestListener failed to open: %@",error); jens@0: } jens@0: jens@0: - (void) listenerDidOpen: (TCPListener*)listener {Log(@"** BLIPTestListener did open");} jens@0: - (void) listenerDidClose: (TCPListener*)listener {Log(@"** BLIPTestListener did close");} jens@0: jens@0: - (BOOL) listener: (TCPListener*)listener shouldAcceptConnectionFrom: (IPAddress*)address jens@0: { jens@0: Log(@"** %@ shouldAcceptConnectionFrom: %@",self,address); jens@0: return YES; jens@0: } jens@0: jens@0: jens@0: - (void) connectionDidOpen: (TCPConnection*)connection jens@0: { jens@0: Log(@"** %@ didOpen [SSL=%@]",connection,connection.actualSecurityLevel); jens@0: } jens@0: - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert jens@0: { jens@0: #if HAVE_KEYCHAIN_FRAMEWORK jens@0: Certificate *cert = peerCert ?[Certificate certificateWithCertificateRef: peerCert] :nil; jens@0: Log(@"** %@ authorizeSSLPeer: %@",connection,cert); jens@0: #else jens@0: Log(@"** %@ authorizeSSLPeer: %@",self,peerCert); jens@0: #endif jens@0: return peerCert != nil || ! kListenerRequiresClientCert; jens@0: } jens@0: - (void) connection: (TCPConnection*)connection failedToOpen: (NSError*)error jens@0: { jens@0: Log(@"** %@ failedToOpen: %@",connection,error); jens@0: } jens@0: - (void) connectionDidClose: (TCPConnection*)connection jens@0: { jens@0: Log(@"** %@ didClose",connection); jens@0: [connection release]; jens@0: } jens@0: - (void) connection: (BLIPConnection*)connection receivedRequest: (BLIPRequest*)request jens@0: { jens@0: Log(@"***** %@ received %@",connection,request); jens@0: NSData *body = request.body; jens@0: size_t size = body.length; jens@0: Assert(size<32768); jens@0: const UInt8 *bytes = body.bytes; jens@0: for( size_t i=0; i. All rights reserved. jens@0: jens@0: Redistribution and use in source and binary forms, with or without modification, are permitted jens@0: provided that the following conditions are met: jens@0: jens@0: * Redistributions of source code must retain the above copyright notice, this list of conditions jens@0: and the following disclaimer. jens@0: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions jens@0: and the following disclaimer in the documentation and/or other materials provided with the jens@0: distribution. jens@0: jens@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR jens@0: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND jens@0: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI- jens@0: BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES jens@0: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR jens@0: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN jens@0: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF jens@0: THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. jens@0: */