TCP/TCPListener.h
author Jens Alfke <jens@mooseyard.com>
Fri Jul 24 14:06:28 2009 -0700 (2009-07-24)
changeset 63 5e4855a592ee
parent 22 8b883753394a
permissions -rwxr-xr-x
* The BLIPConnection receivedRequest: delegate method now returns BOOL. If the method returns NO (or if the method isn't implemented in the delegate), that means it didn't handle the message at all; an error will be returned to the sender.
* If the connection closes unexpectedly due to an error, then the auto-generated responses to pending requests will contain that error. This makes it easier to display a meaningful error message in the handler for the request.
     1 //
     2 //  TCPListener.m
     3 //  MYNetwork
     4 //
     5 //  Created by Jens Alfke on 5/10/08.
     6 //  Copyright 2008 Jens Alfke. All rights reserved.
     7 
     8 #import "TCPEndpoint.h"
     9 @class TCPConnection, IPAddress;
    10 @protocol TCPListenerDelegate;
    11 
    12 
    13 /** Generic TCP-based server that listens for incoming connections on a port.
    14 
    15     For each incoming connection, it creates an instance of (a subclass of) the generic TCP
    16     client class TCPClient. The -connectionClass property lets you customize which subclass
    17     to use.
    18  
    19     TCPListener supports SSL, Bonjour advertisements for the service, and automatic port renumbering
    20     if there are conflicts. (The SSL related methods are inherited from TCPEndpoint.) 
    21  
    22     You will almost always need to implement the TCPListenerDelegate protocol in your own
    23     code, and set an instance as the listener's delegate property, in order to be informed
    24     of important events such as incoming connections. */
    25 @interface TCPListener : TCPEndpoint 
    26 {
    27     @private
    28     uint16_t _port;
    29     BOOL _pickAvailablePort;
    30     BOOL _useIPv6;
    31     CFSocketRef _ipv4socket;
    32     CFSocketRef _ipv6socket;
    33     
    34     NSString *_bonjourServiceType, *_bonjourServiceName;
    35     NSNetServiceOptions _bonjourServiceOptions;
    36     NSNetService *_netService;
    37     NSDictionary *_bonjourTXTRecord;
    38     BOOL _bonjourPublished;
    39     NSInteger /*NSNetServicesError*/ _bonjourError;
    40 
    41     Class _connectionClass;
    42 }
    43 
    44 /** Initializes a new TCPListener that will listen on the given port when opened. */
    45 - (id) initWithPort: (UInt16)port;
    46 
    47 /** The subclass of TCPConnection that will be instantiated. */
    48 @property Class connectionClass;
    49 
    50 /** Delegate object that will be called when interesting things happen to the listener --
    51     most importantly, when a new incoming connection is accepted. */
    52 @property (assign) id<TCPListenerDelegate> delegate;
    53 
    54 /** Should the server listen for IPv6 connections (on the same port number)? Defaults to NO. */
    55 @property BOOL useIPv6;
    56 
    57 /** The port number to listen on.
    58     If the pickAvailablePort property is enabled, this value may be updated after the server opens
    59     to reflect the actual port number being used. */
    60 @property uint16_t port;
    61 
    62 /** Should the server pick a higher port number if the desired port is already in use?
    63     Defaults to NO. If enabled, the port number will be incremented until a free port is found. */
    64 @property BOOL pickAvailablePort;
    65 
    66 /** Opens the server. You must call this after configuring all desired properties (property
    67     changes are ignored while the server is open.) */
    68 - (BOOL) open: (NSError **)error;
    69 
    70 /** Opens the server, without returning a specific error code.
    71     (In case of error the delegate's -listener:failedToOpen: method will be called with the
    72     error code, anyway.) */
    73 - (BOOL) open;
    74 
    75 /** Closes the server. */
    76 - (void) close;
    77 
    78 /** Is the server currently open? */
    79 @property (readonly) BOOL isOpen;
    80 
    81 
    82 #pragma mark BONJOUR:
    83 
    84 /** The Bonjour service type to advertise. Defaults to nil; setting it implicitly enables Bonjour.
    85     The value should look like e.g. "_http._tcp."; for details, see the NSNetService documentation. */
    86 @property (copy) NSString *bonjourServiceType;
    87 
    88 /** The Bonjour service name to advertise. Defaults to nil, meaning that a default name will be
    89     automatically generated if Bonjour is enabled (by setting -bonjourServiceType). */
    90 @property (copy) NSString *bonjourServiceName;
    91 
    92 /** Options to use when publishing the Bonjour service. */
    93 @property NSNetServiceOptions bonjourServiceOptions;
    94 
    95 /** The dictionary form of the Bonjour TXT record: metadata about the service that can be browsed
    96     by peers. Changes to this dictionary will be pushed in near-real-time to interested peers. */
    97 @property (copy) NSDictionary *bonjourTXTRecord;
    98 
    99 /** Is this service currently published/advertised via Bonjour? */
   100 @property (readonly) BOOL bonjourPublished;
   101 
   102 /** Current error status of Bonjour service advertising. See NSNetServicesError for error codes. */
   103 @property (readonly) NSInteger /*NSNetServicesError*/ bonjourError;
   104 
   105 /** The NSNetService being published. */
   106 @property (readonly) NSNetService* bonjourService;
   107 
   108 
   109 @end
   110 
   111 
   112 
   113 #pragma mark -
   114 
   115 /** The delegate messages sent by TCPListener.
   116     All are optional except -listener:didAcceptConnection:. */
   117 @protocol TCPListenerDelegate <NSObject>
   118 
   119 /** Called after an incoming connection arrives and is opened;
   120     the connection is now ready to send and receive data.
   121     To control whether or not a connection should be accepted, implement the
   122     -listener:shouldAcceptConnectionFrom: method.
   123     To use a different class than TCPConnection, set the listener's -connectionClass property.
   124     (This is the only required delegate method; the others are optional to implement.) */
   125 - (void) listener: (TCPListener*)listener didAcceptConnection: (TCPConnection*)connection;
   126 
   127 @optional
   128 /** Called after the listener successfully opens. */
   129 - (void) listenerDidOpen: (TCPListener*)listener;
   130 /** Called if the listener fails to open due to an error. */
   131 - (void) listener: (TCPListener*)listener failedToOpen: (NSError*)error;
   132 /** Called after the listener closes. */
   133 - (void) listenerDidClose: (TCPListener*)listener;
   134 /** Called when an incoming connection request arrives, but before the conncetion is opened;
   135     return YES to accept the connection, NO to refuse it.
   136     This method can only use criteria like the peer IP address, or the number of currently
   137     open connections, to determine whether to accept. If you also want to check the
   138     peer's SSL certificate, then return YES from this method, and use the TCPConnection
   139     delegate method -connection:authorizeSSLPeer: to examine the certificate. */
   140 - (BOOL) listener: (TCPListener*)listener shouldAcceptConnectionFrom: (IPAddress*)address;
   141 @end