Subversion Repositories Mobile Apps.GyroMouse

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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