1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/BLIP/BLIPTest.m Fri May 23 17:37:36 2008 -0700
1.3 @@ -0,0 +1,350 @@
1.4 +//
1.5 +// BLIPTest.m
1.6 +// MYNetwork
1.7 +//
1.8 +// Created by Jens Alfke on 5/13/08.
1.9 +// Copyright 2008 Jens Alfke. All rights reserved.
1.10 +//
1.11 +
1.12 +#ifndef NDEBUG
1.13 +
1.14 +
1.15 +#import "BLIPRequest.h"
1.16 +#import "BLIPProperties.h"
1.17 +#import "BLIPConnection.h"
1.18 +#import "IPAddress.h"
1.19 +#import "Target.h"
1.20 +
1.21 +#define HAVE_KEYCHAIN_FRAMEWORK 0
1.22 +#if HAVE_KEYCHAIN_FRAMEWORK
1.23 +#import <Keychain/Keychain.h>
1.24 +#endif
1.25 +
1.26 +#define kListenerPort 46353
1.27 +#define kSendInterval 0.5
1.28 +#define kNBatchedMessages 20
1.29 +#define kUseCompression YES
1.30 +#define kUrgentEvery 4
1.31 +#define kClientRequiresSSL NO
1.32 +#define kClientUsesSSLCert NO
1.33 +#define kListenerRequiresSSL NO
1.34 +#define kListenerRequiresClientCert NO
1.35 +
1.36 +
1.37 +static SecIdentityRef GetClientIdentity(void) {
1.38 + return NULL; // Make this return a valid identity to test client-side certs
1.39 +}
1.40 +
1.41 +static SecIdentityRef GetListenerIdentity(void) {
1.42 + return NULL; // Make this return a valid identity to test client-side certs
1.43 +}
1.44 +
1.45 +
1.46 +#pragma mark -
1.47 +#pragma mark CLIENT TEST:
1.48 +
1.49 +
1.50 +@interface BLIPConnectionTester : NSObject <BLIPConnectionDelegate>
1.51 +{
1.52 + BLIPConnection *_conn;
1.53 + NSMutableDictionary *_pending;
1.54 +}
1.55 +
1.56 +@end
1.57 +
1.58 +
1.59 +@implementation BLIPConnectionTester
1.60 +
1.61 +- (id) init
1.62 +{
1.63 + self = [super init];
1.64 + if (self != nil) {
1.65 + Log(@"** INIT %@",self);
1.66 + _pending = [[NSMutableDictionary alloc] init];
1.67 + IPAddress *addr = [[IPAddress alloc] initWithHostname: @"localhost" port: kListenerPort];
1.68 + _conn = [[BLIPConnection alloc] initToAddress: addr];
1.69 + if( ! _conn ) {
1.70 + [self release];
1.71 + return nil;
1.72 + }
1.73 + if( kClientRequiresSSL ) {
1.74 + _conn.SSLProperties = $mdict({kTCPPropertySSLAllowsAnyRoot, $true});
1.75 + if( kClientUsesSSLCert ) {
1.76 + SecIdentityRef clientIdentity = GetClientIdentity();
1.77 + if( clientIdentity ) {
1.78 + [_conn setSSLProperty: $array((id)clientIdentity)
1.79 + forKey: kTCPPropertySSLCertificates];
1.80 + }
1.81 + }
1.82 + }
1.83 + _conn.delegate = self;
1.84 + Log(@"** Opening connection...");
1.85 + [_conn open];
1.86 + }
1.87 + return self;
1.88 +}
1.89 +
1.90 +- (void) dealloc
1.91 +{
1.92 + Log(@"** %@ closing",self);
1.93 + [_conn close];
1.94 + [_conn release];
1.95 + [super dealloc];
1.96 +}
1.97 +
1.98 +- (void) sendAMessage
1.99 +{
1.100 + Log(@"** Sending another %i messages...", kNBatchedMessages);
1.101 + for( int i=0; i<kNBatchedMessages; i++ ) {
1.102 + size_t size = random() % 32768;
1.103 + NSMutableData *body = [NSMutableData dataWithLength: size];
1.104 + UInt8 *bytes = body.mutableBytes;
1.105 + for( size_t i=0; i<size; i++ )
1.106 + bytes[i] = i % 256;
1.107 +
1.108 + BLIPRequest *q = [_conn requestWithBody: body
1.109 + properties: $dict({@"Content-Type", @"application/octet-stream"},
1.110 + {@"User-Agent", @"BLIPConnectionTester"},
1.111 + {@"Date", [[NSDate date] description]},
1.112 + {@"Size",$sprintf(@"%u",size)})];
1.113 + Assert(q);
1.114 + if( kUseCompression && (random()%2==1) )
1.115 + q.compressed = YES;
1.116 + if( random()%16 > 12 )
1.117 + q.urgent = YES;
1.118 + BLIPResponse *response = [q send];
1.119 + Assert(response);
1.120 + Assert(q.number>0);
1.121 + Assert(response.number==q.number);
1.122 + [_pending setObject: $object(size) forKey: $object(q.number)];
1.123 + response.onComplete = $target(self,responseArrived:);
1.124 + }
1.125 + [self performSelector: @selector(sendAMessage) withObject: nil afterDelay: kSendInterval];
1.126 +}
1.127 +
1.128 +- (void) responseArrived: (BLIPResponse*)response
1.129 +{
1.130 + Log(@"********** called responseArrived: %@",response);
1.131 +}
1.132 +
1.133 +- (void) connectionDidOpen: (TCPConnection*)connection
1.134 +{
1.135 + Log(@"** %@ didOpen",connection);
1.136 + [self sendAMessage];
1.137 +}
1.138 +- (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert
1.139 +{
1.140 +#if HAVE_KEYCHAIN_FRAMEWORK
1.141 + Certificate *cert = peerCert ?[Certificate certificateWithCertificateRef: peerCert] :nil;
1.142 + Log(@"** %@ authorizeSSLPeer: %@",self,cert);
1.143 +#else
1.144 + Log(@"** %@ authorizeSSLPeer: %@",self,peerCert);
1.145 +#endif
1.146 + return peerCert != nil;
1.147 +}
1.148 +- (void) connection: (TCPConnection*)connection failedToOpen: (NSError*)error
1.149 +{
1.150 + Log(@"** %@ failedToOpen: %@",connection,error);
1.151 + CFRunLoopStop(CFRunLoopGetCurrent());
1.152 +}
1.153 +- (void) connectionDidClose: (TCPConnection*)connection
1.154 +{
1.155 + Log(@"** %@ didClose",connection);
1.156 + setObj(&_conn,nil);
1.157 + [NSObject cancelPreviousPerformRequestsWithTarget: self];
1.158 + CFRunLoopStop(CFRunLoopGetCurrent());
1.159 +}
1.160 +- (void) connection: (BLIPConnection*)connection receivedRequest: (BLIPRequest*)request
1.161 +{
1.162 + Log(@"***** %@ received %@",connection,request);
1.163 + [request respondWithData: request.body];
1.164 +}
1.165 +
1.166 +- (void) connection: (BLIPConnection*)connection receivedResponse: (BLIPResponse*)response
1.167 +{
1.168 + Log(@"********** %@ received %@",connection,response);
1.169 + NSNumber *sizeObj = [_pending objectForKey: $object(response.number)];
1.170 +
1.171 + if( response.error )
1.172 + Warn(@"Got error response: %@",response.error);
1.173 + else {
1.174 + NSData *body = response.body;
1.175 + size_t size = body.length;
1.176 + Assert(size<32768);
1.177 + const UInt8 *bytes = body.bytes;
1.178 + for( size_t i=0; i<size; i++ )
1.179 + AssertEq(bytes[i],i % 256);
1.180 + AssertEq(size,sizeObj.intValue);
1.181 + }
1.182 + Assert(sizeObj);
1.183 + [_pending removeObjectForKey: $object(response.number)];
1.184 + Log(@"Now %u replies pending", _pending.count);
1.185 + Assert(_pending.count<100);
1.186 +}
1.187 +
1.188 +
1.189 +@end
1.190 +
1.191 +
1.192 +TestCase(BLIPConnection) {
1.193 +#if HAVE_KEYCHAIN_FRAMEWORK
1.194 + [Keychain setUserInteractionAllowed: YES];
1.195 +#endif
1.196 + BLIPConnectionTester *tester = [[BLIPConnectionTester alloc] init];
1.197 + CAssert(tester);
1.198 +
1.199 + [[NSRunLoop currentRunLoop] run];
1.200 +
1.201 + Log(@"** Runloop stopped");
1.202 + [tester release];
1.203 +}
1.204 +
1.205 +
1.206 +
1.207 +
1.208 +#pragma mark LISTENER TEST:
1.209 +
1.210 +
1.211 +@interface BLIPTestListener : NSObject <TCPListenerDelegate, BLIPConnectionDelegate>
1.212 +{
1.213 + BLIPListener *_listener;
1.214 +}
1.215 +
1.216 +@end
1.217 +
1.218 +
1.219 +@implementation BLIPTestListener
1.220 +
1.221 +- (id) init
1.222 +{
1.223 + self = [super init];
1.224 + if (self != nil) {
1.225 + _listener = [[BLIPListener alloc] initWithPort: kListenerPort];
1.226 + _listener.delegate = self;
1.227 + _listener.pickAvailablePort = YES;
1.228 + _listener.bonjourServiceType = @"_bliptest._tcp";
1.229 + if( kListenerRequiresSSL ) {
1.230 + SecIdentityRef listenerIdentity = GetListenerIdentity();
1.231 + Assert(listenerIdentity);
1.232 + _listener.SSLProperties = $mdict({kTCPPropertySSLCertificates, $array((id)listenerIdentity)},
1.233 + {kTCPPropertySSLAllowsAnyRoot,$true},
1.234 + {kTCPPropertySSLClientSideAuthentication, $object(kTryAuthenticate)});
1.235 + }
1.236 + Assert( [_listener open] );
1.237 + Log(@"%@ is listening...",self);
1.238 + }
1.239 + return self;
1.240 +}
1.241 +
1.242 +- (void) dealloc
1.243 +{
1.244 + Log(@"%@ closing",self);
1.245 + [_listener close];
1.246 + [_listener release];
1.247 + [super dealloc];
1.248 +}
1.249 +
1.250 +- (void) listener: (TCPListener*)listener didAcceptConnection: (TCPConnection*)connection
1.251 +{
1.252 + Log(@"** %@ accepted %@",self,connection);
1.253 + connection.delegate = self;
1.254 +}
1.255 +
1.256 +- (void) listener: (TCPListener*)listener failedToOpen: (NSError*)error
1.257 +{
1.258 + Log(@"** BLIPTestListener failed to open: %@",error);
1.259 +}
1.260 +
1.261 +- (void) listenerDidOpen: (TCPListener*)listener {Log(@"** BLIPTestListener did open");}
1.262 +- (void) listenerDidClose: (TCPListener*)listener {Log(@"** BLIPTestListener did close");}
1.263 +
1.264 +- (BOOL) listener: (TCPListener*)listener shouldAcceptConnectionFrom: (IPAddress*)address
1.265 +{
1.266 + Log(@"** %@ shouldAcceptConnectionFrom: %@",self,address);
1.267 + return YES;
1.268 +}
1.269 +
1.270 +
1.271 +- (void) connectionDidOpen: (TCPConnection*)connection
1.272 +{
1.273 + Log(@"** %@ didOpen [SSL=%@]",connection,connection.actualSecurityLevel);
1.274 +}
1.275 +- (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert
1.276 +{
1.277 +#if HAVE_KEYCHAIN_FRAMEWORK
1.278 + Certificate *cert = peerCert ?[Certificate certificateWithCertificateRef: peerCert] :nil;
1.279 + Log(@"** %@ authorizeSSLPeer: %@",connection,cert);
1.280 +#else
1.281 + Log(@"** %@ authorizeSSLPeer: %@",self,peerCert);
1.282 +#endif
1.283 + return peerCert != nil || ! kListenerRequiresClientCert;
1.284 +}
1.285 +- (void) connection: (TCPConnection*)connection failedToOpen: (NSError*)error
1.286 +{
1.287 + Log(@"** %@ failedToOpen: %@",connection,error);
1.288 +}
1.289 +- (void) connectionDidClose: (TCPConnection*)connection
1.290 +{
1.291 + Log(@"** %@ didClose",connection);
1.292 + [connection release];
1.293 +}
1.294 +- (void) connection: (BLIPConnection*)connection receivedRequest: (BLIPRequest*)request
1.295 +{
1.296 + Log(@"***** %@ received %@",connection,request);
1.297 + NSData *body = request.body;
1.298 + size_t size = body.length;
1.299 + Assert(size<32768);
1.300 + const UInt8 *bytes = body.bytes;
1.301 + for( size_t i=0; i<size; i++ )
1.302 + AssertEq(bytes[i],i % 256);
1.303 +
1.304 + AssertEqual([request valueOfProperty: @"Content-Type"], @"application/octet-stream");
1.305 + AssertEqual([request valueOfProperty: @"User-Agent"], @"BLIPConnectionTester");
1.306 + AssertEq([[request valueOfProperty: @"Size"] intValue], size);
1.307 +
1.308 + [request respondWithData: body];
1.309 +}
1.310 +
1.311 +
1.312 +@end
1.313 +
1.314 +
1.315 +TestCase(BLIPListener) {
1.316 + EnableLogTo(BLIP,YES);
1.317 + EnableLogTo(PortMapper,YES);
1.318 + EnableLogTo(Bonjour,YES);
1.319 +#if HAVE_KEYCHAIN_FRAMEWORK
1.320 + [Keychain setUserInteractionAllowed: YES];
1.321 +#endif
1.322 + BLIPTestListener *listener = [[BLIPTestListener alloc] init];
1.323 +
1.324 + [[NSRunLoop currentRunLoop] run];
1.325 +
1.326 + [listener release];
1.327 +}
1.328 +
1.329 +
1.330 +#endif
1.331 +
1.332 +
1.333 +/*
1.334 + Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
1.335 +
1.336 + Redistribution and use in source and binary forms, with or without modification, are permitted
1.337 + provided that the following conditions are met:
1.338 +
1.339 + * Redistributions of source code must retain the above copyright notice, this list of conditions
1.340 + and the following disclaimer.
1.341 + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
1.342 + and the following disclaimer in the documentation and/or other materials provided with the
1.343 + distribution.
1.344 +
1.345 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
1.346 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
1.347 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
1.348 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1.349 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1.350 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1.351 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
1.352 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.353 + */