* Added more documentation.
authorJens Alfke <jens@mooseyard.com>
Sat May 24 17:25:06 2008 -0700 (2008-05-24)
changeset 29fdd8dba529c
parent 1 8267d5c429c4
child 3 76f302097a75
* Added more documentation.
* Minor API changes.
.hgignore
BLIP/BLIPConnection.h
BLIP/BLIPConnection.m
BLIP/BLIPDispatcher.h
BLIP/BLIPDispatcher.m
BLIP/BLIPMessage.h
BLIP/BLIPProperties.m
BLIP/BLIPReader.m
BLIP/BLIPRequest.h
BLIP/BLIPRequest.m
BLIP/BLIPTest.m
IPAddress.h
MYNetwork.xcodeproj/project.pbxproj
TCP/TCPConnection.h
TCP/TCPListener.h
TCP/TCPStream.h
TCP/TCPStream.m
TCP/TCPWriter.h
maindocs.h
     1.1 --- a/.hgignore	Sat May 24 13:26:02 2008 -0700
     1.2 +++ b/.hgignore	Sat May 24 17:25:06 2008 -0700
     1.3 @@ -1,6 +1,9 @@
     1.4  syntax: glob
     1.5  .DS_Store
     1.6  build
     1.7 +Documentation
     1.8 +Doxyfile
     1.9 +uploadDocs
    1.10  .svn
    1.11  (*)
    1.12  *.pbxuser
     2.1 --- a/BLIP/BLIPConnection.h	Sat May 24 13:26:02 2008 -0700
     2.2 +++ b/BLIP/BLIPConnection.h	Sat May 24 17:25:06 2008 -0700
     2.3 @@ -25,6 +25,13 @@
     2.4  /** The delegate object that will be called when the connection opens, closes or receives messages. */
     2.5  @property (assign) id<BLIPConnectionDelegate> delegate;
     2.6  
     2.7 +/** The connection's request dispatcher. By default it's not configured to do anything; but you
     2.8 +    can add rules to the dispatcher to call specific target methods based on properties of the
     2.9 +    incoming requests.
    2.10 + 
    2.11 +    Requests that aren't handled by the dispatcher (i.e. all of them, by default) will be
    2.12 +    passed to the delegate's connection:receivedRequest: method; or if there's no delegate,
    2.13 +    a generic error response will be returned. */
    2.14  @property (readonly) BLIPDispatcher *dispatcher;
    2.15  
    2.16  /** Creates an outgoing request, with no properties.
    2.17 @@ -63,7 +70,8 @@
    2.18  
    2.19  @optional
    2.20  /** Called when a BLIPResponse (to one of your requests) is received from the peer.
    2.21 -    This is called <i>after</i> the response object's onComplete target, if any, is invoked. */
    2.22 +    This is called <i>after</i> the response object's onComplete target, if any, is invoked.
    2.23 +    (This method is optional.) */
    2.24  - (void) connection: (BLIPConnection*)connection receivedResponse: (BLIPResponse*)response;
    2.25  @end
    2.26  
    2.27 @@ -78,6 +86,10 @@
    2.28      BLIPDispatcher *_dispatcher;
    2.29  }
    2.30  
    2.31 +/** The default request dispatcher that will be inherited by all BLIPConnections opened by this
    2.32 +    listener.
    2.33 +    If a connection's own dispatcher doesn't have a rule to match a message, this inherited
    2.34 +    dispatcher will be checked next. Only if it fails too will the delegate be called. */
    2.35  @property (readonly) BLIPDispatcher *dispatcher;
    2.36  
    2.37  @end
     3.1 --- a/BLIP/BLIPConnection.m	Sat May 24 13:26:02 2008 -0700
     3.2 +++ b/BLIP/BLIPConnection.m	Sat May 24 17:25:06 2008 -0700
     3.3 @@ -66,7 +66,7 @@
     3.4              [self tellDelegate: @selector(connection:receivedRequest:) withObject: request];
     3.5          if( ! request.noReply && ! request.repliedTo ) {
     3.6              LogTo(BLIP,@"Returning default empty response to %@",request);
     3.7 -            [request respondWithData: nil];
     3.8 +            [request respondWithData: nil contentType: nil];
     3.9          }
    3.10      }@catch( NSException *x ) {
    3.11          MYReportException(x,@"Dispatching BLIP request");
     4.1 --- a/BLIP/BLIPDispatcher.h	Sat May 24 13:26:02 2008 -0700
     4.2 +++ b/BLIP/BLIPDispatcher.h	Sat May 24 17:25:06 2008 -0700
     4.3 @@ -10,19 +10,48 @@
     4.4  @class MYTarget, BLIPMessage;
     4.5  
     4.6  
     4.7 +/** Routes BLIP messages to targets based on a series of rule predicates.
     4.8 +    Every BLIPConnection has a BLIPDispatcher, which is initially empty but you can add rules
     4.9 +    to it.
    4.10 + 
    4.11 +    Every BLIPListener also has a dispatcher, which is inherited as the parent by every
    4.12 +    connection that it accepts, so you can add rules to the listener's dispatcher to share them
    4.13 +    between all connections.
    4.14 + 
    4.15 +    It's not necessary to use a dispatcher. Any undispatched requests will be sent to the
    4.16 +    BLIPConnection's delegate's -connection:receivedRequest: method, which can do its own
    4.17 +    custom handling. But it's often easier to use the dispatcher to associate handlers with
    4.18 +    request based on property values. */
    4.19  @interface BLIPDispatcher : NSObject 
    4.20  {
    4.21      NSMutableArray *_predicates, *_targets;
    4.22      BLIPDispatcher *_parent;
    4.23  }
    4.24  
    4.25 +/** The inherited parent dispatcher.
    4.26 +    If a message does not match any of this dispatcher's rules, it will next be passed to
    4.27 +    the parent, if there is one. */
    4.28  @property (retain) BLIPDispatcher *parent;
    4.29  
    4.30 +/** Adds a new rule, to call a given target method if a given predicate matches the message. */
    4.31  - (void) addTarget: (MYTarget*)target forPredicate: (NSPredicate*)predicate;
    4.32 +
    4.33 +/** Convenience method that adds a rule that compares a property against a string. */
    4.34 +- (void) addTarget: (MYTarget*)target forValueOfProperty: (NSString*)value forKey: (NSString*)key;
    4.35 +
    4.36 +/** Removes all rules with the given target method. */
    4.37  - (void) removeTarget: (MYTarget*)target;
    4.38  
    4.39 -- (void) addTarget: (MYTarget*)target forValueOfProperty: (NSString*)value forKey: (NSString*)key;
    4.40 -
    4.41 +/** Tests the message against all the rules, in the order they were added, and calls the
    4.42 +    target of the first matching rule.
    4.43 +    If no rule matches, the message is passed to the parent dispatcher's -dispatchMessage:,
    4.44 +    if there is a parent.
    4.45 +    If no rules at all match, NO is returned. */
    4.46  - (BOOL) dispatchMessage: (BLIPMessage*)message;
    4.47  
    4.48 +/** Returns a target object that will call this dispatcher's -dispatchMessage: method.
    4.49 +    This can be used to make this dispatcher the target of another dispatcher's rule,
    4.50 +    stringing them together hierarchically. */
    4.51 +- (MYTarget*) asTarget;
    4.52 +
    4.53  @end
     5.1 --- a/BLIP/BLIPDispatcher.m	Sat May 24 13:26:02 2008 -0700
     5.2 +++ b/BLIP/BLIPDispatcher.m	Sat May 24 17:25:06 2008 -0700
     5.3 @@ -84,6 +84,12 @@
     5.4  }
     5.5  
     5.6  
     5.7 +- (MYTarget*) asTarget;
     5.8 +{
     5.9 +    return $target(self,dispatchMessage:);
    5.10 +}
    5.11 +
    5.12 +
    5.13  @end
    5.14  
    5.15  
     6.1 --- a/BLIP/BLIPMessage.h	Sat May 24 13:26:02 2008 -0700
     6.2 +++ b/BLIP/BLIPMessage.h	Sat May 24 17:25:06 2008 -0700
     6.3 @@ -31,7 +31,7 @@
     6.4  };
     6.5  
     6.6  
     6.7 -/** Abstract superclass for both requests and responses. */
     6.8 +/** Abstract superclass for BLIP requests and responses. */
     6.9  @interface BLIPMessage : NSObject 
    6.10  {
    6.11      BLIPConnection *_connection;
    6.12 @@ -65,12 +65,12 @@
    6.13  /** Has the entire message, including the body, arrived? */
    6.14  @property (readonly) BOOL complete;
    6.15  
    6.16 -/** Should the message body be compressed using gzip?
    6.17 -    This property can only be set before sending the message. */
    6.18 +/** Should the message body be compressed with gzip?
    6.19 +    This property can only be set <i>before</i> sending the message. */
    6.20  @property BOOL compressed;
    6.21  
    6.22  /** Should the message be sent ahead of normal-priority messages?
    6.23 -    This property can only be set before sending the message. */
    6.24 +    This property can only be set <i>before</i> sending the message. */
    6.25  @property BOOL urgent;
    6.26  
    6.27  /** Can this message be changed? (Only true for outgoing messages, before you send them.) */
    6.28 @@ -84,7 +84,8 @@
    6.29  
    6.30  #pragma mark PROPERTIES:
    6.31  
    6.32 -/** The message's properties, a dictionary-like object. */
    6.33 +/** The message's properties, a dictionary-like object.
    6.34 +    Message properties are much like the headers in HTTP, MIME and RFC822. */
    6.35  @property (readonly) BLIPProperties* properties;
    6.36  
    6.37  /** Mutable version of the message's properties; only available if this mesage is mutable. */
     7.1 --- a/BLIP/BLIPProperties.m	Sat May 24 13:26:02 2008 -0700
     7.2 +++ b/BLIP/BLIPProperties.m	Sat May 24 17:25:06 2008 -0700
     7.3 @@ -20,7 +20,7 @@
     7.4      "Error-Code"
     7.5      "Error-Domain",
     7.6      "application/octet-stream",
     7.7 -    "text/plain",
     7.8 +    "text/plain; charset=UTF-8",
     7.9      "text/xml",
    7.10      "text/yaml",
    7.11      "application/x-cloudy-signed+yaml",
     8.1 --- a/BLIP/BLIPReader.m	Sat May 24 13:26:02 2008 -0700
     8.2 +++ b/BLIP/BLIPReader.m	Sat May 24 17:25:06 2008 -0700
     8.3 @@ -102,11 +102,9 @@
     8.4      SInt32 headerLeft = sizeof(BLIPFrameHeader) - _curBytesRead;
     8.5      if( headerLeft > 0 ) {
     8.6          // Read (more of) the header:
     8.7 -        NSInteger bytesRead = [(NSInputStream*)_stream read: (uint8_t*)&_curHeader +_curBytesRead
     8.8 -                                                  maxLength: headerLeft];
     8.9 -        if( bytesRead < 0 ) {
    8.10 -            [self _gotError];
    8.11 -        } else {
    8.12 +        NSInteger bytesRead = [self read: (uint8_t*)&_curHeader +_curBytesRead
    8.13 +                               maxLength: headerLeft];
    8.14 +        if( bytesRead > 0 ) {
    8.15              _curBytesRead += bytesRead;
    8.16              if( _curBytesRead < sizeof(BLIPFrameHeader) ) {
    8.17                  // Incomplete header:
    8.18 @@ -135,10 +133,8 @@
    8.19          if( bodyRemaining > 0 ) {
    8.20              uint8_t *dst = _curBody.mutableBytes;
    8.21              dst += _curBody.length - bodyRemaining;
    8.22 -            NSInteger bytesRead = [(NSInputStream*)_stream read: dst maxLength: bodyRemaining];
    8.23 -            if( bytesRead < 0 )
    8.24 -                return (void)[self _gotError];
    8.25 -            else if( bytesRead > 0 ) {
    8.26 +            NSInteger bytesRead = [self read: dst maxLength: bodyRemaining];
    8.27 +            if( bytesRead > 0 ) {
    8.28                  _curBytesRead += bytesRead;
    8.29                  bodyRemaining -= bytesRead;
    8.30                  LogTo(BLIPVerbose,@"%@: Read %u bytes of frame body (%u left)",self,bytesRead,bodyRemaining);
     9.1 --- a/BLIP/BLIPRequest.h	Sat May 24 13:26:02 2008 -0700
     9.2 +++ b/BLIP/BLIPRequest.h	Sat May 24 17:25:06 2008 -0700
     9.3 @@ -39,8 +39,8 @@
     9.4  
     9.5  /** Sends this request over its connection.
     9.6      (Actually, the connection queues it to be sent; this method always returns immediately.)
     9.7 -    If this request has not been assigned to a connection, an exception will be raised.
     9.8 -    Its matching response object will be returned, or nil if the request couldn't be sent. */
     9.9 +    Its matching response object will be returned, or nil if the request couldn't be sent.
    9.10 +    If this request has not been assigned to a connection, an exception will be raised. */
    9.11  - (BLIPResponse*) send;
    9.12  
    9.13  /** Does this request not need a response?
    9.14 @@ -58,8 +58,9 @@
    9.15      It will prevent a default empty response from being sent upon return from the request handler. */
    9.16  - (void) deferResponse;
    9.17  
    9.18 -/** Shortcut to respond to this request with the given data. */
    9.19 -- (void) respondWithData: (NSData*)data;
    9.20 +/** Shortcut to respond to this request with the given data.
    9.21 +    The contentType, if not nil, is stored in the "Content-Type" property. */
    9.22 +- (void) respondWithData: (NSData*)data contentType: (NSString*)contentType;
    9.23  
    9.24  /** Shortcut to respond to this request with the given string (which will be encoded in UTF-8). */
    9.25  - (void) respondWithString: (NSString*)string;
    10.1 --- a/BLIP/BLIPRequest.m	Sat May 24 13:26:02 2008 -0700
    10.2 +++ b/BLIP/BLIPRequest.m	Sat May 24 17:25:06 2008 -0700
    10.3 @@ -103,9 +103,25 @@
    10.4      return _response != nil;
    10.5  }
    10.6  
    10.7 -- (void) respondWithData: (NSData*)data                   {self.response.body = data; [self.response send];}
    10.8 -- (void) respondWithString: (NSString*)string             {[self respondWithData: [string dataUsingEncoding: NSUTF8StringEncoding]];}
    10.9 -- (void) respondWithError: (NSError*)error                {self.response.error = error; [self.response send];}
   10.10 +- (void) respondWithData: (NSData*)data contentType: (NSString*)contentType
   10.11 +{
   10.12 +    BLIPResponse *response = self.response;
   10.13 +    response.body = data;
   10.14 +    response.contentType = contentType;
   10.15 +    [response send];
   10.16 +}
   10.17 +
   10.18 +- (void) respondWithString: (NSString*)string
   10.19 +{
   10.20 +    [self respondWithData: [string dataUsingEncoding: NSUTF8StringEncoding]
   10.21 +              contentType: @"text/plain; charset=UTF-8"];
   10.22 +}
   10.23 +
   10.24 +- (void) respondWithError: (NSError*)error
   10.25 +{
   10.26 +    self.response.error = error; 
   10.27 +    [self.response send];
   10.28 +}
   10.29  
   10.30  - (void) respondWithErrorCode: (int)errorCode message: (NSString*)errorMessage
   10.31  {
    11.1 --- a/BLIP/BLIPTest.m	Sat May 24 13:26:02 2008 -0700
    11.2 +++ b/BLIP/BLIPTest.m	Sat May 24 17:25:06 2008 -0700
    11.3 @@ -162,7 +162,7 @@
    11.4  - (void) connection: (BLIPConnection*)connection receivedRequest: (BLIPRequest*)request
    11.5  {
    11.6      Log(@"***** %@ received %@",connection,request);
    11.7 -    [request respondWithData: request.body];
    11.8 +    [request respondWithData: request.body contentType: request.contentType];
    11.9  }
   11.10  
   11.11  - (void) connection: (BLIPConnection*)connection receivedResponse: (BLIPResponse*)response
   11.12 @@ -307,7 +307,7 @@
   11.13      AssertEqual([request valueOfProperty: @"User-Agent"], @"BLIPConnectionTester");
   11.14      AssertEq([[request valueOfProperty: @"Size"] intValue], size);
   11.15  
   11.16 -    [request respondWithData: body];
   11.17 +    [request respondWithData: body contentType: request.contentType];
   11.18  }
   11.19  
   11.20  
    12.1 --- a/IPAddress.h	Sat May 24 13:26:02 2008 -0700
    12.2 +++ b/IPAddress.h	Sat May 24 17:25:06 2008 -0700
    12.3 @@ -9,7 +9,7 @@
    12.4  #import <Foundation/Foundation.h>
    12.5  
    12.6  
    12.7 -/** Represents an Internet Protocol address and port number (similar to a sockaddr_in.)
    12.8 +/** Represents an Internet Protocol address and port number (similar to a sockaddr_in).
    12.9      IPAddress itself only remembers the raw 32-bit IPv4 address; the subclass HostAddress
   12.10      also remembers the DNS host-name. */
   12.11  @interface IPAddress : NSObject <NSCoding, NSCopying>
   12.12 @@ -35,7 +35,7 @@
   12.13  /** Initializes an IPAddress from a BSD struct sockaddr. */
   12.14  - (id) initWithSockAddr: (const struct sockaddr*)sockaddr;
   12.15  
   12.16 -/** Returns the IP address of this host (with a socket number of zero.)
   12.17 +/** Returns the IP address of this host (with a port number of zero).
   12.18      If multiple network interfaces are active, the main one's address is returned. */
   12.19  + (IPAddress*) localAddress;
   12.20  
    13.1 --- a/MYNetwork.xcodeproj/project.pbxproj	Sat May 24 13:26:02 2008 -0700
    13.2 +++ b/MYNetwork.xcodeproj/project.pbxproj	Sat May 24 17:25:06 2008 -0700
    13.3 @@ -93,6 +93,7 @@
    13.4  		270462C00DE4A639003D9D3F /* MYUtilities_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYUtilities_Prefix.pch; sourceTree = "<group>"; };
    13.5  		270462C10DE4A64B003D9D3F /* MYUtilitiesTest_main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYUtilitiesTest_main.m; sourceTree = "<group>"; };
    13.6  		270462C30DE4A65B003D9D3F /* BLIP Overview.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "BLIP Overview.txt"; path = "BLIP/BLIP Overview.txt"; sourceTree = "<group>"; wrapsLines = 1; };
    13.7 +		277903830DE8C2DD00C6D295 /* maindocs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = maindocs.h; sourceTree = "<group>"; wrapsLines = 1; };
    13.8  		27D5EC050DE5FEDE00CD84FA /* BLIPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLIPRequest.h; sourceTree = "<group>"; };
    13.9  		27D5EC060DE5FEDE00CD84FA /* BLIPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BLIPRequest.m; sourceTree = "<group>"; };
   13.10  /* End PBXFileReference section */
   13.11 @@ -115,6 +116,7 @@
   13.12  			isa = PBXGroup;
   13.13  			children = (
   13.14  				270462C30DE4A65B003D9D3F /* BLIP Overview.txt */,
   13.15 +				277903830DE8C2DD00C6D295 /* maindocs.h */,
   13.16  				270460F00DE49030003D9D3F /* MYNetwork */,
   13.17  				270461220DE49055003D9D3F /* MYUtilities */,
   13.18  				2704616D0DE492C9003D9D3F /* google-toolbox */,
    14.1 --- a/TCP/TCPConnection.h	Sat May 24 13:26:02 2008 -0700
    14.2 +++ b/TCP/TCPConnection.h	Sat May 24 17:25:06 2008 -0700
    14.3 @@ -23,7 +23,8 @@
    14.4  
    14.5  /** A generic class that manages a TCP socket connection.
    14.6      It creates a TCPReader and a TCPWriter to handle I/O.
    14.7 -    TCPConnection itself mostly deals with SSL setup and opening/closing the socket. */
    14.8 +    TCPConnection itself mostly deals with SSL setup and opening/closing the socket.
    14.9 +    (The SSL related methods are inherited from TCPEndpoint.) */
   14.10  @interface TCPConnection : TCPEndpoint
   14.11  {
   14.12      @private
   14.13 @@ -108,7 +109,8 @@
   14.14  
   14.15  
   14.16  
   14.17 -/** The delegate messages sent by TCPConnection. */
   14.18 +/** The delegate messages sent by TCPConnection.
   14.19 +    All methods are optional. */
   14.20  @protocol TCPConnectionDelegate <NSObject>
   14.21  @optional
   14.22  /** Called after the connection successfully opens. */
    15.1 --- a/TCP/TCPListener.h	Sat May 24 13:26:02 2008 -0700
    15.2 +++ b/TCP/TCPListener.h	Sat May 24 17:25:06 2008 -0700
    15.3 @@ -11,11 +11,17 @@
    15.4  
    15.5  
    15.6  /** Generic TCP-based server that listens for incoming connections on a port.
    15.7 +
    15.8      For each incoming connection, it creates an instance of (a subclass of) the generic TCP
    15.9      client class TCPClient. The -connectionClass property lets you customize which subclass
   15.10      to use.
   15.11 -    TCPListener supports Bonjour advertisements for the service, and automatic port renumbering
   15.12 -    if there are conflicts. */
   15.13 + 
   15.14 +    TCPListener supports SSL, Bonjour advertisements for the service, and automatic port renumbering
   15.15 +    if there are conflicts. (The SSL related methods are inherited from TCPEndpoint.) 
   15.16 + 
   15.17 +    You will almost always need to implement the TCPListenerDelegate protocol in your own
   15.18 +    code, and set an instance as the listener's delegate property, in order to be informed
   15.19 +    of important events such as incoming connections. */
   15.20  @interface TCPListener : TCPEndpoint 
   15.21  {
   15.22      @private
   15.23 @@ -40,6 +46,8 @@
   15.24  /** The subclass of TCPConnection that will be instantiated. */
   15.25  @property Class connectionClass;
   15.26  
   15.27 +/** Delegate object that will be called when interesting things happen to the listener --
   15.28 +    most importantly, when a new incoming connection is accepted. */
   15.29  @property (assign) id<TCPListenerDelegate> delegate;
   15.30  
   15.31  /** Should the server listen for IPv6 connections (on the same port number)? Defaults to NO. */
   15.32 @@ -58,6 +66,9 @@
   15.33      changes are ignored while the server is open.) */
   15.34  - (BOOL) open: (NSError **)error;
   15.35  
   15.36 +/** Opens the server, without returning a specific error code.
   15.37 +    (In case of error the delegate's -listener:failedToOpen: method will be called with the
   15.38 +    error code, anyway.) */
   15.39  - (BOOL) open;
   15.40  
   15.41  /** Closes the server. */
   15.42 @@ -94,14 +105,30 @@
   15.43  
   15.44  #pragma mark -
   15.45  
   15.46 -/** The delegate messages sent by TCPListener. */
   15.47 +/** The delegate messages sent by TCPListener.
   15.48 +    All are optional except -listener:didAcceptConnection:. */
   15.49  @protocol TCPListenerDelegate <NSObject>
   15.50  
   15.51 +/** Called after an incoming connection arrives and is opened;
   15.52 +    the connection is now ready to send and receive data.
   15.53 +    To control whether or not a connection should be accepted, implement the
   15.54 +    -listener:shouldAcceptConnectionFrom: method.
   15.55 +    To use a different class than TCPConnection, set the listener's -connectionClass property.
   15.56 +    (This is the only required delegate method; the others are optional to implement.) */
   15.57  - (void) listener: (TCPListener*)listener didAcceptConnection: (TCPConnection*)connection;
   15.58  
   15.59  @optional
   15.60 +/** Called after the listener successfully opens. */
   15.61  - (void) listenerDidOpen: (TCPListener*)listener;
   15.62 +/** Called if the listener fails to open due to an error. */
   15.63  - (void) listener: (TCPListener*)listener failedToOpen: (NSError*)error;
   15.64 +/** Called after the listener closes. */
   15.65  - (void) listenerDidClose: (TCPListener*)listener;
   15.66 +/** Called when an incoming connection request arrives, but before the conncetion is opened;
   15.67 +    return YES to accept the connection, NO to refuse it.
   15.68 +    This method can only use criteria like the peer IP address, or the number of currently
   15.69 +    open connections, to determine whether to accept. If you also want to check the
   15.70 +    peer's SSL certificate, then return YES from this method, and use the TCPConnection
   15.71 +    delegate method -connection:authorizeSSLPeer: to examine the certificate. */
   15.72  - (BOOL) listener: (TCPListener*)listener shouldAcceptConnectionFrom: (IPAddress*)address;
   15.73  @end
    16.1 --- a/TCP/TCPStream.h	Sat May 24 13:26:02 2008 -0700
    16.2 +++ b/TCP/TCPStream.h	Sat May 24 17:25:06 2008 -0700
    16.3 @@ -10,7 +10,7 @@
    16.4  @class TCPConnection, TCPWriter;
    16.5  
    16.6  
    16.7 -/** INTERNAL abstract superclass for data streams, used by TCPConnection. */
    16.8 +/** Abstract superclass for data streams, used by TCPConnection. */
    16.9  @interface TCPStream : NSObject 
   16.10  {
   16.11      TCPConnection *_conn;
   16.12 @@ -55,8 +55,15 @@
   16.13  
   16.14  /** Input stream for a TCPConnection. */
   16.15  @interface TCPReader : TCPStream
   16.16 +
   16.17  /** The connection's TCPWriter. */
   16.18  @property (readonly) TCPWriter *writer;
   16.19 +
   16.20 +/** Reads bytes from the stream, like the corresponding method of NSInputStream.
   16.21 +    The number of bytes actually read is returned, or zero if no data is available.
   16.22 +    If an error occurs, it will call its -_gotError method, and return a negative number. */
   16.23 +- (NSInteger) read: (void*)dst maxLength: (NSUInteger)maxLength;
   16.24 +
   16.25  @end
   16.26  
   16.27  
    17.1 --- a/TCP/TCPStream.m	Sat May 24 13:26:02 2008 -0700
    17.2 +++ b/TCP/TCPStream.m	Sat May 24 17:25:06 2008 -0700
    17.3 @@ -239,6 +239,15 @@
    17.4  }
    17.5  
    17.6  
    17.7 +- (NSInteger) read: (void*)dst maxLength: (NSUInteger)maxLength
    17.8 +{
    17.9 +    NSInteger bytesRead = [(NSInputStream*)_stream read:dst maxLength: maxLength];
   17.10 +    if( bytesRead < 0 )
   17.11 +        [self _gotError];
   17.12 +    return bytesRead;
   17.13 +}
   17.14 +
   17.15 +
   17.16  @end
   17.17  
   17.18  
    18.1 --- a/TCP/TCPWriter.h	Sat May 24 13:26:02 2008 -0700
    18.2 +++ b/TCP/TCPWriter.h	Sat May 24 17:25:06 2008 -0700
    18.3 @@ -9,7 +9,7 @@
    18.4  #import "TCPStream.h"
    18.5  
    18.6  
    18.7 -/** INTERNAL class that writes a queue of arbitrary data blobs to the socket. */
    18.8 +/** Output stream for a TCPConnection. Writes a queue of arbitrary data blobs to the socket. */
    18.9  @interface TCPWriter : TCPStream 
   18.10  {
   18.11      NSMutableArray *_queue;
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/maindocs.h	Sat May 24 17:25:06 2008 -0700
    19.3 @@ -0,0 +1,53 @@
    19.4 +//
    19.5 +//  maindocs.h
    19.6 +//  MYNetwork
    19.7 +//
    19.8 +//  Created by Jens Alfke on 5/24/08.
    19.9 +//  Copyright 2008 Jens Alfke. All rights reserved.
   19.10 +//
   19.11 +// This file just contains the Doxygen comments that generate the main (index.html) page content.
   19.12 +
   19.13 +
   19.14 +/*! \mainpage MYNetwork: Mooseyard Networking library, including BLIP protocol implementation. 
   19.15 + 
   19.16 +    \section intro_sec Introduction
   19.17 + 
   19.18 +    MYNetwork is a set of Objective-C networking classes for Cocoa applications on Mac OS X.
   19.19 +    It consists of:
   19.20 +    <ul>
   19.21 +    <li>Networking utility classes (presently only IPAddress);
   19.22 +    <li>A generic TCP client/server implementation,
   19.23 +        useful for implementing your own network protocols; (see TCPListener and TCPConnection)
   19.24 +    <li>An implementation of BLIP, a lightweight network protocol I've invented as an easy way
   19.25 +        to send request and response messages between peers. (see BLIPListener, BLIPConnection, BLIPRequest, etc.)
   19.26 +    </ul>
   19.27 + 
   19.28 +    MYNetwork is released under a BSD license, which means you can freely use it in open-source
   19.29 +    or commercial projects, provided you give credit in your documentation or About box.
   19.30 + 
   19.31 +    \section config Configuration
   19.32 + 
   19.33 +    MYNetwork requires Mac OS X 10.5 or later, since it uses Objective-C 2 features like
   19.34 +    properties and for...in loops.
   19.35 + 
   19.36 +    MYNetwork uses my <a href="/hg/hgwebdir.cgi/MYUtilities">MYUtilities</a> library. You'll need to have downloaded that library, and added
   19.37 +    the necessary source files and headers to your project. See the MYNetwork Xcode project,
   19.38 +    which contains the minimal set of MYUtilities files needed to build MYUtilities. (That project
   19.39 +    has its search paths set up to assume that MYUtilities is in a directory next to MYNetwork.)
   19.40 +
   19.41 +    \section download How To Get It
   19.42 +
   19.43 +    <ul>
   19.44 +    <li><a href="http://mooseyard.com/hg/hgwebdir.cgi/MYNetwork/archive/tip.zip">Download the current source code</a>
   19.45 +    <li>To check out the source code using <a href="http://selenic.com/mercurial">Mercurial</a>:
   19.46 +    \verbatim hg clone http://mooseyard.com/hg/hgwebdir.cgi/MYNetwork/ MYNetwork \endverbatim
   19.47 +    </ul>
   19.48 +
   19.49 +    Or if you're just looking:
   19.50 +
   19.51 +    <ul>
   19.52 +    <li><a href="http://mooseyard.com/hg/hgwebdir.cgi/MYNetwork/file/tip">Browse the source code</a>
   19.53 +    <li><a href="annotated.html">Browse the class documentation</a>
   19.54 +    </ul>
   19.55 + 
   19.56 + */