Subversion Repositories Mobile Apps.GyroMouse

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //  
  2. //  GCDAsyncUdpSocket
  3. //  
  4. //  This class is in the public domain.
  5. //  Originally created by Robbie Hanson of Deusty LLC.
  6. //  Updated and maintained by Deusty LLC and the Apple development community.
  7. //  
  8. //  https://github.com/robbiehanson/CocoaAsyncSocket
  9. //
  10.  
  11. #import <Foundation/Foundation.h>
  12. #import <dispatch/dispatch.h>
  13. #import <TargetConditionals.h>
  14. #import <Availability.h>
  15.  
  16. NS_ASSUME_NONNULL_BEGIN
  17. extern NSString *const GCDAsyncUdpSocketException;
  18. extern NSString *const GCDAsyncUdpSocketErrorDomain;
  19.  
  20. extern NSString *const GCDAsyncUdpSocketQueueName;
  21. extern NSString *const GCDAsyncUdpSocketThreadName;
  22.  
  23. typedef NS_ERROR_ENUM(GCDAsyncUdpSocketErrorDomain, GCDAsyncUdpSocketError) {
  24.         GCDAsyncUdpSocketNoError = 0,          // Never used
  25.         GCDAsyncUdpSocketBadConfigError,       // Invalid configuration
  26.         GCDAsyncUdpSocketBadParamError,        // Invalid parameter was passed
  27.         GCDAsyncUdpSocketSendTimeoutError,     // A send operation timed out
  28.         GCDAsyncUdpSocketClosedError,          // The socket was closed
  29.         GCDAsyncUdpSocketOtherError,           // Description provided in userInfo
  30. };
  31.  
  32. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  33. #pragma mark -
  34. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  35.  
  36. @class GCDAsyncUdpSocket;
  37.  
  38. @protocol GCDAsyncUdpSocketDelegate <NSObject>
  39. @optional
  40.  
  41. /**
  42.  * By design, UDP is a connectionless protocol, and connecting is not needed.
  43.  * However, you may optionally choose to connect to a particular host for reasons
  44.  * outlined in the documentation for the various connect methods listed above.
  45.  *
  46.  * This method is called if one of the connect methods are invoked, and the connection is successful.
  47. **/
  48. - (void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address;
  49.  
  50. /**
  51.  * By design, UDP is a connectionless protocol, and connecting is not needed.
  52.  * However, you may optionally choose to connect to a particular host for reasons
  53.  * outlined in the documentation for the various connect methods listed above.
  54.  *
  55.  * This method is called if one of the connect methods are invoked, and the connection fails.
  56.  * This may happen, for example, if a domain name is given for the host and the domain name is unable to be resolved.
  57. **/
  58. - (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotConnect:(NSError * _Nullable)error;
  59.  
  60. /**
  61.  * Called when the datagram with the given tag has been sent.
  62. **/
  63. - (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag;
  64.  
  65. /**
  66.  * Called if an error occurs while trying to send a datagram.
  67.  * This could be due to a timeout, or something more serious such as the data being too large to fit in a sigle packet.
  68. **/
  69. - (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError * _Nullable)error;
  70.  
  71. /**
  72.  * Called when the socket has received the requested datagram.
  73. **/
  74. - (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
  75.                                              fromAddress:(NSData *)address
  76.                                        withFilterContext:(nullable id)filterContext;
  77.  
  78. /**
  79.  * Called when the socket is closed.
  80. **/
  81. - (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError  * _Nullable)error;
  82.  
  83. @end
  84.  
  85. /**
  86.  * You may optionally set a receive filter for the socket.
  87.  * A filter can provide several useful features:
  88.  *    
  89.  * 1. Many times udp packets need to be parsed.
  90.  *    Since the filter can run in its own independent queue, you can parallelize this parsing quite easily.
  91.  *    The end result is a parallel socket io, datagram parsing, and packet processing.
  92.  *
  93.  * 2. Many times udp packets are discarded because they are duplicate/unneeded/unsolicited.
  94.  *    The filter can prevent such packets from arriving at the delegate.
  95.  *    And because the filter can run in its own independent queue, this doesn't slow down the delegate.
  96.  *
  97.  *    - Since the udp protocol does not guarantee delivery, udp packets may be lost.
  98.  *      Many protocols built atop udp thus provide various resend/re-request algorithms.
  99.  *      This sometimes results in duplicate packets arriving.
  100.  *      A filter may allow you to architect the duplicate detection code to run in parallel to normal processing.
  101.  *    
  102.  *    - Since the udp socket may be connectionless, its possible for unsolicited packets to arrive.
  103.  *      Such packets need to be ignored.
  104.  *
  105.  * 3. Sometimes traffic shapers are needed to simulate real world environments.
  106.  *    A filter allows you to write custom code to simulate such environments.
  107.  *    The ability to code this yourself is especially helpful when your simulated environment
  108.  *    is more complicated than simple traffic shaping (e.g. simulating a cone port restricted router),
  109.  *    or the system tools to handle this aren't available (e.g. on a mobile device).
  110.  *
  111.  * @param data    - The packet that was received.
  112.  * @param address - The address the data was received from.
  113.  *                  See utilities section for methods to extract info from address.
  114.  * @param context - Out parameter you may optionally set, which will then be passed to the delegate method.
  115.  *                  For example, filter block can parse the data and then,
  116.  *                  pass the parsed data to the delegate.
  117.  *
  118.  * @returns - YES if the received packet should be passed onto the delegate.
  119.  *            NO if the received packet should be discarded, and not reported to the delegete.
  120.  *
  121.  * Example:
  122.  *
  123.  * GCDAsyncUdpSocketReceiveFilterBlock filter = ^BOOL (NSData *data, NSData *address, id *context) {
  124.  *
  125.  *     MyProtocolMessage *msg = [MyProtocol parseMessage:data];
  126.  *    
  127.  *     *context = response;
  128.  *     return (response != nil);
  129.  * };
  130.  * [udpSocket setReceiveFilter:filter withQueue:myParsingQueue];
  131.  *
  132. **/
  133. typedef BOOL (^GCDAsyncUdpSocketReceiveFilterBlock)(NSData *data, NSData *address, id __nullable * __nonnull context);
  134.  
  135. /**
  136.  * You may optionally set a send filter for the socket.
  137.  * A filter can provide several interesting possibilities:
  138.  *
  139.  * 1. Optional caching of resolved addresses for domain names.
  140.  *    The cache could later be consulted, resulting in fewer system calls to getaddrinfo.
  141.  *
  142.  * 2. Reusable modules of code for bandwidth monitoring.
  143.  *
  144.  * 3. Sometimes traffic shapers are needed to simulate real world environments.
  145.  *    A filter allows you to write custom code to simulate such environments.
  146.  *    The ability to code this yourself is especially helpful when your simulated environment
  147.  *    is more complicated than simple traffic shaping (e.g. simulating a cone port restricted router),
  148.  *    or the system tools to handle this aren't available (e.g. on a mobile device).
  149.  *
  150.  * @param data    - The packet that was received.
  151.  * @param address - The address the data was received from.
  152.  *                  See utilities section for methods to extract info from address.
  153.  * @param tag     - The tag that was passed in the send method.
  154.  *
  155.  * @returns - YES if the packet should actually be sent over the socket.
  156.  *            NO if the packet should be silently dropped (not sent over the socket).
  157.  *
  158.  * Regardless of the return value, the delegate will be informed that the packet was successfully sent.
  159.  *
  160. **/
  161. typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address, long tag);
  162.  
  163.  
  164. @interface GCDAsyncUdpSocket : NSObject
  165.  
  166. /**
  167.  * GCDAsyncUdpSocket uses the standard delegate paradigm,
  168.  * but executes all delegate callbacks on a given delegate dispatch queue.
  169.  * This allows for maximum concurrency, while at the same time providing easy thread safety.
  170.  *
  171.  * You MUST set a delegate AND delegate dispatch queue before attempting to
  172.  * use the socket, or you will get an error.
  173.  *
  174.  * The socket queue is optional.
  175.  * If you pass NULL, GCDAsyncSocket will automatically create its own socket queue.
  176.  * If you choose to provide a socket queue, the socket queue must not be a concurrent queue,
  177.  * then please see the discussion for the method markSocketQueueTargetQueue.
  178.  *
  179.  * The delegate queue and socket queue can optionally be the same.
  180. **/
  181. - (instancetype)init;
  182. - (instancetype)initWithSocketQueue:(nullable dispatch_queue_t)sq;
  183. - (instancetype)initWithDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq;
  184. - (instancetype)initWithDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq socketQueue:(nullable dispatch_queue_t)sq NS_DESIGNATED_INITIALIZER;
  185.  
  186. #pragma mark Configuration
  187.  
  188. - (nullable id<GCDAsyncUdpSocketDelegate>)delegate;
  189. - (void)setDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)delegate;
  190. - (void)synchronouslySetDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)delegate;
  191.  
  192. - (nullable dispatch_queue_t)delegateQueue;
  193. - (void)setDelegateQueue:(nullable dispatch_queue_t)delegateQueue;
  194. - (void)synchronouslySetDelegateQueue:(nullable dispatch_queue_t)delegateQueue;
  195.  
  196. - (void)getDelegate:(id<GCDAsyncUdpSocketDelegate> __nullable * __nullable)delegatePtr delegateQueue:(dispatch_queue_t __nullable * __nullable)delegateQueuePtr;
  197. - (void)setDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
  198. - (void)synchronouslySetDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
  199.  
  200. /**
  201.  * By default, both IPv4 and IPv6 are enabled.
  202.  *
  203.  * This means GCDAsyncUdpSocket automatically supports both protocols,
  204.  * and can send to IPv4 or IPv6 addresses,
  205.  * as well as receive over IPv4 and IPv6.
  206.  *
  207.  * For operations that require DNS resolution, GCDAsyncUdpSocket supports both IPv4 and IPv6.
  208.  * If a DNS lookup returns only IPv4 results, GCDAsyncUdpSocket will automatically use IPv4.
  209.  * If a DNS lookup returns only IPv6 results, GCDAsyncUdpSocket will automatically use IPv6.
  210.  * If a DNS lookup returns both IPv4 and IPv6 results, then the protocol used depends on the configured preference.
  211.  * If IPv4 is preferred, then IPv4 is used.
  212.  * If IPv6 is preferred, then IPv6 is used.
  213.  * If neutral, then the first IP version in the resolved array will be used.
  214.  *
  215.  * Starting with Mac OS X 10.7 Lion and iOS 5, the default IP preference is neutral.
  216.  * On prior systems the default IP preference is IPv4.
  217.  **/
  218. - (BOOL)isIPv4Enabled;
  219. - (void)setIPv4Enabled:(BOOL)flag;
  220.  
  221. - (BOOL)isIPv6Enabled;
  222. - (void)setIPv6Enabled:(BOOL)flag;
  223.  
  224. - (BOOL)isIPv4Preferred;
  225. - (BOOL)isIPv6Preferred;
  226. - (BOOL)isIPVersionNeutral;
  227.  
  228. - (void)setPreferIPv4;
  229. - (void)setPreferIPv6;
  230. - (void)setIPVersionNeutral;
  231.  
  232. /**
  233.  * Gets/Sets the maximum size of the buffer that will be allocated for receive operations.
  234.  * The default maximum size is 65535 bytes.
  235.  *
  236.  * The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535.
  237.  * The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295.
  238.  *
  239.  * Since the OS/GCD notifies us of the size of each received UDP packet,
  240.  * the actual allocated buffer size for each packet is exact.
  241.  * And in practice the size of UDP packets is generally much smaller than the max.
  242.  * Indeed most protocols will send and receive packets of only a few bytes,
  243.  * or will set a limit on the size of packets to prevent fragmentation in the IP layer.
  244.  *
  245.  * If you set the buffer size too small, the sockets API in the OS will silently discard
  246.  * any extra data, and you will not be notified of the error.
  247. **/
  248. - (uint16_t)maxReceiveIPv4BufferSize;
  249. - (void)setMaxReceiveIPv4BufferSize:(uint16_t)max;
  250.  
  251. - (uint32_t)maxReceiveIPv6BufferSize;
  252. - (void)setMaxReceiveIPv6BufferSize:(uint32_t)max;
  253.  
  254. /**
  255.  * Gets/Sets the maximum size of the buffer that will be allocated for send operations.
  256.  * The default maximum size is 65535 bytes.
  257.  *
  258.  * Given that a typical link MTU is 1500 bytes, a large UDP datagram will have to be
  259.  * fragmented, and that’s both expensive and risky (if one fragment goes missing, the
  260.  * entire datagram is lost).  You are much better off sending a large number of smaller
  261.  * UDP datagrams, preferably using a path MTU algorithm to avoid fragmentation.
  262.  *
  263.  * You must set it before the sockt is created otherwise it won't work.
  264.  *
  265.  **/
  266. - (uint16_t)maxSendBufferSize;
  267. - (void)setMaxSendBufferSize:(uint16_t)max;
  268.  
  269. /**
  270.  * User data allows you to associate arbitrary information with the socket.
  271.  * This data is not used internally in any way.
  272. **/
  273. - (nullable id)userData;
  274. - (void)setUserData:(nullable id)arbitraryUserData;
  275.  
  276. #pragma mark Diagnostics
  277.  
  278. /**
  279.  * Returns the local address info for the socket.
  280.  *
  281.  * The localAddress method returns a sockaddr structure wrapped in a NSData object.
  282.  * The localHost method returns the human readable IP address as a string.
  283.  *
  284.  * Note: Address info may not be available until after the socket has been binded, connected
  285.  * or until after data has been sent.
  286. **/
  287. - (nullable NSData *)localAddress;
  288. - (nullable NSString *)localHost;
  289. - (uint16_t)localPort;
  290.  
  291. - (nullable NSData *)localAddress_IPv4;
  292. - (nullable NSString *)localHost_IPv4;
  293. - (uint16_t)localPort_IPv4;
  294.  
  295. - (nullable NSData *)localAddress_IPv6;
  296. - (nullable NSString *)localHost_IPv6;
  297. - (uint16_t)localPort_IPv6;
  298.  
  299. /**
  300.  * Returns the remote address info for the socket.
  301.  *
  302.  * The connectedAddress method returns a sockaddr structure wrapped in a NSData object.
  303.  * The connectedHost method returns the human readable IP address as a string.
  304.  *
  305.  * Note: Since UDP is connectionless by design, connected address info
  306.  * will not be available unless the socket is explicitly connected to a remote host/port.
  307.  * If the socket is not connected, these methods will return nil / 0.
  308. **/
  309. - (nullable NSData *)connectedAddress;
  310. - (nullable NSString *)connectedHost;
  311. - (uint16_t)connectedPort;
  312.  
  313. /**
  314.  * Returns whether or not this socket has been connected to a single host.
  315.  * By design, UDP is a connectionless protocol, and connecting is not needed.
  316.  * If connected, the socket will only be able to send/receive data to/from the connected host.
  317. **/
  318. - (BOOL)isConnected;
  319.  
  320. /**
  321.  * Returns whether or not this socket has been closed.
  322.  * The only way a socket can be closed is if you explicitly call one of the close methods.
  323. **/
  324. - (BOOL)isClosed;
  325.  
  326. /**
  327.  * Returns whether or not this socket is IPv4.
  328.  *
  329.  * By default this will be true, unless:
  330.  * - IPv4 is disabled (via setIPv4Enabled:)
  331.  * - The socket is explicitly bound to an IPv6 address
  332.  * - The socket is connected to an IPv6 address
  333. **/
  334. - (BOOL)isIPv4;
  335.  
  336. /**
  337.  * Returns whether or not this socket is IPv6.
  338.  *
  339.  * By default this will be true, unless:
  340.  * - IPv6 is disabled (via setIPv6Enabled:)
  341.  * - The socket is explicitly bound to an IPv4 address
  342.  * _ The socket is connected to an IPv4 address
  343.  *
  344.  * This method will also return false on platforms that do not support IPv6.
  345.  * Note: The iPhone does not currently support IPv6.
  346. **/
  347. - (BOOL)isIPv6;
  348.  
  349. #pragma mark Binding
  350.  
  351. /**
  352.  * Binds the UDP socket to the given port.
  353.  * Binding should be done for server sockets that receive data prior to sending it.
  354.  * Client sockets can skip binding,
  355.  * as the OS will automatically assign the socket an available port when it starts sending data.
  356.  *
  357.  * You may optionally pass a port number of zero to immediately bind the socket,
  358.  * yet still allow the OS to automatically assign an available port.
  359.  *
  360.  * You cannot bind a socket after its been connected.
  361.  * You can only bind a socket once.
  362.  * You can still connect a socket (if desired) after binding.
  363.  *
  364.  * On success, returns YES.
  365.  * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass NULL for errPtr.
  366. **/
  367. - (BOOL)bindToPort:(uint16_t)port error:(NSError **)errPtr;
  368.  
  369. /**
  370.  * Binds the UDP socket to the given port and optional interface.
  371.  * Binding should be done for server sockets that receive data prior to sending it.
  372.  * Client sockets can skip binding,
  373.  * as the OS will automatically assign the socket an available port when it starts sending data.
  374.  *
  375.  * You may optionally pass a port number of zero to immediately bind the socket,
  376.  * yet still allow the OS to automatically assign an available port.
  377.  *
  378.  * The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35").
  379.  * You may also use the special strings "localhost" or "loopback" to specify that
  380.  * the socket only accept packets from the local machine.
  381.  *
  382.  * You cannot bind a socket after its been connected.
  383.  * You can only bind a socket once.
  384.  * You can still connect a socket (if desired) after binding.
  385.  *
  386.  * On success, returns YES.
  387.  * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass NULL for errPtr.
  388. **/
  389. - (BOOL)bindToPort:(uint16_t)port interface:(nullable NSString *)interface error:(NSError **)errPtr;
  390.  
  391. /**
  392.  * Binds the UDP socket to the given address, specified as a sockaddr structure wrapped in a NSData object.
  393.  *
  394.  * If you have an existing struct sockaddr you can convert it to a NSData object like so:
  395.  * struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  396.  * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];
  397.  *
  398.  * Binding should be done for server sockets that receive data prior to sending it.
  399.  * Client sockets can skip binding,
  400.  * as the OS will automatically assign the socket an available port when it starts sending data.
  401.  *
  402.  * You cannot bind a socket after its been connected.
  403.  * You can only bind a socket once.
  404.  * You can still connect a socket (if desired) after binding.
  405.  *
  406.  * On success, returns YES.
  407.  * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass NULL for errPtr.
  408. **/
  409. - (BOOL)bindToAddress:(NSData *)localAddr error:(NSError **)errPtr;
  410.  
  411. #pragma mark Connecting
  412.  
  413. /**
  414.  * Connects the UDP socket to the given host and port.
  415.  * By design, UDP is a connectionless protocol, and connecting is not needed.
  416.  *
  417.  * Choosing to connect to a specific host/port has the following effect:
  418.  * - You will only be able to send data to the connected host/port.
  419.  * - You will only be able to receive data from the connected host/port.
  420.  * - You will receive ICMP messages that come from the connected host/port, such as "connection refused".
  421.  *
  422.  * The actual process of connecting a UDP socket does not result in any communication on the socket.
  423.  * It simply changes the internal state of the socket.
  424.  *
  425.  * You cannot bind a socket after it has been connected.
  426.  * You can only connect a socket once.
  427.  *
  428.  * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2").
  429.  *
  430.  * This method is asynchronous as it requires a DNS lookup to resolve the given host name.
  431.  * If an obvious error is detected, this method immediately returns NO and sets errPtr.
  432.  * If you don't care about the error, you can pass nil for errPtr.
  433.  * Otherwise, this method returns YES and begins the asynchronous connection process.
  434.  * The result of the asynchronous connection process will be reported via the delegate methods.
  435.  **/
  436. - (BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port error:(NSError **)errPtr;
  437.  
  438. /**
  439.  * Connects the UDP socket to the given address, specified as a sockaddr structure wrapped in a NSData object.
  440.  *
  441.  * If you have an existing struct sockaddr you can convert it to a NSData object like so:
  442.  * struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  443.  * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];
  444.  *
  445.  * By design, UDP is a connectionless protocol, and connecting is not needed.
  446.  *
  447.  * Choosing to connect to a specific address has the following effect:
  448.  * - You will only be able to send data to the connected address.
  449.  * - You will only be able to receive data from the connected address.
  450.  * - You will receive ICMP messages that come from the connected address, such as "connection refused".
  451.  *
  452.  * Connecting a UDP socket does not result in any communication on the socket.
  453.  * It simply changes the internal state of the socket.
  454.  *
  455.  * You cannot bind a socket after its been connected.
  456.  * You can only connect a socket once.
  457.  *
  458.  * On success, returns YES.
  459.  * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
  460.  *
  461.  * Note: Unlike the connectToHost:onPort:error: method, this method does not require a DNS lookup.
  462.  * Thus when this method returns, the connection has either failed or fully completed.
  463.  * In other words, this method is synchronous, unlike the asynchronous connectToHost::: method.
  464.  * However, for compatibility and simplification of delegate code, if this method returns YES
  465.  * then the corresponding delegate method (udpSocket:didConnectToHost:port:) is still invoked.
  466. **/
  467. - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
  468.  
  469. #pragma mark Multicast
  470.  
  471. /**
  472.  * Join multicast group.
  473.  * Group should be an IP address (eg @"225.228.0.1").
  474.  *
  475.  * On success, returns YES.
  476.  * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
  477. **/
  478. - (BOOL)joinMulticastGroup:(NSString *)group error:(NSError **)errPtr;
  479.  
  480. /**
  481.  * Join multicast group.
  482.  * Group should be an IP address (eg @"225.228.0.1").
  483.  * The interface may be a name (e.g. "en1" or "lo0") or the corresponding IP address (e.g. "192.168.4.35").
  484.  *
  485.  * On success, returns YES.
  486.  * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
  487. **/
  488. - (BOOL)joinMulticastGroup:(NSString *)group onInterface:(nullable NSString *)interface error:(NSError **)errPtr;
  489.  
  490. - (BOOL)leaveMulticastGroup:(NSString *)group error:(NSError **)errPtr;
  491. - (BOOL)leaveMulticastGroup:(NSString *)group onInterface:(nullable NSString *)interface error:(NSError **)errPtr;
  492.  
  493. /**
  494.  * Send multicast on a specified interface.
  495.  * For IPv4, interface should be the the IP address of the interface (eg @"192.168.10.1").
  496.  * For IPv6, interface should be the a network interface name (eg @"en0").
  497.  *
  498.  * On success, returns YES.
  499.  * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
  500. **/
  501.  
  502. - (BOOL)sendIPv4MulticastOnInterface:(NSString*)interface error:(NSError **)errPtr;
  503. - (BOOL)sendIPv6MulticastOnInterface:(NSString*)interface error:(NSError **)errPtr;
  504.  
  505. #pragma mark Reuse Port
  506.  
  507. /**
  508.  * By default, only one socket can be bound to a given IP address + port at a time.
  509.  * To enable multiple processes to simultaneously bind to the same address+port,
  510.  * you need to enable this functionality in the socket.  All processes that wish to
  511.  * use the address+port simultaneously must all enable reuse port on the socket
  512.  * bound to that port.
  513.  **/
  514. - (BOOL)enableReusePort:(BOOL)flag error:(NSError **)errPtr;
  515.  
  516. #pragma mark Broadcast
  517.  
  518. /**
  519.  * By default, the underlying socket in the OS will not allow you to send broadcast messages.
  520.  * In order to send broadcast messages, you need to enable this functionality in the socket.
  521.  *
  522.  * A broadcast is a UDP message to addresses like "192.168.255.255" or "255.255.255.255" that is
  523.  * delivered to every host on the network.
  524.  * The reason this is generally disabled by default (by the OS) is to prevent
  525.  * accidental broadcast messages from flooding the network.
  526. **/
  527. - (BOOL)enableBroadcast:(BOOL)flag error:(NSError **)errPtr;
  528.  
  529. #pragma mark Sending
  530.  
  531. /**
  532.  * Asynchronously sends the given data, with the given timeout and tag.
  533.  *
  534.  * This method may only be used with a connected socket.
  535.  * Recall that connecting is optional for a UDP socket.
  536.  * For connected sockets, data can only be sent to the connected address.
  537.  * For non-connected sockets, the remote destination is specified for each packet.
  538.  * For more information about optionally connecting udp sockets, see the documentation for the connect methods above.
  539.  *
  540.  * @param data
  541.  *     The data to send.
  542.  *     If data is nil or zero-length, this method does nothing.
  543.  *     If passing NSMutableData, please read the thread-safety notice below.
  544.  *
  545.  * @param timeout
  546.  *    The timeout for the send opeartion.
  547.  *    If the timeout value is negative, the send operation will not use a timeout.
  548.  *
  549.  * @param tag
  550.  *    The tag is for your convenience.
  551.  *    It is not sent or received over the socket in any manner what-so-ever.
  552.  *    It is reported back as a parameter in the udpSocket:didSendDataWithTag:
  553.  *    or udpSocket:didNotSendDataWithTag:dueToError: methods.
  554.  *    You can use it as an array index, state id, type constant, etc.
  555.  *
  556.  *
  557.  * Thread-Safety Note:
  558.  * If the given data parameter is mutable (NSMutableData) then you MUST NOT alter the data while
  559.  * the socket is sending it. In other words, it's not safe to alter the data until after the delegate method
  560.  * udpSocket:didSendDataWithTag: or udpSocket:didNotSendDataWithTag:dueToError: is invoked signifying
  561.  * that this particular send operation has completed.
  562.  * This is due to the fact that GCDAsyncUdpSocket does NOT copy the data.
  563.  * It simply retains it for performance reasons.
  564.  * Often times, if NSMutableData is passed, it is because a request/response was built up in memory.
  565.  * Copying this data adds an unwanted/unneeded overhead.
  566.  * If you need to write data from an immutable buffer, and you need to alter the buffer before the socket
  567.  * completes sending the bytes (which is NOT immediately after this method returns, but rather at a later time
  568.  * when the delegate method notifies you), then you should first copy the bytes, and pass the copy to this method.
  569. **/
  570. - (void)sendData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  571.  
  572. /**
  573.  * Asynchronously sends the given data, with the given timeout and tag, to the given host and port.
  574.  *
  575.  * This method cannot be used with a connected socket.
  576.  * Recall that connecting is optional for a UDP socket.
  577.  * For connected sockets, data can only be sent to the connected address.
  578.  * For non-connected sockets, the remote destination is specified for each packet.
  579.  * For more information about optionally connecting udp sockets, see the documentation for the connect methods above.
  580.  *
  581.  * @param data
  582.  *     The data to send.
  583.  *     If data is nil or zero-length, this method does nothing.
  584.  *     If passing NSMutableData, please read the thread-safety notice below.
  585.  *
  586.  * @param host
  587.  *     The destination to send the udp packet to.
  588.  *     May be specified as a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2").
  589.  *     You may also use the convenience strings of "loopback" or "localhost".
  590.  *
  591.  * @param port
  592.  *    The port of the host to send to.
  593.  *
  594.  * @param timeout
  595.  *    The timeout for the send opeartion.
  596.  *    If the timeout value is negative, the send operation will not use a timeout.
  597.  *
  598.  * @param tag
  599.  *    The tag is for your convenience.
  600.  *    It is not sent or received over the socket in any manner what-so-ever.
  601.  *    It is reported back as a parameter in the udpSocket:didSendDataWithTag:
  602.  *    or udpSocket:didNotSendDataWithTag:dueToError: methods.
  603.  *    You can use it as an array index, state id, type constant, etc.
  604.  *
  605.  *
  606.  * Thread-Safety Note:
  607.  * If the given data parameter is mutable (NSMutableData) then you MUST NOT alter the data while
  608.  * the socket is sending it. In other words, it's not safe to alter the data until after the delegate method
  609.  * udpSocket:didSendDataWithTag: or udpSocket:didNotSendDataWithTag:dueToError: is invoked signifying
  610.  * that this particular send operation has completed.
  611.  * This is due to the fact that GCDAsyncUdpSocket does NOT copy the data.
  612.  * It simply retains it for performance reasons.
  613.  * Often times, if NSMutableData is passed, it is because a request/response was built up in memory.
  614.  * Copying this data adds an unwanted/unneeded overhead.
  615.  * If you need to write data from an immutable buffer, and you need to alter the buffer before the socket
  616.  * completes sending the bytes (which is NOT immediately after this method returns, but rather at a later time
  617.  * when the delegate method notifies you), then you should first copy the bytes, and pass the copy to this method.
  618. **/
  619. - (void)sendData:(NSData *)data
  620.           toHost:(NSString *)host
  621.             port:(uint16_t)port
  622.      withTimeout:(NSTimeInterval)timeout
  623.              tag:(long)tag;
  624.  
  625. /**
  626.  * Asynchronously sends the given data, with the given timeout and tag, to the given address.
  627.  *
  628.  * This method cannot be used with a connected socket.
  629.  * Recall that connecting is optional for a UDP socket.
  630.  * For connected sockets, data can only be sent to the connected address.
  631.  * For non-connected sockets, the remote destination is specified for each packet.
  632.  * For more information about optionally connecting udp sockets, see the documentation for the connect methods above.
  633.  *
  634.  * @param data
  635.  *     The data to send.
  636.  *     If data is nil or zero-length, this method does nothing.
  637.  *     If passing NSMutableData, please read the thread-safety notice below.
  638.  *
  639.  * @param remoteAddr
  640.  *     The address to send the data to (specified as a sockaddr structure wrapped in a NSData object).
  641.  *
  642.  * @param timeout
  643.  *    The timeout for the send opeartion.
  644.  *    If the timeout value is negative, the send operation will not use a timeout.
  645.  *
  646.  * @param tag
  647.  *    The tag is for your convenience.
  648.  *    It is not sent or received over the socket in any manner what-so-ever.
  649.  *    It is reported back as a parameter in the udpSocket:didSendDataWithTag:
  650.  *    or udpSocket:didNotSendDataWithTag:dueToError: methods.
  651.  *    You can use it as an array index, state id, type constant, etc.
  652.  *
  653.  *
  654.  * Thread-Safety Note:
  655.  * If the given data parameter is mutable (NSMutableData) then you MUST NOT alter the data while
  656.  * the socket is sending it. In other words, it's not safe to alter the data until after the delegate method
  657.  * udpSocket:didSendDataWithTag: or udpSocket:didNotSendDataWithTag:dueToError: is invoked signifying
  658.  * that this particular send operation has completed.
  659.  * This is due to the fact that GCDAsyncUdpSocket does NOT copy the data.
  660.  * It simply retains it for performance reasons.
  661.  * Often times, if NSMutableData is passed, it is because a request/response was built up in memory.
  662.  * Copying this data adds an unwanted/unneeded overhead.
  663.  * If you need to write data from an immutable buffer, and you need to alter the buffer before the socket
  664.  * completes sending the bytes (which is NOT immediately after this method returns, but rather at a later time
  665.  * when the delegate method notifies you), then you should first copy the bytes, and pass the copy to this method.
  666. **/
  667. - (void)sendData:(NSData *)data toAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  668.  
  669. /**
  670.  * You may optionally set a send filter for the socket.
  671.  * A filter can provide several interesting possibilities:
  672.  *
  673.  * 1. Optional caching of resolved addresses for domain names.
  674.  *    The cache could later be consulted, resulting in fewer system calls to getaddrinfo.
  675.  *
  676.  * 2. Reusable modules of code for bandwidth monitoring.
  677.  *
  678.  * 3. Sometimes traffic shapers are needed to simulate real world environments.
  679.  *    A filter allows you to write custom code to simulate such environments.
  680.  *    The ability to code this yourself is especially helpful when your simulated environment
  681.  *    is more complicated than simple traffic shaping (e.g. simulating a cone port restricted router),
  682.  *    or the system tools to handle this aren't available (e.g. on a mobile device).
  683.  *
  684.  * For more information about GCDAsyncUdpSocketSendFilterBlock, see the documentation for its typedef.
  685.  * To remove a previously set filter, invoke this method and pass a nil filterBlock and NULL filterQueue.
  686.  *
  687.  * Note: This method invokes setSendFilter:withQueue:isAsynchronous: (documented below),
  688.  *       passing YES for the isAsynchronous parameter.
  689. **/
  690. - (void)setSendFilter:(nullable GCDAsyncUdpSocketSendFilterBlock)filterBlock withQueue:(nullable dispatch_queue_t)filterQueue;
  691.  
  692. /**
  693.  * The receive filter can be run via dispatch_async or dispatch_sync.
  694.  * Most typical situations call for asynchronous operation.
  695.  *
  696.  * However, there are a few situations in which synchronous operation is preferred.
  697.  * Such is the case when the filter is extremely minimal and fast.
  698.  * This is because dispatch_sync is faster than dispatch_async.
  699.  *
  700.  * If you choose synchronous operation, be aware of possible deadlock conditions.
  701.  * Since the socket queue is executing your block via dispatch_sync,
  702.  * then you cannot perform any tasks which may invoke dispatch_sync on the socket queue.
  703.  * For example, you can't query properties on the socket.
  704. **/
  705. - (void)setSendFilter:(nullable GCDAsyncUdpSocketSendFilterBlock)filterBlock
  706.             withQueue:(nullable dispatch_queue_t)filterQueue
  707.        isAsynchronous:(BOOL)isAsynchronous;
  708.  
  709. #pragma mark Receiving
  710.  
  711. /**
  712.  * There are two modes of operation for receiving packets: one-at-a-time & continuous.
  713.  *
  714.  * In one-at-a-time mode, you call receiveOnce everytime your delegate is ready to process an incoming udp packet.
  715.  * Receiving packets one-at-a-time may be better suited for implementing certain state machine code,
  716.  * where your state machine may not always be ready to process incoming packets.
  717.  *
  718.  * In continuous mode, the delegate is invoked immediately everytime incoming udp packets are received.
  719.  * Receiving packets continuously is better suited to real-time streaming applications.
  720.  *
  721.  * You may switch back and forth between one-at-a-time mode and continuous mode.
  722.  * If the socket is currently in continuous mode, calling this method will switch it to one-at-a-time mode.
  723.  *
  724.  * When a packet is received (and not filtered by the optional receive filter),
  725.  * the delegate method (udpSocket:didReceiveData:fromAddress:withFilterContext:) is invoked.
  726.  *
  727.  * If the socket is able to begin receiving packets, this method returns YES.
  728.  * Otherwise it returns NO, and sets the errPtr with appropriate error information.
  729.  *
  730.  * An example error:
  731.  * You created a udp socket to act as a server, and immediately called receive.
  732.  * You forgot to first bind the socket to a port number, and received a error with a message like:
  733.  * "Must bind socket before you can receive data."
  734. **/
  735. - (BOOL)receiveOnce:(NSError **)errPtr;
  736.  
  737. /**
  738.  * There are two modes of operation for receiving packets: one-at-a-time & continuous.
  739.  *
  740.  * In one-at-a-time mode, you call receiveOnce everytime your delegate is ready to process an incoming udp packet.
  741.  * Receiving packets one-at-a-time may be better suited for implementing certain state machine code,
  742.  * where your state machine may not always be ready to process incoming packets.
  743.  *
  744.  * In continuous mode, the delegate is invoked immediately everytime incoming udp packets are received.
  745.  * Receiving packets continuously is better suited to real-time streaming applications.
  746.  *
  747.  * You may switch back and forth between one-at-a-time mode and continuous mode.
  748.  * If the socket is currently in one-at-a-time mode, calling this method will switch it to continuous mode.
  749.  *
  750.  * For every received packet (not filtered by the optional receive filter),
  751.  * the delegate method (udpSocket:didReceiveData:fromAddress:withFilterContext:) is invoked.
  752.  *
  753.  * If the socket is able to begin receiving packets, this method returns YES.
  754.  * Otherwise it returns NO, and sets the errPtr with appropriate error information.
  755.  *
  756.  * An example error:
  757.  * You created a udp socket to act as a server, and immediately called receive.
  758.  * You forgot to first bind the socket to a port number, and received a error with a message like:
  759.  * "Must bind socket before you can receive data."
  760. **/
  761. - (BOOL)beginReceiving:(NSError **)errPtr;
  762.  
  763. /**
  764.  * If the socket is currently receiving (beginReceiving has been called), this method pauses the receiving.
  765.  * That is, it won't read any more packets from the underlying OS socket until beginReceiving is called again.
  766.  *
  767.  * Important Note:
  768.  * GCDAsyncUdpSocket may be running in parallel with your code.
  769.  * That is, your delegate is likely running on a separate thread/dispatch_queue.
  770.  * When you invoke this method, GCDAsyncUdpSocket may have already dispatched delegate methods to be invoked.
  771.  * Thus, if those delegate methods have already been dispatch_async'd,
  772.  * your didReceive delegate method may still be invoked after this method has been called.
  773.  * You should be aware of this, and program defensively.
  774. **/
  775. - (void)pauseReceiving;
  776.  
  777. /**
  778.  * You may optionally set a receive filter for the socket.
  779.  * This receive filter may be set to run in its own queue (independent of delegate queue).
  780.  *
  781.  * A filter can provide several useful features.
  782.  *
  783.  * 1. Many times udp packets need to be parsed.
  784.  *    Since the filter can run in its own independent queue, you can parallelize this parsing quite easily.
  785.  *    The end result is a parallel socket io, datagram parsing, and packet processing.
  786.  *
  787.  * 2. Many times udp packets are discarded because they are duplicate/unneeded/unsolicited.
  788.  *    The filter can prevent such packets from arriving at the delegate.
  789.  *    And because the filter can run in its own independent queue, this doesn't slow down the delegate.
  790.  *
  791.  *    - Since the udp protocol does not guarantee delivery, udp packets may be lost.
  792.  *      Many protocols built atop udp thus provide various resend/re-request algorithms.
  793.  *      This sometimes results in duplicate packets arriving.
  794.  *      A filter may allow you to architect the duplicate detection code to run in parallel to normal processing.
  795.  *    
  796.  *    - Since the udp socket may be connectionless, its possible for unsolicited packets to arrive.
  797.  *      Such packets need to be ignored.
  798.  *
  799.  * 3. Sometimes traffic shapers are needed to simulate real world environments.
  800.  *    A filter allows you to write custom code to simulate such environments.
  801.  *    The ability to code this yourself is especially helpful when your simulated environment
  802.  *    is more complicated than simple traffic shaping (e.g. simulating a cone port restricted router),
  803.  *    or the system tools to handle this aren't available (e.g. on a mobile device).
  804.  *
  805.  * Example:
  806.  *
  807.  * GCDAsyncUdpSocketReceiveFilterBlock filter = ^BOOL (NSData *data, NSData *address, id *context) {
  808.  *
  809.  *     MyProtocolMessage *msg = [MyProtocol parseMessage:data];
  810.  *    
  811.  *     *context = response;
  812.  *     return (response != nil);
  813.  * };
  814.  * [udpSocket setReceiveFilter:filter withQueue:myParsingQueue];
  815.  *
  816.  * For more information about GCDAsyncUdpSocketReceiveFilterBlock, see the documentation for its typedef.
  817.  * To remove a previously set filter, invoke this method and pass a nil filterBlock and NULL filterQueue.
  818.  *
  819.  * Note: This method invokes setReceiveFilter:withQueue:isAsynchronous: (documented below),
  820.  *       passing YES for the isAsynchronous parameter.
  821. **/
  822. - (void)setReceiveFilter:(nullable GCDAsyncUdpSocketReceiveFilterBlock)filterBlock withQueue:(nullable dispatch_queue_t)filterQueue;
  823.  
  824. /**
  825.  * The receive filter can be run via dispatch_async or dispatch_sync.
  826.  * Most typical situations call for asynchronous operation.
  827.  *
  828.  * However, there are a few situations in which synchronous operation is preferred.
  829.  * Such is the case when the filter is extremely minimal and fast.
  830.  * This is because dispatch_sync is faster than dispatch_async.
  831.  *
  832.  * If you choose synchronous operation, be aware of possible deadlock conditions.
  833.  * Since the socket queue is executing your block via dispatch_sync,
  834.  * then you cannot perform any tasks which may invoke dispatch_sync on the socket queue.
  835.  * For example, you can't query properties on the socket.
  836. **/
  837. - (void)setReceiveFilter:(nullable GCDAsyncUdpSocketReceiveFilterBlock)filterBlock
  838.                withQueue:(nullable dispatch_queue_t)filterQueue
  839.           isAsynchronous:(BOOL)isAsynchronous;
  840.  
  841. #pragma mark Closing
  842.  
  843. /**
  844.  * Immediately closes the underlying socket.
  845.  * Any pending send operations are discarded.
  846.  *
  847.  * The GCDAsyncUdpSocket instance may optionally be used again.
  848.  *   (it will setup/configure/use another unnderlying BSD socket).
  849. **/
  850. - (void)close;
  851.  
  852. /**
  853.  * Closes the underlying socket after all pending send operations have been sent.
  854.  *
  855.  * The GCDAsyncUdpSocket instance may optionally be used again.
  856.  *   (it will setup/configure/use another unnderlying BSD socket).
  857. **/
  858. - (void)closeAfterSending;
  859.  
  860. #pragma mark Advanced
  861. /**
  862.  * GCDAsyncSocket maintains thread safety by using an internal serial dispatch_queue.
  863.  * In most cases, the instance creates this queue itself.
  864.  * However, to allow for maximum flexibility, the internal queue may be passed in the init method.
  865.  * This allows for some advanced options such as controlling socket priority via target queues.
  866.  * However, when one begins to use target queues like this, they open the door to some specific deadlock issues.
  867.  *
  868.  * For example, imagine there are 2 queues:
  869.  * dispatch_queue_t socketQueue;
  870.  * dispatch_queue_t socketTargetQueue;
  871.  *
  872.  * If you do this (pseudo-code):
  873.  * socketQueue.targetQueue = socketTargetQueue;
  874.  *
  875.  * Then all socketQueue operations will actually get run on the given socketTargetQueue.
  876.  * This is fine and works great in most situations.
  877.  * But if you run code directly from within the socketTargetQueue that accesses the socket,
  878.  * you could potentially get deadlock. Imagine the following code:
  879.  *
  880.  * - (BOOL)socketHasSomething
  881.  * {
  882.  *     __block BOOL result = NO;
  883.  *     dispatch_block_t block = ^{
  884.  *         result = [self someInternalMethodToBeRunOnlyOnSocketQueue];
  885.  *     }
  886.  *     if (is_executing_on_queue(socketQueue))
  887.  *         block();
  888.  *     else
  889.  *         dispatch_sync(socketQueue, block);
  890.  *
  891.  *     return result;
  892.  * }
  893.  *
  894.  * What happens if you call this method from the socketTargetQueue? The result is deadlock.
  895.  * This is because the GCD API offers no mechanism to discover a queue's targetQueue.
  896.  * Thus we have no idea if our socketQueue is configured with a targetQueue.
  897.  * If we had this information, we could easily avoid deadlock.
  898.  * But, since these API's are missing or unfeasible, you'll have to explicitly set it.
  899.  *
  900.  * IF you pass a socketQueue via the init method,
  901.  * AND you've configured the passed socketQueue with a targetQueue,
  902.  * THEN you should pass the end queue in the target hierarchy.
  903.  *
  904.  * For example, consider the following queue hierarchy:
  905.  * socketQueue -> ipQueue -> moduleQueue
  906.  *
  907.  * This example demonstrates priority shaping within some server.
  908.  * All incoming client connections from the same IP address are executed on the same target queue.
  909.  * And all connections for a particular module are executed on the same target queue.
  910.  * Thus, the priority of all networking for the entire module can be changed on the fly.
  911.  * Additionally, networking traffic from a single IP cannot monopolize the module.
  912.  *
  913.  * Here's how you would accomplish something like that:
  914.  * - (dispatch_queue_t)newSocketQueueForConnectionFromAddress:(NSData *)address onSocket:(GCDAsyncSocket *)sock
  915.  * {
  916.  *     dispatch_queue_t socketQueue = dispatch_queue_create("", NULL);
  917.  *     dispatch_queue_t ipQueue = [self ipQueueForAddress:address];
  918.  *
  919.  *     dispatch_set_target_queue(socketQueue, ipQueue);
  920.  *     dispatch_set_target_queue(iqQueue, moduleQueue);
  921.  *
  922.  *     return socketQueue;
  923.  * }
  924.  * - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
  925.  * {
  926.  *     [clientConnections addObject:newSocket];
  927.  *     [newSocket markSocketQueueTargetQueue:moduleQueue];
  928.  * }
  929.  *
  930.  * Note: This workaround is ONLY needed if you intend to execute code directly on the ipQueue or moduleQueue.
  931.  * This is often NOT the case, as such queues are used solely for execution shaping.
  932.  **/
  933. - (void)markSocketQueueTargetQueue:(dispatch_queue_t)socketQueuesPreConfiguredTargetQueue;
  934. - (void)unmarkSocketQueueTargetQueue:(dispatch_queue_t)socketQueuesPreviouslyConfiguredTargetQueue;
  935.  
  936. /**
  937.  * It's not thread-safe to access certain variables from outside the socket's internal queue.
  938.  *
  939.  * For example, the socket file descriptor.
  940.  * File descriptors are simply integers which reference an index in the per-process file table.
  941.  * However, when one requests a new file descriptor (by opening a file or socket),
  942.  * the file descriptor returned is guaranteed to be the lowest numbered unused descriptor.
  943.  * So if we're not careful, the following could be possible:
  944.  *
  945.  * - Thread A invokes a method which returns the socket's file descriptor.
  946.  * - The socket is closed via the socket's internal queue on thread B.
  947.  * - Thread C opens a file, and subsequently receives the file descriptor that was previously the socket's FD.
  948.  * - Thread A is now accessing/altering the file instead of the socket.
  949.  *
  950.  * In addition to this, other variables are not actually objects,
  951.  * and thus cannot be retained/released or even autoreleased.
  952.  * An example is the sslContext, of type SSLContextRef, which is actually a malloc'd struct.
  953.  *
  954.  * Although there are internal variables that make it difficult to maintain thread-safety,
  955.  * it is important to provide access to these variables
  956.  * to ensure this class can be used in a wide array of environments.
  957.  * This method helps to accomplish this by invoking the current block on the socket's internal queue.
  958.  * The methods below can be invoked from within the block to access
  959.  * those generally thread-unsafe internal variables in a thread-safe manner.
  960.  * The given block will be invoked synchronously on the socket's internal queue.
  961.  *
  962.  * If you save references to any protected variables and use them outside the block, you do so at your own peril.
  963. **/
  964. - (void)performBlock:(dispatch_block_t)block;
  965.  
  966. /**
  967.  * These methods are only available from within the context of a performBlock: invocation.
  968.  * See the documentation for the performBlock: method above.
  969.  *
  970.  * Provides access to the socket's file descriptor(s).
  971.  * If the socket isn't connected, or explicity bound to a particular interface,
  972.  * it might actually have multiple internal socket file descriptors - one for IPv4 and one for IPv6.
  973. **/
  974. - (int)socketFD;
  975. - (int)socket4FD;
  976. - (int)socket6FD;
  977.  
  978. #if TARGET_OS_IPHONE
  979.  
  980. /**
  981.  * These methods are only available from within the context of a performBlock: invocation.
  982.  * See the documentation for the performBlock: method above.
  983.  *
  984.  * Returns (creating if necessary) a CFReadStream/CFWriteStream for the internal socket.
  985.  *
  986.  * Generally GCDAsyncUdpSocket doesn't use CFStream. (It uses the faster GCD API's.)
  987.  * However, if you need one for any reason,
  988.  * these methods are a convenient way to get access to a safe instance of one.
  989. **/
  990. - (nullable CFReadStreamRef)readStream;
  991. - (nullable CFWriteStreamRef)writeStream;
  992.  
  993. /**
  994.  * This method is only available from within the context of a performBlock: invocation.
  995.  * See the documentation for the performBlock: method above.
  996.  *
  997.  * Configures the socket to allow it to operate when the iOS application has been backgrounded.
  998.  * In other words, this method creates a read & write stream, and invokes:
  999.  *
  1000.  * CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  1001.  * CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  1002.  *
  1003.  * Returns YES if successful, NO otherwise.
  1004.  *
  1005.  * Example usage:
  1006.  *
  1007.  * [asyncUdpSocket performBlock:^{
  1008.  *     [asyncUdpSocket enableBackgroundingOnSocket];
  1009.  * }];
  1010.  *
  1011.  *
  1012.  * NOTE : Apple doesn't currently support backgrounding UDP sockets. (Only TCP for now).
  1013. **/
  1014. //- (BOOL)enableBackgroundingOnSockets;
  1015.  
  1016. #endif
  1017.  
  1018. #pragma mark Utilities
  1019.  
  1020. /**
  1021.  * Extracting host/port/family information from raw address data.
  1022. **/
  1023.  
  1024. + (nullable NSString *)hostFromAddress:(NSData *)address;
  1025. + (uint16_t)portFromAddress:(NSData *)address;
  1026. + (int)familyFromAddress:(NSData *)address;
  1027.  
  1028. + (BOOL)isIPv4Address:(NSData *)address;
  1029. + (BOOL)isIPv6Address:(NSData *)address;
  1030.  
  1031. + (BOOL)getHost:(NSString * __nullable * __nullable)hostPtr port:(uint16_t * __nullable)portPtr fromAddress:(NSData *)address;
  1032. + (BOOL)getHost:(NSString * __nullable * __nullable)hostPtr port:(uint16_t * __nullable)portPtr family:(int * __nullable)afPtr fromAddress:(NSData *)address;
  1033.  
  1034. @end
  1035.  
  1036. NS_ASSUME_NONNULL_END
  1037.