jens@0: // jens@0: // TCPConnection.h jens@0: // MYNetwork jens@0: // jens@0: // Created by Jens Alfke on 5/18/08. jens@0: // Copyright 2008 Jens Alfke. All rights reserved. jens@0: // jens@0: jens@0: #import "TCPEndpoint.h" jens@0: @class IPAddress; jens@0: @class TCPReader, TCPWriter, TCPListener; jens@0: @protocol TCPConnectionDelegate; jens@0: jens@0: jens@0: typedef enum { jens@0: kTCP_Disconnected = -1, jens@0: kTCP_Closed, jens@0: kTCP_Opening, jens@0: kTCP_Open, jens@0: kTCP_Closing jens@0: } TCPConnectionStatus; jens@0: jens@0: jens@0: /** A generic class that manages a TCP socket connection. jens@0: It creates a TCPReader and a TCPWriter to handle I/O. jens@2: TCPConnection itself mostly deals with SSL setup and opening/closing the socket. jens@2: (The SSL related methods are inherited from TCPEndpoint.) */ jens@0: @interface TCPConnection : TCPEndpoint jens@0: { jens@0: @private jens@0: TCPListener *_server; jens@0: IPAddress *_address; jens@0: BOOL _isIncoming, _checkedPeerCert; jens@0: TCPConnectionStatus _status; jens@0: TCPReader *_reader; jens@0: TCPWriter *_writer; jens@0: NSError *_error; jens@0: } jens@0: jens@0: /** Initializes a TCPConnection to the given IP address. jens@0: Afer configuring settings, you should call -open to begin the connection. */ jens@0: - (id) initToAddress: (IPAddress*)address; jens@0: jens@0: /** Initializes a TCPConnection to the given IP address, binding to a specific outgoing port jens@0: number. (This is usually only necessary when attempting to tunnel through a NAT.) */ jens@0: - (id) initToAddress: (IPAddress*)address jens@0: localPort: (UInt16)localPort; jens@0: jens@7: /** Initializes a TCPConnection to the given NSNetService's address and port. jens@7: If the service's address cannot be resolved, nil is returned. */ jens@7: - (id) initToNetService: (NSNetService*)service; jens@7: jens@0: /** Initializes a TCPConnection from an incoming TCP socket. jens@0: You don't usually need to call this; TCPListener does it automatically. */ jens@0: - (id) initIncomingFromSocket: (CFSocketNativeHandle)socket listener: (TCPListener*)listener; jens@0: jens@0: /** The delegate object that will be called when the connection opens, closes or receives messages. */ jens@0: @property (assign) id delegate; jens@0: jens@0: /** The certificate(s) of the connected peer, if this connection uses SSL. jens@0: The items in the array are SecCertificateRefs; use the Keychain API to work with them. */ jens@0: @property (readonly) NSArray *peerSSLCerts; jens@0: jens@0: /** Connection's current status */ jens@0: @property (readonly) TCPConnectionStatus status; jens@0: jens@0: /** Opens the connection. This happens asynchronously; wait for a delegate method to be called. jens@0: You don't need to open incoming connections received via a TCPListener. */ jens@0: - (void) open; jens@0: jens@0: /** Closes the connection, after waiting for all in-progress messages to be sent or received. jens@0: This happens asynchronously; wait for a delegate method to be called.*/ jens@0: - (void) close; jens@0: jens@0: /** Closes the connection, like -close, but if it hasn't closed by the time the timeout jens@0: expires, it will disconnect the socket. */ jens@0: - (void) closeWithTimeout: (NSTimeInterval)timeout; jens@0: jens@0: /** Closes all open TCPConnections. */ jens@0: + (void) closeAllWithTimeout: (NSTimeInterval)timeout; jens@0: jens@0: /** Blocks until all open TCPConnections close. You should call +closeAllWithTimeout: first. */ jens@0: + (void) waitTillAllClosed; jens@0: jens@0: /** The IP address of the other peer. */ jens@7: @property (readonly,retain) IPAddress *address; jens@0: jens@0: /** The TCPListener that created this incoming connection, or nil */ jens@0: @property (readonly) TCPListener *server; jens@0: jens@0: /** Is this an incoming connection, received via a TCPListener? */ jens@0: @property (readonly) BOOL isIncoming; jens@0: jens@0: /** The fatal error, if any, jens@0: that caused the connection to fail to open or to disconnect unexpectedly. */ jens@0: @property (readonly) NSError *error; jens@0: jens@0: /** The actual security level of this connection. jens@0: Value is nil or one of the security level constants from NSStream.h, jens@0: such as NSStreamSocketSecurityLevelTLSv1. */ jens@0: @property (readonly) NSString* actualSecurityLevel; jens@0: jens@0: jens@0: @property (readonly) TCPReader *reader; jens@0: @property (readonly) TCPWriter *writer; jens@0: jens@0: jens@0: // protected: jens@0: - (Class) readerClass; jens@0: - (Class) writerClass; jens@0: jens@0: @end jens@0: jens@0: jens@0: jens@2: /** The delegate messages sent by TCPConnection. jens@2: All methods are optional. */ jens@0: @protocol TCPConnectionDelegate jens@0: @optional jens@0: /** Called after the connection successfully opens. */ jens@0: - (void) connectionDidOpen: (TCPConnection*)connection; jens@0: /** Called after the connection fails to open due to an error. */ jens@0: - (void) connection: (TCPConnection*)connection failedToOpen: (NSError*)error; jens@0: /** Called when the identity of the peer is known, if using an SSL connection and the SSL jens@0: settings say to check the peer's certificate. jens@0: This happens, if at all, after the -connectionDidOpen: call. */ jens@0: - (BOOL) connection: (TCPConnection*)connection authorizeSSLPeer: (SecCertificateRef)peerCert; jens@0: /** Called after the connection closes. */ jens@0: - (void) connectionDidClose: (TCPConnection*)connection; jens@0: @end