Got it to build on iPhone. (Haven't tried running it yet.)
authorJens Alfke <jens@mooseyard.com>
Thu May 29 16:40:36 2008 -0700 (2008-05-29)
changeset 86f539dd9921c
parent 7 5936db2c1987
child 9 980beba83fb7
Got it to build on iPhone. (Haven't tried running it yet.)
BLIP/BLIP.png
BLIP/BLIPDispatcher.h
BLIP/BLIPDispatcher.m
BLIP/BLIPMessage.m
BLIP/BLIPProperties.m
BLIP/BLIPReader.m
BLIP/BLIPTest.m
TCP/TCPConnection.h
TCP/TCPConnection.m
TCP/TCPEndpoint.h
TCP/TCPListener.m
maindocs.h
     1.1 Binary file BLIP/BLIP.png has changed
     2.1 --- a/BLIP/BLIPDispatcher.h	Sun May 25 13:43:03 2008 -0700
     2.2 +++ b/BLIP/BLIPDispatcher.h	Thu May 29 16:40:36 2008 -0700
     2.3 @@ -10,8 +10,9 @@
     2.4  @class MYTarget, BLIPMessage;
     2.5  
     2.6  
     2.7 -/** Routes BLIP messages to targets based on a series of rule predicates.
     2.8 -    Every BLIPConnection has a BLIPDispatcher, which is initially empty but you can add rules
     2.9 +/** Routes BLIP messages to targets based on a series of rules.
    2.10 + 
    2.11 +    Every BLIPConnection has a BLIPDispatcher, which is initially empty, but you can add rules
    2.12      to it.
    2.13   
    2.14      Every BLIPListener also has a dispatcher, which is inherited as the parent by every
    2.15 @@ -33,11 +34,13 @@
    2.16      the parent, if there is one. */
    2.17  @property (retain) BLIPDispatcher *parent;
    2.18  
    2.19 +/** Convenience method that adds a rule that compares a property against a string. */
    2.20 +- (void) addTarget: (MYTarget*)target forValueOfProperty: (NSString*)value forKey: (NSString*)key;
    2.21 +
    2.22 +#if ! TARGET_OS_IPHONE      /* NSPredicate is not available on iPhone, unfortunately */
    2.23  /** Adds a new rule, to call a given target method if a given predicate matches the message. */
    2.24  - (void) addTarget: (MYTarget*)target forPredicate: (NSPredicate*)predicate;
    2.25 -
    2.26 -/** Convenience method that adds a rule that compares a property against a string. */
    2.27 -- (void) addTarget: (MYTarget*)target forValueOfProperty: (NSString*)value forKey: (NSString*)key;
    2.28 +#endif
    2.29  
    2.30  /** Removes all rules with the given target method. */
    2.31  - (void) removeTarget: (MYTarget*)target;
     3.1 --- a/BLIP/BLIPDispatcher.m	Sun May 25 13:43:03 2008 -0700
     3.2 +++ b/BLIP/BLIPDispatcher.m	Thu May 29 16:40:36 2008 -0700
     3.3 @@ -39,11 +39,13 @@
     3.4  @synthesize parent=_parent;
     3.5  
     3.6  
     3.7 +#if ! TARGET_OS_IPHONE
     3.8  - (void) addTarget: (MYTarget*)target forPredicate: (NSPredicate*)predicate
     3.9  {
    3.10      [_targets addObject: target];
    3.11      [_predicates addObject: predicate];
    3.12  }
    3.13 +#endif
    3.14  
    3.15  
    3.16  - (void) removeTarget: (MYTarget*)target
    3.17 @@ -58,12 +60,29 @@
    3.18  
    3.19  - (void) addTarget: (MYTarget*)target forValueOfProperty: (NSString*)value forKey: (NSString*)key
    3.20  {
    3.21 +#if TARGET_OS_IPHONE
    3.22 +    Assert(target);
    3.23 +    [_predicates addObject: $array(key,value)];
    3.24 +    [_targets addObject: target];
    3.25 +#else
    3.26      [self addTarget: target 
    3.27         forPredicate: [NSComparisonPredicate predicateWithLeftExpression: [NSExpression expressionForKeyPath: key]
    3.28                                                          rightExpression: [NSExpression expressionForConstantValue: value]
    3.29                                                                 modifier: NSDirectPredicateModifier
    3.30                                                                     type: NSEqualToPredicateOperatorType
    3.31                                                                  options: 0]];
    3.32 +#endif
    3.33 +}
    3.34 +
    3.35 +
    3.36 +static BOOL testPredicate( id predicate, NSDictionary *properties ) {
    3.37 +#if TARGET_OS_IPHONE
    3.38 +    NSString *key = [predicate objectAtIndex: 0];
    3.39 +    NSString *value = [predicate objectAtIndex: 1];
    3.40 +    return $equal( [properties objectForKey: key], value );
    3.41 +#else
    3.42 +    return [(NSPredicate*)predicate evaluateWithObject: properties];
    3.43 +#endif
    3.44  }
    3.45  
    3.46  
    3.47 @@ -72,8 +91,8 @@
    3.48      NSDictionary *properties = message.properties.allProperties;
    3.49      NSUInteger n = _predicates.count;
    3.50      for( NSUInteger i=0; i<n; i++ ) {
    3.51 -        NSPredicate *p = [_predicates objectAtIndex: i];
    3.52 -        if( [p evaluateWithObject: properties] ) {
    3.53 +        id p = [_predicates objectAtIndex: i];
    3.54 +        if( testPredicate(p, properties) ) {
    3.55              MYTarget *target = [_targets objectAtIndex: i];
    3.56              LogTo(BLIP,@"Dispatcher matched %@ -- calling %@",p,target);
    3.57              [target invokeWithSender: message];
     4.1 --- a/BLIP/BLIPMessage.m	Sun May 25 13:43:03 2008 -0700
     4.2 +++ b/BLIP/BLIPMessage.m	Thu May 29 16:40:36 2008 -0700
     4.3 @@ -247,10 +247,10 @@
     4.4      }
     4.5          
     4.6      // First write the frame header:
     4.7 -    BLIPFrameHeader header = {  EndianU32_NtoB(kBLIPFrameHeaderMagicNumber),
     4.8 -                                EndianU32_NtoB(_number),
     4.9 -                                EndianU16_NtoB(flags),
    4.10 -                                EndianU16_NtoB(sizeof(BLIPFrameHeader) + lengthToWrite) };
    4.11 +    BLIPFrameHeader header = {  NSSwapHostIntToBig(kBLIPFrameHeaderMagicNumber),
    4.12 +                                NSSwapHostIntToBig(_number),
    4.13 +                                NSSwapHostShortToBig(flags),
    4.14 +                                NSSwapHostShortToBig(sizeof(BLIPFrameHeader) + lengthToWrite) };
    4.15      
    4.16      [writer writeData: [NSData dataWithBytes: &header length: sizeof(header)]];
    4.17      
     5.1 --- a/BLIP/BLIPProperties.m	Sun May 25 13:43:03 2008 -0700
     5.2 +++ b/BLIP/BLIPProperties.m	Thu May 29 16:40:36 2008 -0700
     5.3 @@ -56,7 +56,7 @@
     5.4      
     5.5      // Read the length:
     5.6      const char *bytes = data.bytes;
     5.7 -    size_t length = EndianU16_BtoN( *(UInt16*)bytes ) + sizeof(UInt16);
     5.8 +    size_t length = NSSwapBigShortToHost( *(UInt16*)bytes ) + sizeof(UInt16);
     5.9      if( length > available ) {
    5.10          // Properties not complete yet.
    5.11          *usedLength = 0;
    5.12 @@ -307,7 +307,7 @@
    5.13      NSUInteger length = data.length - sizeof(UInt16);
    5.14      if( length > 0xFFFF )
    5.15          return nil;
    5.16 -    *(UInt16*)[data mutableBytes] = EndianU16_NtoB((UInt16)length);
    5.17 +    *(UInt16*)[data mutableBytes] = NSSwapHostShortToBig((UInt16)length);
    5.18      return data;
    5.19  }
    5.20  
     6.1 --- a/BLIP/BLIPReader.m	Sun May 25 13:43:03 2008 -0700
     6.2 +++ b/BLIP/BLIPReader.m	Thu May 29 16:40:36 2008 -0700
     6.3 @@ -63,10 +63,10 @@
     6.4  - (NSString*) _validateHeader
     6.5  {
     6.6      // Convert header to native byte order:
     6.7 -    _curHeader.magic = EndianU32_BtoN(_curHeader.magic);
     6.8 -    _curHeader.number= EndianU32_BtoN(_curHeader.number);
     6.9 -    _curHeader.flags = EndianU16_BtoN(_curHeader.flags);
    6.10 -    _curHeader.size  = EndianU16_BtoN(_curHeader.size);
    6.11 +    _curHeader.magic = NSSwapBigIntToHost(_curHeader.magic);
    6.12 +    _curHeader.number= NSSwapBigIntToHost(_curHeader.number);
    6.13 +    _curHeader.flags = NSSwapBigShortToHost(_curHeader.flags);
    6.14 +    _curHeader.size  = NSSwapBigShortToHost(_curHeader.size);
    6.15      
    6.16      if( _curHeader.magic != kBLIPFrameHeaderMagicNumber )
    6.17          return $sprintf(@"Incorrect magic number (%08X not %08X)",
     7.1 --- a/BLIP/BLIPTest.m	Sun May 25 13:43:03 2008 -0700
     7.2 +++ b/BLIP/BLIPTest.m	Thu May 29 16:40:36 2008 -0700
     7.3 @@ -233,7 +233,7 @@
     7.4              Assert(listenerIdentity);
     7.5              _listener.SSLProperties = $mdict({kTCPPropertySSLCertificates, $array((id)listenerIdentity)},
     7.6                                               {kTCPPropertySSLAllowsAnyRoot,$true},
     7.7 -            {kTCPPropertySSLClientSideAuthentication, $object(kTryAuthenticate)});
     7.8 +                            {kTCPPropertySSLClientSideAuthentication, $object(kTCPTryAuthenticate)});
     7.9          }
    7.10          Assert( [_listener open] );
    7.11          Log(@"%@ is listening...",self);
     8.1 --- a/TCP/TCPConnection.h	Sun May 25 13:43:03 2008 -0700
     8.2 +++ b/TCP/TCPConnection.h	Thu May 29 16:40:36 2008 -0700
     8.3 @@ -7,6 +7,7 @@
     8.4  //
     8.5  
     8.6  #import "TCPEndpoint.h"
     8.7 +#import <Security/Security.h>
     8.8  @class IPAddress;
     8.9  @class TCPReader, TCPWriter, TCPListener;
    8.10  @protocol TCPConnectionDelegate;
     9.1 --- a/TCP/TCPConnection.m	Sun May 25 13:43:03 2008 -0700
     9.2 +++ b/TCP/TCPConnection.m	Thu May 29 16:40:36 2008 -0700
     9.3 @@ -14,6 +14,15 @@
     9.4  #import "ExceptionUtils.h"
     9.5  
     9.6  
     9.7 +#if TARGET_OS_IPHONE
     9.8 +// SecureTransport.h is missing on iPhone, with its SSL constants:
     9.9 +enum{
    9.10 +    errSSLClosedAbort 			= -9806,	/* connection closed via error */
    9.11 +};
    9.12 +#endif
    9.13 +
    9.14 +
    9.15 +
    9.16  NSString* const TCPErrorDomain = @"TCP";
    9.17  
    9.18  
    9.19 @@ -62,10 +71,20 @@
    9.20  {
    9.21      NSInputStream *input = nil;
    9.22      NSOutputStream *output = nil;
    9.23 +#if TARGET_OS_IPHONE
    9.24 +    // +getStreamsToHost: is missing for some stupid reason on iPhone. Grrrrrrrrrr.
    9.25 +    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)address.hostname, address.port,
    9.26 +                                       (CFReadStreamRef*)&input, (CFWriteStreamRef*)&output);
    9.27 +    if( input )
    9.28 +        [(id)CFMakeCollectable(input) autorelease];
    9.29 +    if( output )
    9.30 +        [(id)CFMakeCollectable(output) autorelease];
    9.31 +#else
    9.32      [NSStream getStreamsToHost: [NSHost hostWithAddress: address.ipv4name]
    9.33                            port: address.port 
    9.34                     inputStream: &input 
    9.35                    outputStream: &output];
    9.36 +#endif
    9.37      return [self _initWithAddress: address inputStream: input outputStream: output];
    9.38      //FIX: Support localPort!
    9.39  }
    10.1 --- a/TCP/TCPEndpoint.h	Sun May 25 13:43:03 2008 -0700
    10.2 +++ b/TCP/TCPEndpoint.h	Thu May 29 16:40:36 2008 -0700
    10.3 @@ -7,13 +7,23 @@
    10.4  //
    10.5  
    10.6  #import <Foundation/Foundation.h>
    10.7 +#if TARGET_OS_IPHONE
    10.8 +#include <CFNetwork/CFSocketStream.h>
    10.9 +#else
   10.10  #import <CoreServices/CoreServices.h>
   10.11 +#endif
   10.12  
   10.13  
   10.14  // SSL properties:
   10.15  #define kTCPPropertySSLCertificates  ((NSString*)kCFStreamSSLCertificates)
   10.16  #define kTCPPropertySSLAllowsAnyRoot ((NSString*)kCFStreamSSLAllowsAnyRoot)
   10.17 -extern NSString* const kTCPPropertySSLClientSideAuthentication;    // value is SSLAuthenticate enum
   10.18 +
   10.19 +extern NSString* const kTCPPropertySSLClientSideAuthentication;    // value is TCPAuthenticate enum
   10.20 +typedef enum {
   10.21 +	kTCPNeverAuthenticate,			/* skip client authentication */
   10.22 +	kTCPAlwaysAuthenticate,         /* require it */
   10.23 +	kTCPTryAuthenticate             /* try to authenticate, but not error if client has no cert */
   10.24 +} TCPAuthenticate; // these MUST have same values as SSLAuthenticate enum in SecureTransport.h!
   10.25  
   10.26  
   10.27  /** Abstract base class of TCPConnection and TCPListener.
    11.1 --- a/TCP/TCPListener.m	Sun May 25 13:43:03 2008 -0700
    11.2 +++ b/TCP/TCPListener.m	Thu May 29 16:40:36 2008 -0700
    11.3 @@ -129,7 +129,7 @@
    11.4          if( ! _ipv4socket ) {
    11.5              if( error.code==EADDRINUSE && _pickAvailablePort && _port<0xFFFF ) {
    11.6                  LogTo(BLIPVerbose,@"%@: port busy, trying %hu...",self,_port+1);
    11.7 -                self.port++;        // try the next port
    11.8 +                self.port += 1;        // try the next port
    11.9              } else {
   11.10                  if( outError ) *outError = error;
   11.11                  return [self _failedToOpen: error];
    12.1 --- a/maindocs.h	Sun May 25 13:43:03 2008 -0700
    12.2 +++ b/maindocs.h	Thu May 29 16:40:36 2008 -0700
    12.3 @@ -11,7 +11,9 @@
    12.4  /*! \mainpage MYNetwork: Mooseyard Networking Library, With BLIP Protocol Implementation
    12.5   
    12.6      <center><b>By <a href="/Jens/">Jens Alfke</a></b></center>
    12.7 - 
    12.8 +
    12.9 +    <img src="BLIP.png">
   12.10 +
   12.11  \section intro_sec Introduction
   12.12   
   12.13      MYNetwork is a set of Objective-C networking classes for Cocoa applications on Mac OS X.
   12.14 @@ -39,6 +41,19 @@
   12.15  
   12.16  \section blipdesc What's BLIP?
   12.17   
   12.18 + <table style="background-color: #fff; padding: 5px; float: right" cellspacing=0>
   12.19 + <tr><td>
   12.20 + <img src="http://groups.google.com/groups/img/3nb/groups_bar.gif"
   12.21 + height=26 width=132 alt="Google Groups">
   12.22 + </td></tr>
   12.23 + <tr><td style="padding-left: 5px;font-size: 125%">
   12.24 + <b>BLIP Protocol</b>
   12.25 + </td></tr>
   12.26 + <tr><td style="padding-left: 5px">
   12.27 + <a href="http://groups.google.com/group/blip-protocol">Visit this group</a>
   12.28 + </td></tr>
   12.29 + </table>
   12.30 + 
   12.31  BLIP is a message-oriented network protocol that lets the two peers on either end of a TCP socket send request and response messages to each other. It's a generic protocol, in that the requests and responses can contain any kind of data you like. 
   12.32   
   12.33  BLIP was inspired by <a
   12.34 @@ -77,7 +92,7 @@
   12.35   
   12.36  <li>The implementation supports SSL connections (with optional client-side certificates), and Bonjour service advertising.
   12.37  </ul>
   12.38 - 
   12.39 +  
   12.40  \section config Configuration
   12.41   
   12.42      MYNetwork requires Mac OS X 10.5 or later, since it uses Objective-C 2 features like