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