//
// GCDAsyncSocket.h
//
// This class is in the public domain.
// Originally created by Robbie Hanson in Q3 2010.
// Updated and maintained by Deusty LLC and the Apple development community.
//
// https://github.com/robbiehanson/CocoaAsyncSocket
//
#import <Foundation/Foundation.h>
#import <Security/Security.h>
#import <Security/SecureTransport.h>
#import <dispatch/dispatch.h>
#import <Availability.h>
#include <sys/socket.h> // AF_INET, AF_INET6
@class GCDAsyncReadPacket;
@class GCDAsyncWritePacket;
@class GCDAsyncSocketPreBuffer;
extern NSString *const GCDAsyncSocketException;
extern NSString *const GCDAsyncSocketErrorDomain;
extern NSString *const GCDAsyncSocketQueueName;
extern NSString *const GCDAsyncSocketThreadName;
extern NSString *const GCDAsyncSocketManuallyEvaluateTrust;
#if TARGET_OS_IPHONE
extern NSString *const GCDAsyncSocketUseCFStreamForTLS;
#endif
#define GCDAsyncSocketSSLPeerName (NSString *)kCFStreamSSLPeerName
#define GCDAsyncSocketSSLCertificates (NSString *)kCFStreamSSLCertificates
#define GCDAsyncSocketSSLIsServer (NSString *)kCFStreamSSLIsServer
extern NSString *const GCDAsyncSocketSSLPeerID;
extern NSString *const GCDAsyncSocketSSLProtocolVersionMin;
extern NSString *const GCDAsyncSocketSSLProtocolVersionMax;
extern NSString *const GCDAsyncSocketSSLSessionOptionFalseStart;
extern NSString *const GCDAsyncSocketSSLSessionOptionSendOneByteRecord;
extern NSString *const GCDAsyncSocketSSLCipherSuites;
#if !TARGET_OS_IPHONE
extern NSString *const GCDAsyncSocketSSLDiffieHellmanParameters;
#endif
#define GCDAsyncSocketLoggingContext 65535
enum GCDAsyncSocketError
{
GCDAsyncSocketNoError = 0, // Never used
GCDAsyncSocketBadConfigError, // Invalid configuration
GCDAsyncSocketBadParamError, // Invalid parameter was passed
GCDAsyncSocketConnectTimeoutError, // A connect operation timed out
GCDAsyncSocketReadTimeoutError, // A read operation timed out
GCDAsyncSocketWriteTimeoutError, // A write operation timed out
GCDAsyncSocketReadMaxedOutError, // Reached set maxLength without completing
GCDAsyncSocketClosedError, // The remote peer closed the connection
GCDAsyncSocketOtherError, // Description provided in userInfo
};
typedef enum GCDAsyncSocketError GCDAsyncSocketError;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@interface GCDAsyncSocket : NSObject
/**
* GCDAsyncSocket uses the standard delegate paradigm,
* but executes all delegate callbacks on a given delegate dispatch queue.
* This allows for maximum concurrency, while at the same time providing easy thread safety.
*
* You MUST set a delegate AND delegate dispatch queue before attempting to
* use the socket, or you will get an error.
*
* The socket queue is optional.
* If you pass NULL, GCDAsyncSocket will automatically create it's own socket queue.
* If you choose to provide a socket queue, the socket queue must not be a concurrent queue.
* If you choose to provide a socket queue, and the socket queue has a configured target queue,
* then please see the discussion for the method markSocketQueueTargetQueue.
*
* The delegate queue and socket queue can optionally be the same.
**/
- (id)init;
- (id)initWithSocketQueue:(dispatch_queue_t)sq;
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq;
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq;
#pragma mark Configuration
@property (atomic, weak, readwrite) id delegate;
#if OS_OBJECT_USE_OBJC
@property (atomic, strong, readwrite) dispatch_queue_t delegateQueue;
#else
@property (atomic, assign, readwrite) dispatch_queue_t delegateQueue;
#endif
- (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr;
- (void)setDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
/**
* If you are setting the delegate to nil within the delegate's dealloc method,
* you may need to use the synchronous versions below.
**/
- (void)synchronouslySetDelegate:(id)delegate;
- (void)synchronouslySetDelegateQueue:(dispatch_queue_t)delegateQueue;
- (void)synchronouslySetDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
/**
* By default, both IPv4 and IPv6 are enabled.
*
* For accepting incoming connections, this means GCDAsyncSocket automatically supports both protocols,
* and can simulataneously accept incoming connections on either protocol.
*
* For outgoing connections, this means GCDAsyncSocket can connect to remote hosts running either protocol.
* If a DNS lookup returns only IPv4 results, GCDAsyncSocket will automatically use IPv4.
* If a DNS lookup returns only IPv6 results, GCDAsyncSocket will automatically use IPv6.
* If a DNS lookup returns both IPv4 and IPv6 results, the preferred protocol will be chosen.
* By default, the preferred protocol is IPv4, but may be configured as desired.
**/
@property (atomic, assign, readwrite, getter=isIPv4Enabled) BOOL IPv4Enabled;
@property (atomic, assign, readwrite, getter=isIPv6Enabled) BOOL IPv6Enabled;
@property (atomic, assign, readwrite, getter=isIPv4PreferredOverIPv6) BOOL IPv4PreferredOverIPv6;
/**
* User data allows you to associate arbitrary information with the socket.
* This data is not used internally by socket in any way.
**/
@property (atomic, strong, readwrite) id userData;
#pragma mark Accepting
/**
* Tells the socket to begin listening and accepting connections on the given port.
* When a connection is accepted, a new instance of GCDAsyncSocket will be spawned to handle it,
* and the socket:didAcceptNewSocket: delegate method will be invoked.
*
* The socket will listen on all available interfaces (e.g. wifi, ethernet, etc)
**/
- (BOOL)acceptOnPort:(uint16_t)port error:(NSError **)errPtr;
/**
* This method is the same as acceptOnPort:error: with the
* additional option of specifying which interface to listen on.
*
* For example, you could specify that the socket should only accept connections over ethernet,
* and not other interfaces such as wifi.
*
* The interface may be specified by name (e.g. "en1" or "lo0") or by IP address (e.g. "192.168.4.34").
* You may also use the special strings "localhost" or "loopback" to specify that
* the socket only accept connections from the local machine.
*
* You can see the list of interfaces via the command line utility "ifconfig",
* or programmatically via the getifaddrs() function.
*
* To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method.
**/
- (BOOL)acceptOnInterface:(NSString *)interface port:(uint16_t)port error:(NSError **)errPtr;
#pragma mark Connecting
/**
* Connects to the given host and port.
*
* This method invokes connectToHost:onPort:viaInterface:withTimeout:error:
* and uses the default interface, and no timeout.
**/
- (BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port error:(NSError **)errPtr;
/**
* Connects to the given host and port with an optional timeout.
*
* This method invokes connectToHost:onPort:viaInterface:withTimeout:error: and uses the default interface.
**/
- (BOOL)connectToHost:(NSString *)host
onPort:(uint16_t)port
withTimeout:(NSTimeInterval)timeout
error:(NSError **)errPtr;
/**
* Connects to the given host & port, via the optional interface, with an optional timeout.
*
* The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2").
* The host may also be the special strings "localhost" or "loopback" to specify connecting
* to a service on the local machine.
*
* The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35").
* The interfac