Updated CocoaAsyncSocket. Added SO_REUSEPORT
This commit is contained in:
parent
cfcb081d61
commit
6f62be0d6e
|
@ -13,14 +13,14 @@
|
||||||
#import <TargetConditionals.h>
|
#import <TargetConditionals.h>
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
extern NSString *const GCDAsyncUdpSocketException;
|
extern NSString *const GCDAsyncUdpSocketException;
|
||||||
extern NSString *const GCDAsyncUdpSocketErrorDomain;
|
extern NSString *const GCDAsyncUdpSocketErrorDomain;
|
||||||
|
|
||||||
extern NSString *const GCDAsyncUdpSocketQueueName;
|
extern NSString *const GCDAsyncUdpSocketQueueName;
|
||||||
extern NSString *const GCDAsyncUdpSocketThreadName;
|
extern NSString *const GCDAsyncUdpSocketThreadName;
|
||||||
|
|
||||||
enum GCDAsyncUdpSocketError
|
typedef NS_ENUM(NSInteger, GCDAsyncUdpSocketError) {
|
||||||
{
|
|
||||||
GCDAsyncUdpSocketNoError = 0, // Never used
|
GCDAsyncUdpSocketNoError = 0, // Never used
|
||||||
GCDAsyncUdpSocketBadConfigError, // Invalid configuration
|
GCDAsyncUdpSocketBadConfigError, // Invalid configuration
|
||||||
GCDAsyncUdpSocketBadParamError, // Invalid parameter was passed
|
GCDAsyncUdpSocketBadParamError, // Invalid parameter was passed
|
||||||
|
@ -28,7 +28,59 @@ enum GCDAsyncUdpSocketError
|
||||||
GCDAsyncUdpSocketClosedError, // The socket was closed
|
GCDAsyncUdpSocketClosedError, // The socket was closed
|
||||||
GCDAsyncUdpSocketOtherError, // Description provided in userInfo
|
GCDAsyncUdpSocketOtherError, // Description provided in userInfo
|
||||||
};
|
};
|
||||||
typedef enum GCDAsyncUdpSocketError GCDAsyncUdpSocketError;
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#pragma mark -
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@class GCDAsyncUdpSocket;
|
||||||
|
|
||||||
|
@protocol GCDAsyncUdpSocketDelegate <NSObject>
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By design, UDP is a connectionless protocol, and connecting is not needed.
|
||||||
|
* However, you may optionally choose to connect to a particular host for reasons
|
||||||
|
* outlined in the documentation for the various connect methods listed above.
|
||||||
|
*
|
||||||
|
* This method is called if one of the connect methods are invoked, and the connection is successful.
|
||||||
|
**/
|
||||||
|
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By design, UDP is a connectionless protocol, and connecting is not needed.
|
||||||
|
* However, you may optionally choose to connect to a particular host for reasons
|
||||||
|
* outlined in the documentation for the various connect methods listed above.
|
||||||
|
*
|
||||||
|
* This method is called if one of the connect methods are invoked, and the connection fails.
|
||||||
|
* This may happen, for example, if a domain name is given for the host and the domain name is unable to be resolved.
|
||||||
|
**/
|
||||||
|
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotConnect:(NSError * _Nullable)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the datagram with the given tag has been sent.
|
||||||
|
**/
|
||||||
|
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if an error occurs while trying to send a datagram.
|
||||||
|
* This could be due to a timeout, or something more serious such as the data being too large to fit in a sigle packet.
|
||||||
|
**/
|
||||||
|
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError * _Nullable)error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the socket has received the requested datagram.
|
||||||
|
**/
|
||||||
|
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
|
||||||
|
fromAddress:(NSData *)address
|
||||||
|
withFilterContext:(nullable id)filterContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the socket is closed.
|
||||||
|
**/
|
||||||
|
- (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError * _Nullable)error;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You may optionally set a receive filter for the socket.
|
* You may optionally set a receive filter for the socket.
|
||||||
|
@ -78,7 +130,7 @@ typedef enum GCDAsyncUdpSocketError GCDAsyncUdpSocketError;
|
||||||
* [udpSocket setReceiveFilter:filter withQueue:myParsingQueue];
|
* [udpSocket setReceiveFilter:filter withQueue:myParsingQueue];
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
typedef BOOL (^GCDAsyncUdpSocketReceiveFilterBlock)(NSData *data, NSData *address, id *context);
|
typedef BOOL (^GCDAsyncUdpSocketReceiveFilterBlock)(NSData *data, NSData *address, id __nullable * __nonnull context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You may optionally set a send filter for the socket.
|
* You may optionally set a send filter for the socket.
|
||||||
|
@ -126,24 +178,24 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
*
|
*
|
||||||
* The delegate queue and socket queue can optionally be the same.
|
* The delegate queue and socket queue can optionally be the same.
|
||||||
**/
|
**/
|
||||||
- (id)init;
|
- (instancetype)init;
|
||||||
- (id)initWithSocketQueue:(dispatch_queue_t)sq;
|
- (instancetype)initWithSocketQueue:(nullable dispatch_queue_t)sq;
|
||||||
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq;
|
- (instancetype)initWithDelegate:(nullable id <GCDAsyncUdpSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq;
|
||||||
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq;
|
- (instancetype)initWithDelegate:(nullable id <GCDAsyncUdpSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq socketQueue:(nullable dispatch_queue_t)sq;
|
||||||
|
|
||||||
#pragma mark Configuration
|
#pragma mark Configuration
|
||||||
|
|
||||||
- (id)delegate;
|
- (nullable id <GCDAsyncUdpSocketDelegate>)delegate;
|
||||||
- (void)setDelegate:(id)delegate;
|
- (void)setDelegate:(nullable id <GCDAsyncUdpSocketDelegate>)delegate;
|
||||||
- (void)synchronouslySetDelegate:(id)delegate;
|
- (void)synchronouslySetDelegate:(nullable id <GCDAsyncUdpSocketDelegate>)delegate;
|
||||||
|
|
||||||
- (dispatch_queue_t)delegateQueue;
|
- (nullable dispatch_queue_t)delegateQueue;
|
||||||
- (void)setDelegateQueue:(dispatch_queue_t)delegateQueue;
|
- (void)setDelegateQueue:(nullable dispatch_queue_t)delegateQueue;
|
||||||
- (void)synchronouslySetDelegateQueue:(dispatch_queue_t)delegateQueue;
|
- (void)synchronouslySetDelegateQueue:(nullable dispatch_queue_t)delegateQueue;
|
||||||
|
|
||||||
- (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr;
|
- (void)getDelegate:(id <GCDAsyncUdpSocketDelegate> __nullable * __nullable)delegatePtr delegateQueue:(dispatch_queue_t __nullable * __nullable)delegateQueuePtr;
|
||||||
- (void)setDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
|
- (void)setDelegate:(nullable id <GCDAsyncUdpSocketDelegate>)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
|
||||||
- (void)synchronouslySetDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
|
- (void)synchronouslySetDelegate:(nullable id <GCDAsyncUdpSocketDelegate>)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By default, both IPv4 and IPv6 are enabled.
|
* By default, both IPv4 and IPv6 are enabled.
|
||||||
|
@ -179,7 +231,7 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets/Sets the maximum size of the buffer that will be allocated for receive operations.
|
* Gets/Sets the maximum size of the buffer that will be allocated for receive operations.
|
||||||
* The default maximum size is 9216 bytes.
|
* The default maximum size is 65535 bytes.
|
||||||
*
|
*
|
||||||
* The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535.
|
* The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535.
|
||||||
* The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295.
|
* The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295.
|
||||||
|
@ -199,12 +251,27 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
- (uint32_t)maxReceiveIPv6BufferSize;
|
- (uint32_t)maxReceiveIPv6BufferSize;
|
||||||
- (void)setMaxReceiveIPv6BufferSize:(uint32_t)max;
|
- (void)setMaxReceiveIPv6BufferSize:(uint32_t)max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets/Sets the maximum size of the buffer that will be allocated for send operations.
|
||||||
|
* The default maximum size is 65535 bytes.
|
||||||
|
*
|
||||||
|
* Given that a typical link MTU is 1500 bytes, a large UDP datagram will have to be
|
||||||
|
* fragmented, and that’s both expensive and risky (if one fragment goes missing, the
|
||||||
|
* entire datagram is lost). You are much better off sending a large number of smaller
|
||||||
|
* UDP datagrams, preferably using a path MTU algorithm to avoid fragmentation.
|
||||||
|
*
|
||||||
|
* You must set it before the sockt is created otherwise it won't work.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
- (uint16_t)maxSendBufferSize;
|
||||||
|
- (void)setMaxSendBufferSize:(uint16_t)max;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User data allows you to associate arbitrary information with the socket.
|
* User data allows you to associate arbitrary information with the socket.
|
||||||
* This data is not used internally in any way.
|
* This data is not used internally in any way.
|
||||||
**/
|
**/
|
||||||
- (id)userData;
|
- (nullable id)userData;
|
||||||
- (void)setUserData:(id)arbitraryUserData;
|
- (void)setUserData:(nullable id)arbitraryUserData;
|
||||||
|
|
||||||
#pragma mark Diagnostics
|
#pragma mark Diagnostics
|
||||||
|
|
||||||
|
@ -217,16 +284,16 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* Note: Address info may not be available until after the socket has been binded, connected
|
* Note: Address info may not be available until after the socket has been binded, connected
|
||||||
* or until after data has been sent.
|
* or until after data has been sent.
|
||||||
**/
|
**/
|
||||||
- (NSData *)localAddress;
|
- (nullable NSData *)localAddress;
|
||||||
- (NSString *)localHost;
|
- (nullable NSString *)localHost;
|
||||||
- (uint16_t)localPort;
|
- (uint16_t)localPort;
|
||||||
|
|
||||||
- (NSData *)localAddress_IPv4;
|
- (nullable NSData *)localAddress_IPv4;
|
||||||
- (NSString *)localHost_IPv4;
|
- (nullable NSString *)localHost_IPv4;
|
||||||
- (uint16_t)localPort_IPv4;
|
- (uint16_t)localPort_IPv4;
|
||||||
|
|
||||||
- (NSData *)localAddress_IPv6;
|
- (nullable NSData *)localAddress_IPv6;
|
||||||
- (NSString *)localHost_IPv6;
|
- (nullable NSString *)localHost_IPv6;
|
||||||
- (uint16_t)localPort_IPv6;
|
- (uint16_t)localPort_IPv6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -239,8 +306,8 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* will not be available unless the socket is explicitly connected to a remote host/port.
|
* will not be available unless the socket is explicitly connected to a remote host/port.
|
||||||
* If the socket is not connected, these methods will return nil / 0.
|
* If the socket is not connected, these methods will return nil / 0.
|
||||||
**/
|
**/
|
||||||
- (NSData *)connectedAddress;
|
- (nullable NSData *)connectedAddress;
|
||||||
- (NSString *)connectedHost;
|
- (nullable NSString *)connectedHost;
|
||||||
- (uint16_t)connectedPort;
|
- (uint16_t)connectedPort;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -319,7 +386,7 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* On success, returns YES.
|
* On success, returns YES.
|
||||||
* Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass NULL for errPtr.
|
* Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass NULL for errPtr.
|
||||||
**/
|
**/
|
||||||
- (BOOL)bindToPort:(uint16_t)port interface:(NSString *)interface error:(NSError **)errPtr;
|
- (BOOL)bindToPort:(uint16_t)port interface:(nullable NSString *)interface error:(NSError **)errPtr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds the UDP socket to the given address, specified as a sockaddr structure wrapped in a NSData object.
|
* Binds the UDP socket to the given address, specified as a sockaddr structure wrapped in a NSData object.
|
||||||
|
@ -418,10 +485,21 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* On success, returns YES.
|
* On success, returns YES.
|
||||||
* Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
|
* Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
|
||||||
**/
|
**/
|
||||||
- (BOOL)joinMulticastGroup:(NSString *)group onInterface:(NSString *)interface error:(NSError **)errPtr;
|
- (BOOL)joinMulticastGroup:(NSString *)group onInterface:(nullable NSString *)interface error:(NSError **)errPtr;
|
||||||
|
|
||||||
- (BOOL)leaveMulticastGroup:(NSString *)group error:(NSError **)errPtr;
|
- (BOOL)leaveMulticastGroup:(NSString *)group error:(NSError **)errPtr;
|
||||||
- (BOOL)leaveMulticastGroup:(NSString *)group onInterface:(NSString *)interface error:(NSError **)errPtr;
|
- (BOOL)leaveMulticastGroup:(NSString *)group onInterface:(nullable NSString *)interface error:(NSError **)errPtr;
|
||||||
|
|
||||||
|
#pragma mark Reuse Port
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, only one socket can be bound to a given IP address + port at a time.
|
||||||
|
* To enable multiple processes to simultaneously bind to the same address+port,
|
||||||
|
* you need to enable this functionality in the socket. All processes that wish to
|
||||||
|
* use the address+port simultaneously must all enable reuse port on the socket
|
||||||
|
* bound to that port.
|
||||||
|
**/
|
||||||
|
- (BOOL)enableReusePort:(BOOL)flag error:(NSError **)errPtr;
|
||||||
|
|
||||||
#pragma mark Broadcast
|
#pragma mark Broadcast
|
||||||
|
|
||||||
|
@ -597,7 +675,7 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* Note: This method invokes setSendFilter:withQueue:isAsynchronous: (documented below),
|
* Note: This method invokes setSendFilter:withQueue:isAsynchronous: (documented below),
|
||||||
* passing YES for the isAsynchronous parameter.
|
* passing YES for the isAsynchronous parameter.
|
||||||
**/
|
**/
|
||||||
- (void)setSendFilter:(GCDAsyncUdpSocketSendFilterBlock)filterBlock withQueue:(dispatch_queue_t)filterQueue;
|
- (void)setSendFilter:(nullable GCDAsyncUdpSocketSendFilterBlock)filterBlock withQueue:(nullable dispatch_queue_t)filterQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The receive filter can be run via dispatch_async or dispatch_sync.
|
* The receive filter can be run via dispatch_async or dispatch_sync.
|
||||||
|
@ -612,8 +690,8 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* then you cannot perform any tasks which may invoke dispatch_sync on the socket queue.
|
* then you cannot perform any tasks which may invoke dispatch_sync on the socket queue.
|
||||||
* For example, you can't query properties on the socket.
|
* For example, you can't query properties on the socket.
|
||||||
**/
|
**/
|
||||||
- (void)setSendFilter:(GCDAsyncUdpSocketSendFilterBlock)filterBlock
|
- (void)setSendFilter:(nullable GCDAsyncUdpSocketSendFilterBlock)filterBlock
|
||||||
withQueue:(dispatch_queue_t)filterQueue
|
withQueue:(nullable dispatch_queue_t)filterQueue
|
||||||
isAsynchronous:(BOOL)isAsynchronous;
|
isAsynchronous:(BOOL)isAsynchronous;
|
||||||
|
|
||||||
#pragma mark Receiving
|
#pragma mark Receiving
|
||||||
|
@ -729,7 +807,7 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* Note: This method invokes setReceiveFilter:withQueue:isAsynchronous: (documented below),
|
* Note: This method invokes setReceiveFilter:withQueue:isAsynchronous: (documented below),
|
||||||
* passing YES for the isAsynchronous parameter.
|
* passing YES for the isAsynchronous parameter.
|
||||||
**/
|
**/
|
||||||
- (void)setReceiveFilter:(GCDAsyncUdpSocketReceiveFilterBlock)filterBlock withQueue:(dispatch_queue_t)filterQueue;
|
- (void)setReceiveFilter:(nullable GCDAsyncUdpSocketReceiveFilterBlock)filterBlock withQueue:(nullable dispatch_queue_t)filterQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The receive filter can be run via dispatch_async or dispatch_sync.
|
* The receive filter can be run via dispatch_async or dispatch_sync.
|
||||||
|
@ -744,8 +822,8 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* then you cannot perform any tasks which may invoke dispatch_sync on the socket queue.
|
* then you cannot perform any tasks which may invoke dispatch_sync on the socket queue.
|
||||||
* For example, you can't query properties on the socket.
|
* For example, you can't query properties on the socket.
|
||||||
**/
|
**/
|
||||||
- (void)setReceiveFilter:(GCDAsyncUdpSocketReceiveFilterBlock)filterBlock
|
- (void)setReceiveFilter:(nullable GCDAsyncUdpSocketReceiveFilterBlock)filterBlock
|
||||||
withQueue:(dispatch_queue_t)filterQueue
|
withQueue:(nullable dispatch_queue_t)filterQueue
|
||||||
isAsynchronous:(BOOL)isAsynchronous;
|
isAsynchronous:(BOOL)isAsynchronous;
|
||||||
|
|
||||||
#pragma mark Closing
|
#pragma mark Closing
|
||||||
|
@ -897,8 +975,8 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* However, if you need one for any reason,
|
* However, if you need one for any reason,
|
||||||
* these methods are a convenient way to get access to a safe instance of one.
|
* these methods are a convenient way to get access to a safe instance of one.
|
||||||
**/
|
**/
|
||||||
- (CFReadStreamRef)readStream;
|
- (nullable CFReadStreamRef)readStream;
|
||||||
- (CFWriteStreamRef)writeStream;
|
- (nullable CFWriteStreamRef)writeStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is only available from within the context of a performBlock: invocation.
|
* This method is only available from within the context of a performBlock: invocation.
|
||||||
|
@ -931,66 +1009,16 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
|
||||||
* Extracting host/port/family information from raw address data.
|
* Extracting host/port/family information from raw address data.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
+ (NSString *)hostFromAddress:(NSData *)address;
|
+ (nullable NSString *)hostFromAddress:(NSData *)address;
|
||||||
+ (uint16_t)portFromAddress:(NSData *)address;
|
+ (uint16_t)portFromAddress:(NSData *)address;
|
||||||
+ (int)familyFromAddress:(NSData *)address;
|
+ (int)familyFromAddress:(NSData *)address;
|
||||||
|
|
||||||
+ (BOOL)isIPv4Address:(NSData *)address;
|
+ (BOOL)isIPv4Address:(NSData *)address;
|
||||||
+ (BOOL)isIPv6Address:(NSData *)address;
|
+ (BOOL)isIPv6Address:(NSData *)address;
|
||||||
|
|
||||||
+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address;
|
+ (BOOL)getHost:(NSString * __nullable * __nullable)hostPtr port:(uint16_t * __nullable)portPtr fromAddress:(NSData *)address;
|
||||||
+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr family:(int *)afPtr fromAddress:(NSData *)address;
|
+ (BOOL)getHost:(NSString * __nullable * __nullable)hostPtr port:(uint16_t * __nullable)portPtr family:(int * __nullable)afPtr fromAddress:(NSData *)address;
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
#pragma mark -
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@protocol GCDAsyncUdpSocketDelegate
|
|
||||||
@optional
|
|
||||||
|
|
||||||
/**
|
|
||||||
* By design, UDP is a connectionless protocol, and connecting is not needed.
|
|
||||||
* However, you may optionally choose to connect to a particular host for reasons
|
|
||||||
* outlined in the documentation for the various connect methods listed above.
|
|
||||||
*
|
|
||||||
* This method is called if one of the connect methods are invoked, and the connection is successful.
|
|
||||||
**/
|
|
||||||
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* By design, UDP is a connectionless protocol, and connecting is not needed.
|
|
||||||
* However, you may optionally choose to connect to a particular host for reasons
|
|
||||||
* outlined in the documentation for the various connect methods listed above.
|
|
||||||
*
|
|
||||||
* This method is called if one of the connect methods are invoked, and the connection fails.
|
|
||||||
* This may happen, for example, if a domain name is given for the host and the domain name is unable to be resolved.
|
|
||||||
**/
|
|
||||||
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotConnect:(NSError *)error;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the datagram with the given tag has been sent.
|
|
||||||
**/
|
|
||||||
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called if an error occurs while trying to send a datagram.
|
|
||||||
* This could be due to a timeout, or something more serious such as the data being too large to fit in a sigle packet.
|
|
||||||
**/
|
|
||||||
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the socket has received the requested datagram.
|
|
||||||
**/
|
|
||||||
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
|
|
||||||
fromAddress:(NSData *)address
|
|
||||||
withFilterContext:(id)filterContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the socket is closed.
|
|
||||||
**/
|
|
||||||
- (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -167,6 +167,8 @@ enum GCDAsyncUdpSocketConfig
|
||||||
uint16_t max4ReceiveSize;
|
uint16_t max4ReceiveSize;
|
||||||
uint32_t max6ReceiveSize;
|
uint32_t max6ReceiveSize;
|
||||||
|
|
||||||
|
uint16_t maxSendSize;
|
||||||
|
|
||||||
int socket4FD;
|
int socket4FD;
|
||||||
int socket6FD;
|
int socket6FD;
|
||||||
|
|
||||||
|
@ -350,14 +352,14 @@ enum GCDAsyncUdpSocketConfig
|
||||||
return [self initWithDelegate:nil delegateQueue:NULL socketQueue:sq];
|
return [self initWithDelegate:nil delegateQueue:NULL socketQueue:sq];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq
|
- (id)initWithDelegate:(id <GCDAsyncUdpSocketDelegate>)aDelegate delegateQueue:(dispatch_queue_t)dq
|
||||||
{
|
{
|
||||||
LogTrace();
|
LogTrace();
|
||||||
|
|
||||||
return [self initWithDelegate:aDelegate delegateQueue:dq socketQueue:NULL];
|
return [self initWithDelegate:aDelegate delegateQueue:dq socketQueue:NULL];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq
|
- (id)initWithDelegate:(id <GCDAsyncUdpSocketDelegate>)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq
|
||||||
{
|
{
|
||||||
LogTrace();
|
LogTrace();
|
||||||
|
|
||||||
|
@ -373,8 +375,10 @@ enum GCDAsyncUdpSocketConfig
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
max4ReceiveSize = 9216;
|
max4ReceiveSize = 65535;
|
||||||
max6ReceiveSize = 9216;
|
max6ReceiveSize = 65535;
|
||||||
|
|
||||||
|
maxSendSize = 65535;
|
||||||
|
|
||||||
socket4FD = SOCKET_NULL;
|
socket4FD = SOCKET_NULL;
|
||||||
socket6FD = SOCKET_NULL;
|
socket6FD = SOCKET_NULL;
|
||||||
|
@ -488,7 +492,7 @@ enum GCDAsyncUdpSocketConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDelegate:(id)newDelegate synchronously:(BOOL)synchronously
|
- (void)setDelegate:(id <GCDAsyncUdpSocketDelegate>)newDelegate synchronously:(BOOL)synchronously
|
||||||
{
|
{
|
||||||
dispatch_block_t block = ^{
|
dispatch_block_t block = ^{
|
||||||
delegate = newDelegate;
|
delegate = newDelegate;
|
||||||
|
@ -505,12 +509,12 @@ enum GCDAsyncUdpSocketConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDelegate:(id)newDelegate
|
- (void)setDelegate:(id <GCDAsyncUdpSocketDelegate>)newDelegate
|
||||||
{
|
{
|
||||||
[self setDelegate:newDelegate synchronously:NO];
|
[self setDelegate:newDelegate synchronously:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)synchronouslySetDelegate:(id)newDelegate
|
- (void)synchronouslySetDelegate:(id <GCDAsyncUdpSocketDelegate>)newDelegate
|
||||||
{
|
{
|
||||||
[self setDelegate:newDelegate synchronously:YES];
|
[self setDelegate:newDelegate synchronously:YES];
|
||||||
}
|
}
|
||||||
|
@ -566,7 +570,7 @@ enum GCDAsyncUdpSocketConfig
|
||||||
[self setDelegateQueue:newDelegateQueue synchronously:YES];
|
[self setDelegateQueue:newDelegateQueue synchronously:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr
|
- (void)getDelegate:(id <GCDAsyncUdpSocketDelegate> *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr
|
||||||
{
|
{
|
||||||
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
|
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
|
||||||
{
|
{
|
||||||
|
@ -588,7 +592,7 @@ enum GCDAsyncUdpSocketConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously
|
- (void)setDelegate:(id <GCDAsyncUdpSocketDelegate>)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously
|
||||||
{
|
{
|
||||||
dispatch_block_t block = ^{
|
dispatch_block_t block = ^{
|
||||||
|
|
||||||
|
@ -613,12 +617,12 @@ enum GCDAsyncUdpSocketConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
|
- (void)setDelegate:(id <GCDAsyncUdpSocketDelegate>)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
|
||||||
{
|
{
|
||||||
[self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:NO];
|
[self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)synchronouslySetDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
|
- (void)synchronouslySetDelegate:(id <GCDAsyncUdpSocketDelegate>)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
|
||||||
{
|
{
|
||||||
[self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:YES];
|
[self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:YES];
|
||||||
}
|
}
|
||||||
|
@ -864,6 +868,37 @@ enum GCDAsyncUdpSocketConfig
|
||||||
dispatch_async(socketQueue, block);
|
dispatch_async(socketQueue, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setMaxSendBufferSize:(uint16_t)max
|
||||||
|
{
|
||||||
|
dispatch_block_t block = ^{
|
||||||
|
|
||||||
|
LogVerbose(@"%@ %u", THIS_METHOD, (unsigned)max);
|
||||||
|
|
||||||
|
maxSendSize = max;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
|
||||||
|
block();
|
||||||
|
else
|
||||||
|
dispatch_async(socketQueue, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (uint16_t)maxSendBufferSize
|
||||||
|
{
|
||||||
|
__block uint16_t result = 0;
|
||||||
|
|
||||||
|
dispatch_block_t block = ^{
|
||||||
|
|
||||||
|
result = maxSendSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
|
||||||
|
block();
|
||||||
|
else
|
||||||
|
dispatch_sync(socketQueue, block);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
- (id)userData
|
- (id)userData
|
||||||
{
|
{
|
||||||
|
@ -906,9 +941,9 @@ enum GCDAsyncUdpSocketConfig
|
||||||
{
|
{
|
||||||
LogTrace();
|
LogTrace();
|
||||||
|
|
||||||
if (delegateQueue && [delegate respondsToSelector:@selector(udpSocket:didConnectToAddress:)])
|
__strong id theDelegate = delegate;
|
||||||
|
if (delegateQueue && [theDelegate respondsToSelector:@selector(udpSocket:didConnectToAddress:)])
|
||||||
{
|
{
|
||||||
id theDelegate = delegate;
|
|
||||||
NSData *address = [anAddress copy]; // In case param is NSMutableData
|
NSData *address = [anAddress copy]; // In case param is NSMutableData
|
||||||
|
|
||||||
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
||||||
|
@ -922,10 +957,9 @@ enum GCDAsyncUdpSocketConfig
|
||||||
{
|
{
|
||||||
LogTrace();
|
LogTrace();
|
||||||
|
|
||||||
if (delegateQueue && [delegate respondsToSelector:@selector(udpSocket:didNotConnect:)])
|
__strong id theDelegate = delegate;
|
||||||
|
if (delegateQueue && [theDelegate respondsToSelector:@selector(udpSocket:didNotConnect:)])
|
||||||
{
|
{
|
||||||
id theDelegate = delegate;
|
|
||||||
|
|
||||||
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
||||||
|
|
||||||
[theDelegate udpSocket:self didNotConnect:error];
|
[theDelegate udpSocket:self didNotConnect:error];
|
||||||
|
@ -937,10 +971,9 @@ enum GCDAsyncUdpSocketConfig
|
||||||
{
|
{
|
||||||
LogTrace();
|
LogTrace();
|
||||||
|
|
||||||
if (delegateQueue && [delegate respondsToSelector:@selector(udpSocket:didSendDataWithTag:)])
|
__strong id theDelegate = delegate;
|
||||||
|
if (delegateQueue && [theDelegate respondsToSelector:@selector(udpSocket:didSendDataWithTag:)])
|
||||||
{
|
{
|
||||||
id theDelegate = delegate;
|
|
||||||
|
|
||||||
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
||||||
|
|
||||||
[theDelegate udpSocket:self didSendDataWithTag:tag];
|
[theDelegate udpSocket:self didSendDataWithTag:tag];
|
||||||
|
@ -952,10 +985,9 @@ enum GCDAsyncUdpSocketConfig
|
||||||
{
|
{
|
||||||
LogTrace();
|
LogTrace();
|
||||||
|
|
||||||
if (delegateQueue && [delegate respondsToSelector:@selector(udpSocket:didNotSendDataWithTag:dueToError:)])
|
__strong id theDelegate = delegate;
|
||||||
|
if (delegateQueue && [theDelegate respondsToSelector:@selector(udpSocket:didNotSendDataWithTag:dueToError:)])
|
||||||
{
|
{
|
||||||
id theDelegate = delegate;
|
|
||||||
|
|
||||||
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
||||||
|
|
||||||
[theDelegate udpSocket:self didNotSendDataWithTag:tag dueToError:error];
|
[theDelegate udpSocket:self didNotSendDataWithTag:tag dueToError:error];
|
||||||
|
@ -969,10 +1001,9 @@ enum GCDAsyncUdpSocketConfig
|
||||||
|
|
||||||
SEL selector = @selector(udpSocket:didReceiveData:fromAddress:withFilterContext:);
|
SEL selector = @selector(udpSocket:didReceiveData:fromAddress:withFilterContext:);
|
||||||
|
|
||||||
if (delegateQueue && [delegate respondsToSelector:selector])
|
__strong id theDelegate = delegate;
|
||||||
|
if (delegateQueue && [theDelegate respondsToSelector:selector])
|
||||||
{
|
{
|
||||||
id theDelegate = delegate;
|
|
||||||
|
|
||||||
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
||||||
|
|
||||||
[theDelegate udpSocket:self didReceiveData:data fromAddress:address withFilterContext:context];
|
[theDelegate udpSocket:self didReceiveData:data fromAddress:address withFilterContext:context];
|
||||||
|
@ -984,10 +1015,9 @@ enum GCDAsyncUdpSocketConfig
|
||||||
{
|
{
|
||||||
LogTrace();
|
LogTrace();
|
||||||
|
|
||||||
if (delegateQueue && [delegate respondsToSelector:@selector(udpSocketDidClose:withError:)])
|
__strong id theDelegate = delegate;
|
||||||
|
if (delegateQueue && [theDelegate respondsToSelector:@selector(udpSocketDidClose:withError:)])
|
||||||
{
|
{
|
||||||
id theDelegate = delegate;
|
|
||||||
|
|
||||||
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
dispatch_async(delegateQueue, ^{ @autoreleasepool {
|
||||||
|
|
||||||
[theDelegate udpSocketDidClose:self withError:error];
|
[theDelegate udpSocketDidClose:self withError:error];
|
||||||
|
@ -1204,9 +1234,17 @@ enum GCDAsyncUdpSocketConfig
|
||||||
}
|
}
|
||||||
else if (res->ai_family == AF_INET6)
|
else if (res->ai_family == AF_INET6)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Fixes connection issues with IPv6, it is the same solution for udp socket.
|
||||||
|
// https://github.com/robbiehanson/CocoaAsyncSocket/issues/429#issuecomment-222477158
|
||||||
|
struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)res->ai_addr;
|
||||||
|
in_port_t *portPtr = &sockaddr->sin6_port;
|
||||||
|
if ((portPtr != NULL) && (*portPtr == 0)) {
|
||||||
|
*portPtr = htons(port);
|
||||||
|
}
|
||||||
|
|
||||||
// Found IPv6 address
|
// Found IPv6 address
|
||||||
// Wrap the native address structure and add to list
|
// Wrap the native address structure and add to list
|
||||||
|
|
||||||
[addresses addObject:[NSData dataWithBytes:res->ai_addr length:res->ai_addrlen]];
|
[addresses addObject:[NSData dataWithBytes:res->ai_addr length:res->ai_addrlen]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1983,6 +2021,39 @@ enum GCDAsyncUdpSocketConfig
|
||||||
return SOCKET_NULL;
|
return SOCKET_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535.
|
||||||
|
* The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295.
|
||||||
|
*
|
||||||
|
* The default maximum size of the UDP buffer in iOS is 9216 bytes.
|
||||||
|
*
|
||||||
|
* This is the reason of #222(GCD does not necessarily return the size of an entire UDP packet) and
|
||||||
|
* #535(GCDAsyncUDPSocket can not send data when data is greater than 9K)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Enlarge the maximum size of UDP packet.
|
||||||
|
* I can not ensure the protocol type now so that the max size is set to 65535 :)
|
||||||
|
**/
|
||||||
|
|
||||||
|
status = setsockopt(socketFD, SOL_SOCKET, SO_SNDBUF, (const char*)&maxSendSize, sizeof(int));
|
||||||
|
if (status == -1)
|
||||||
|
{
|
||||||
|
if (errPtr)
|
||||||
|
*errPtr = [self errnoErrorWithReason:@"Error setting send buffer size (setsockopt)"];
|
||||||
|
close(socketFD);
|
||||||
|
return SOCKET_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = setsockopt(socketFD, SOL_SOCKET, SO_RCVBUF, (const char*)&maxSendSize, sizeof(int));
|
||||||
|
if (status == -1)
|
||||||
|
{
|
||||||
|
if (errPtr)
|
||||||
|
*errPtr = [self errnoErrorWithReason:@"Error setting receive buffer size (setsockopt)"];
|
||||||
|
close(socketFD);
|
||||||
|
return SOCKET_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return socketFD;
|
return socketFD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3453,6 +3524,70 @@ enum GCDAsyncUdpSocketConfig
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#pragma mark Reuse port
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
- (BOOL)enableReusePort:(BOOL)flag error:(NSError **)errPtr
|
||||||
|
{
|
||||||
|
__block BOOL result = NO;
|
||||||
|
__block NSError *err = nil;
|
||||||
|
|
||||||
|
dispatch_block_t block = ^{ @autoreleasepool {
|
||||||
|
|
||||||
|
if (![self preOp:&err])
|
||||||
|
{
|
||||||
|
return_from_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & kDidCreateSockets) == 0)
|
||||||
|
{
|
||||||
|
if (![self createSockets:&err])
|
||||||
|
{
|
||||||
|
return_from_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int value = flag ? 1 : 0;
|
||||||
|
if (socket4FD != SOCKET_NULL)
|
||||||
|
{
|
||||||
|
int error = setsockopt(socket4FD, SOL_SOCKET, SO_REUSEPORT, (const void *)&value, sizeof(value));
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
err = [self errnoErrorWithReason:@"Error in setsockopt() function"];
|
||||||
|
|
||||||
|
return_from_block;
|
||||||
|
}
|
||||||
|
result = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket6FD != SOCKET_NULL)
|
||||||
|
{
|
||||||
|
int error = setsockopt(socket6FD, SOL_SOCKET, SO_REUSEPORT, (const void *)&value, sizeof(value));
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
err = [self errnoErrorWithReason:@"Error in setsockopt() function"];
|
||||||
|
|
||||||
|
return_from_block;
|
||||||
|
}
|
||||||
|
result = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
}};
|
||||||
|
|
||||||
|
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
|
||||||
|
block();
|
||||||
|
else
|
||||||
|
dispatch_sync(socketQueue, block);
|
||||||
|
|
||||||
|
if (errPtr)
|
||||||
|
*errPtr = err;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#pragma mark Broadcast
|
#pragma mark Broadcast
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -3526,6 +3661,8 @@ enum GCDAsyncUdpSocketConfig
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GCDAsyncUdpSendPacket *packet = [[GCDAsyncUdpSendPacket alloc] initWithData:data timeout:timeout tag:tag];
|
GCDAsyncUdpSendPacket *packet = [[GCDAsyncUdpSendPacket alloc] initWithData:data timeout:timeout tag:tag];
|
||||||
|
|
||||||
dispatch_async(socketQueue, ^{ @autoreleasepool {
|
dispatch_async(socketQueue, ^{ @autoreleasepool {
|
||||||
|
@ -4293,7 +4430,9 @@ enum GCDAsyncUdpSocketConfig
|
||||||
struct sockaddr_in sockaddr4;
|
struct sockaddr_in sockaddr4;
|
||||||
socklen_t sockaddr4len = sizeof(sockaddr4);
|
socklen_t sockaddr4len = sizeof(sockaddr4);
|
||||||
|
|
||||||
size_t bufSize = MIN(max4ReceiveSize, socket4FDBytesAvailable);
|
// #222: GCD does not necessarily return the size of an entire UDP packet
|
||||||
|
// from dispatch_source_get_data(), so we must use the maximum packet size.
|
||||||
|
size_t bufSize = max4ReceiveSize;
|
||||||
void *buf = malloc(bufSize);
|
void *buf = malloc(bufSize);
|
||||||
|
|
||||||
result = recvfrom(socket4FD, buf, bufSize, 0, (struct sockaddr *)&sockaddr4, &sockaddr4len);
|
result = recvfrom(socket4FD, buf, bufSize, 0, (struct sockaddr *)&sockaddr4, &sockaddr4len);
|
||||||
|
@ -4328,7 +4467,9 @@ enum GCDAsyncUdpSocketConfig
|
||||||
struct sockaddr_in6 sockaddr6;
|
struct sockaddr_in6 sockaddr6;
|
||||||
socklen_t sockaddr6len = sizeof(sockaddr6);
|
socklen_t sockaddr6len = sizeof(sockaddr6);
|
||||||
|
|
||||||
size_t bufSize = MIN(max6ReceiveSize, socket6FDBytesAvailable);
|
// #222: GCD does not necessarily return the size of an entire UDP packet
|
||||||
|
// from dispatch_source_get_data(), so we must use the maximum packet size.
|
||||||
|
size_t bufSize = max6ReceiveSize;
|
||||||
void *buf = malloc(bufSize);
|
void *buf = malloc(bufSize);
|
||||||
|
|
||||||
result = recvfrom(socket6FD, buf, bufSize, 0, (struct sockaddr *)&sockaddr6, &sockaddr6len);
|
result = recvfrom(socket6FD, buf, bufSize, 0, (struct sockaddr *)&sockaddr6, &sockaddr6len);
|
||||||
|
|
|
@ -96,6 +96,7 @@ NSString *const RCTUDPErrorDomain = @"RCTUDPErrorDomain";
|
||||||
|
|
||||||
[_udpSocket setMaxReceiveIPv4BufferSize:UINT16_MAX];
|
[_udpSocket setMaxReceiveIPv4BufferSize:UINT16_MAX];
|
||||||
[_udpSocket setMaxReceiveIPv6BufferSize:UINT16_MAX];
|
[_udpSocket setMaxReceiveIPv6BufferSize:UINT16_MAX];
|
||||||
|
[_udpSocket enableReusePort:true error:error];
|
||||||
|
|
||||||
BOOL result;
|
BOOL result;
|
||||||
if (address) {
|
if (address) {
|
||||||
|
|
Loading…
Reference in New Issue