更新socket库

This commit is contained in:
祝发冬
2023-07-21 10:54:54 +08:00
parent cce27928e8
commit 85f50867ae
4 changed files with 3047 additions and 1515 deletions
+136 -95
View File
@@ -10,16 +10,17 @@
#import <Foundation/Foundation.h>
#import <dispatch/dispatch.h>
#import <TargetConditionals.h>
#import <Availability.h>
NS_ASSUME_NONNULL_BEGIN
extern NSString *const GCDAsyncUdpSocketException;
extern NSString *const GCDAsyncUdpSocketErrorDomain;
extern NSString *const GCDAsyncUdpSocketQueueName;
extern NSString *const GCDAsyncUdpSocketThreadName;
enum GCDAsyncUdpSocketError
{
typedef NS_ERROR_ENUM(GCDAsyncUdpSocketErrorDomain, GCDAsyncUdpSocketError) {
GCDAsyncUdpSocketNoError = 0, // Never used
GCDAsyncUdpSocketBadConfigError, // Invalid configuration
GCDAsyncUdpSocketBadParamError, // Invalid parameter was passed
@@ -27,7 +28,59 @@ enum GCDAsyncUdpSocketError
GCDAsyncUdpSocketClosedError, // The socket was closed
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.
@@ -77,7 +130,7 @@ typedef enum GCDAsyncUdpSocketError GCDAsyncUdpSocketError;
* [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.
@@ -125,24 +178,24 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
*
* The delegate queue and socket queue can optionally be the same.
**/
- (id)init;
- (id)initWithSocketQueue:(dispatch_queue_t)sq;
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq;
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq;
- (instancetype)init;
- (instancetype)initWithSocketQueue:(nullable dispatch_queue_t)sq;
- (instancetype)initWithDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq;
- (instancetype)initWithDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq socketQueue:(nullable dispatch_queue_t)sq NS_DESIGNATED_INITIALIZER;
#pragma mark Configuration
- (id)delegate;
- (void)setDelegate:(id)delegate;
- (void)synchronouslySetDelegate:(id)delegate;
- (nullable id<GCDAsyncUdpSocketDelegate>)delegate;
- (void)setDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)delegate;
- (void)synchronouslySetDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)delegate;
- (dispatch_queue_t)delegateQueue;
- (void)setDelegateQueue:(dispatch_queue_t)delegateQueue;
- (void)synchronouslySetDelegateQueue:(dispatch_queue_t)delegateQueue;
- (nullable dispatch_queue_t)delegateQueue;
- (void)setDelegateQueue:(nullable dispatch_queue_t)delegateQueue;
- (void)synchronouslySetDelegateQueue:(nullable dispatch_queue_t)delegateQueue;
- (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr;
- (void)setDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
- (void)synchronouslySetDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
- (void)getDelegate:(id<GCDAsyncUdpSocketDelegate> __nullable * __nullable)delegatePtr delegateQueue:(dispatch_queue_t __nullable * __nullable)delegateQueuePtr;
- (void)setDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
- (void)synchronouslySetDelegate:(nullable id<GCDAsyncUdpSocketDelegate>)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
/**
* By default, both IPv4 and IPv6 are enabled.
@@ -178,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.
* 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 IPv6 UDP packet is UINT32_MAX = 4294967295.
@@ -198,12 +251,27 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
- (uint32_t)maxReceiveIPv6BufferSize;
- (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 thats 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.
* This data is not used internally in any way.
**/
- (id)userData;
- (void)setUserData:(id)arbitraryUserData;
- (nullable id)userData;
- (void)setUserData:(nullable id)arbitraryUserData;
#pragma mark Diagnostics
@@ -216,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
* or until after data has been sent.
**/
- (NSData *)localAddress;
- (NSString *)localHost;
- (nullable NSData *)localAddress;
- (nullable NSString *)localHost;
- (uint16_t)localPort;
- (NSData *)localAddress_IPv4;
- (NSString *)localHost_IPv4;
- (nullable NSData *)localAddress_IPv4;
- (nullable NSString *)localHost_IPv4;
- (uint16_t)localPort_IPv4;
- (NSData *)localAddress_IPv6;
- (NSString *)localHost_IPv6;
- (nullable NSData *)localAddress_IPv6;
- (nullable NSString *)localHost_IPv6;
- (uint16_t)localPort_IPv6;
/**
@@ -238,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.
* If the socket is not connected, these methods will return nil / 0.
**/
- (NSData *)connectedAddress;
- (NSString *)connectedHost;
- (nullable NSData *)connectedAddress;
- (nullable NSString *)connectedHost;
- (uint16_t)connectedPort;
/**
@@ -318,7 +386,7 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* On success, returns YES.
* 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.
@@ -417,10 +485,33 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* On success, returns YES.
* 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 onInterface:(NSString *)interface error:(NSError **)errPtr;
- (BOOL)leaveMulticastGroup:(NSString *)group onInterface:(nullable NSString *)interface error:(NSError **)errPtr;
/**
* Send multicast on a specified interface.
* For IPv4, interface should be the the IP address of the interface (eg @"192.168.10.1").
* For IPv6, interface should be the a network interface name (eg @"en0").
*
* On success, returns YES.
* Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr.
**/
- (BOOL)sendIPv4MulticastOnInterface:(NSString*)interface error:(NSError **)errPtr;
- (BOOL)sendIPv6MulticastOnInterface:(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
@@ -545,7 +636,7 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* If data is nil or zero-length, this method does nothing.
* If passing NSMutableData, please read the thread-safety notice below.
*
* @param address
* @param remoteAddr
* The address to send the data to (specified as a sockaddr structure wrapped in a NSData object).
*
* @param timeout
@@ -596,7 +687,7 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* Note: This method invokes setSendFilter:withQueue:isAsynchronous: (documented below),
* 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.
@@ -611,8 +702,8 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* 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.
**/
- (void)setSendFilter:(GCDAsyncUdpSocketSendFilterBlock)filterBlock
withQueue:(dispatch_queue_t)filterQueue
- (void)setSendFilter:(nullable GCDAsyncUdpSocketSendFilterBlock)filterBlock
withQueue:(nullable dispatch_queue_t)filterQueue
isAsynchronous:(BOOL)isAsynchronous;
#pragma mark Receiving
@@ -728,7 +819,7 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* Note: This method invokes setReceiveFilter:withQueue:isAsynchronous: (documented below),
* 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.
@@ -743,8 +834,8 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* 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.
**/
- (void)setReceiveFilter:(GCDAsyncUdpSocketReceiveFilterBlock)filterBlock
withQueue:(dispatch_queue_t)filterQueue
- (void)setReceiveFilter:(nullable GCDAsyncUdpSocketReceiveFilterBlock)filterBlock
withQueue:(nullable dispatch_queue_t)filterQueue
isAsynchronous:(BOOL)isAsynchronous;
#pragma mark Closing
@@ -896,8 +987,8 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* However, if you need one for any reason,
* these methods are a convenient way to get access to a safe instance of one.
**/
- (CFReadStreamRef)readStream;
- (CFWriteStreamRef)writeStream;
- (nullable CFReadStreamRef)readStream;
- (nullable CFWriteStreamRef)writeStream;
/**
* This method is only available from within the context of a performBlock: invocation.
@@ -930,66 +1021,16 @@ typedef BOOL (^GCDAsyncUdpSocketSendFilterBlock)(NSData *data, NSData *address,
* Extracting host/port/family information from raw address data.
**/
+ (NSString *)hostFromAddress:(NSData *)address;
+ (nullable NSString *)hostFromAddress:(NSData *)address;
+ (uint16_t)portFromAddress:(NSData *)address;
+ (int)familyFromAddress:(NSData *)address;
+ (BOOL)isIPv4Address:(NSData *)address;
+ (BOOL)isIPv6Address:(NSData *)address;
+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address;
+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr family:(int *)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;
+ (BOOL)getHost:(NSString * __nullable * __nullable)hostPtr port:(uint16_t * __nullable)portPtr fromAddress:(NSData *)address;
+ (BOOL)getHost:(NSString * __nullable * __nullable)hostPtr port:(uint16_t * __nullable)portPtr family:(int * __nullable)afPtr fromAddress:(NSData *)address;
@end
NS_ASSUME_NONNULL_END