GCDAsyncUdpSocket.h 47 KB

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