ObjFW  Check-in [da2dd2dde5]

Overview
Comment:OFUDPSocket: Use a delegate for async operations
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: da2dd2dde52b0a416211808540adc0a45fe2e1110f1c9d14ec7e3571c77d94ae
User & Date: js on 2018-12-08 18:55:26
Other Links: manifest | tags
Context
2018-12-08
22:01
Minor fix for OFDNSResolver and OFRunLoop check-in: 6387b16864 user: js tags: trunk
18:55
OFUDPSocket: Use a delegate for async operations check-in: da2dd2dde5 user: js tags: trunk
17:05
OFTLSSocketDelegate: Inherit OFTCPSocketDelegate check-in: d3a4cda21a user: js tags: trunk
Changes

Modified src/OFDNSResolver.h from [e43a0539a7] to [3471ccf224].

18
19
20
21
22
23
24


25
26
27
28
29
30
31
#import "OFObject.h"
#import "OFDNSResourceRecord.h"
#import "OFRunLoop.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN



@class OFArray OF_GENERIC(ObjectType);
@class OFDNSResolverQuery;
@class OFDate;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFNumber;
@class OFUDPSocket;







>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#import "OFObject.h"
#import "OFDNSResourceRecord.h"
#import "OFRunLoop.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

#define OF_DNS_RESOLVER_BUFFER_LENGTH 512

@class OFArray OF_GENERIC(ObjectType);
@class OFDNSResolverQuery;
@class OFDate;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFNumber;
@class OFUDPSocket;
83
84
85
86
87
88
89

90
91
92
93
94
95
96
	bool _usesTCP;
	of_time_interval_t _configReloadInterval;
	OFDate *_lastConfigReload;
	OFUDPSocket *_IPv4Socket;
#ifdef OF_HAVE_IPV6
	OFUDPSocket *_IPv6Socket;
#endif

	OFMutableDictionary OF_GENERIC(OFNumber *, OFDNSResolverQuery *)
	    *_queries;
}

/*!
 * @brief A dictionary of static hosts.
 *







>







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
	bool _usesTCP;
	of_time_interval_t _configReloadInterval;
	OFDate *_lastConfigReload;
	OFUDPSocket *_IPv4Socket;
#ifdef OF_HAVE_IPV6
	OFUDPSocket *_IPv6Socket;
#endif
	char _buffer[OF_DNS_RESOLVER_BUFFER_LENGTH];
	OFMutableDictionary OF_GENERIC(OFNumber *, OFDNSResolverQuery *)
	    *_queries;
}

/*!
 * @brief A dictionary of static hosts.
 *

Modified src/OFDNSResolver.m from [e676e364e2] to [55442709eb].

67
68
69
70
71
72
73


74
75
76
77
78
79
80
# include <3ds.h>
#endif

#ifndef SOCK_DNS
# define SOCK_DNS 0
#endif



/*
 * RFC 1035 doesn't specify if pointers to pointers are allowed, and if so how
 * many. Since it's unspecified, we have to assume that it might happen, but we
 * also want to limit it to avoid DoS. Limiting it to 16 levels of pointers and
 * immediately rejecting pointers to itself seems like a fair balance.
 */
#define MAX_ALLOWED_POINTERS 16







>
>







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# include <3ds.h>
#endif

#ifndef SOCK_DNS
# define SOCK_DNS 0
#endif

#define BUFFER_LENGTH OF_DNS_RESOLVER_BUFFER_LENGTH

/*
 * RFC 1035 doesn't specify if pointers to pointers are allowed, and if so how
 * many. Since it's unspecified, we have to assume that it might happen, but we
 * also want to limit it to avoid DoS. Limiting it to 16 levels of pointers and
 * immediately rejecting pointers to itself seems like a fair balance.
 */
#define MAX_ALLOWED_POINTERS 16
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
-	(void)resolver: (OFDNSResolver *)resolver
  didResolveDomainName: (OFString *)domainName
       socketAddresses: (OFData *)socketAddresses
	       context: (id)context
	     exception: (id)exception;
@end

@interface OFDNSResolver ()
- (void)of_setDefaults;
- (void)of_obtainSystemConfig;
#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_3DS)
- (void)of_parseHosts: (OFString *)path;
# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
- (void)of_parseResolvConf: (OFString *)path;
- (void)of_parseResolvConfOption: (OFString *)option;







|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
-	(void)resolver: (OFDNSResolver *)resolver
  didResolveDomainName: (OFString *)domainName
       socketAddresses: (OFData *)socketAddresses
	       context: (id)context
	     exception: (id)exception;
@end

@interface OFDNSResolver () <OFUDPSocketDelegate>
- (void)of_setDefaults;
- (void)of_obtainSystemConfig;
#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_3DS)
- (void)of_parseHosts: (OFString *)path;
# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
- (void)of_parseResolvConf: (OFString *)path;
- (void)of_parseResolvConfOption: (OFString *)option;
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
	   runLoopMode: (of_run_loop_mode_t)runLoopMode
		target: (id)target
	      selector: (SEL)selector
	       context: (id)context;
- (void)of_sendQuery: (OFDNSResolverQuery *)query
	 runLoopMode: (of_run_loop_mode_t)runLoopMode;
- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query;
- (size_t)of_socket: (OFUDPSocket *)sock
      didSendBuffer: (void **)buffer
	  bytesSent: (size_t)bytesSent
	   receiver: (of_socket_address_t *)receiver
	    context: (OFDNSResolverQuery *)query
	  exception: (id)exception;
-      (bool)of_socket: (OFUDPSocket *)sock
  didReceiveIntoBuffer: (unsigned char *)buffer
		length: (size_t)length
		sender: (of_socket_address_t)sender
	       context: (id)context
	     exception: (id)exception;
@end

#ifndef OF_WII
static OFString *
domainFromHostname(void)
{
	char hostname[256];







<
<
<
<
<
<
<
<
<
<
<
<







259
260
261
262
263
264
265












266
267
268
269
270
271
272
	   runLoopMode: (of_run_loop_mode_t)runLoopMode
		target: (id)target
	      selector: (SEL)selector
	       context: (id)context;
- (void)of_sendQuery: (OFDNSResolverQuery *)query
	 runLoopMode: (of_run_loop_mode_t)runLoopMode;
- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query;












@end

#ifndef OF_WII
static OFString *
domainFromHostname(void)
{
	char hostname[256];
1287
1288
1289
1290
1291
1292
1293

1294
1295

1296
1297
1298
1299
1300
1301
1302
	[self close];

	[_staticHosts release];
	[_nameServers release];
	[_localDomain release];
	[_searchDomains release];
	[_lastConfigReload release];

	[_IPv4Socket release];
#ifdef OF_HAVE_IPV6

	[_IPv6Socket release];
#endif
	[_queries release];

	[super dealloc];
}








>


>







1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
	[self close];

	[_staticHosts release];
	[_nameServers release];
	[_localDomain release];
	[_searchDomains release];
	[_lastConfigReload release];
	[_IPv4Socket cancelAsyncRequests];
	[_IPv4Socket release];
#ifdef OF_HAVE_IPV6
	[_IPv6Socket cancelAsyncRequests];
	[_IPv6Socket release];
#endif
	[_queries release];

	[super dealloc];
}

1788
1789
1790
1791
1792
1793
1794



1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808



1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
			of_socket_address_t address =
			    of_socket_address_parse_ip(@"::", 0);

			_IPv6Socket = [[OFUDPSocket alloc] init];
			[_IPv6Socket of_bindToAddress: &address
					    extraType: SOCK_DNS];
			[_IPv6Socket setBlocking: false];



		}

		sock = _IPv6Socket;
		break;
#endif
	case OF_SOCKET_ADDRESS_FAMILY_IPV4:
		if (_IPv4Socket == nil) {
			of_socket_address_t address =
			    of_socket_address_parse_ip(@"0.0.0.0", 0);

			_IPv4Socket = [[OFUDPSocket alloc] init];
			[_IPv4Socket of_bindToAddress: &address
					    extraType: SOCK_DNS];
			[_IPv4Socket setBlocking: false];



		}

		sock = _IPv4Socket;
		break;
	default:
		@throw [OFInvalidArgumentException exception];
	}

	[sock asyncSendBuffer: [query->_queryData items]
		       length: [query->_queryData count]
		     receiver: query->_usedNameServer
		  runLoopMode: runLoopMode
		       target: self
		     selector: @selector(of_socket:didSendBuffer:bytesSent:
				   receiver:context:exception:)
		      context: query];
}

- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query
{
	OFResolveHostFailedException *exception;

	if (query == nil)







>
>
>














>
>
>











|
<
<
<
<







1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818




1819
1820
1821
1822
1823
1824
1825
			of_socket_address_t address =
			    of_socket_address_parse_ip(@"::", 0);

			_IPv6Socket = [[OFUDPSocket alloc] init];
			[_IPv6Socket of_bindToAddress: &address
					    extraType: SOCK_DNS];
			[_IPv6Socket setBlocking: false];
			[_IPv6Socket setDelegate: self];
			[_IPv6Socket asyncReceiveIntoBuffer: _buffer
						     length: BUFFER_LENGTH];
		}

		sock = _IPv6Socket;
		break;
#endif
	case OF_SOCKET_ADDRESS_FAMILY_IPV4:
		if (_IPv4Socket == nil) {
			of_socket_address_t address =
			    of_socket_address_parse_ip(@"0.0.0.0", 0);

			_IPv4Socket = [[OFUDPSocket alloc] init];
			[_IPv4Socket of_bindToAddress: &address
					    extraType: SOCK_DNS];
			[_IPv4Socket setBlocking: false];
			[_IPv4Socket setDelegate: self];
			[_IPv4Socket asyncReceiveIntoBuffer: _buffer
						     length: BUFFER_LENGTH];
		}

		sock = _IPv4Socket;
		break;
	default:
		@throw [OFInvalidArgumentException exception];
	}

	[sock asyncSendBuffer: [query->_queryData items]
		       length: [query->_queryData count]
		     receiver: query->_usedNameServer
		  runLoopMode: runLoopMode];




}

- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query
{
	OFResolveHostFailedException *exception;

	if (query == nil)
1846
1847
1848
1849
1850
1851
1852













1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
		       runLoopMode: [[OFRunLoop currentRunLoop] currentMode]];
		return;
	}

	query = [[query retain] autorelease];
	[_queries removeObjectForKey: query->_ID];














	exception = [OFResolveHostFailedException
	    exceptionWithHost: query->_host
		  recordClass: query->_recordClass
		   recordType: query->_recordType
			error: OF_DNS_RESOLVER_ERROR_TIMEOUT];

	callback(query->_target, query->_selector, self, query->_domainName,
	    nil, nil, nil, query->_context, exception);
}

- (size_t)of_socket: (OFUDPSocket *)sock
      didSendBuffer: (void **)buffer
	  bytesSent: (size_t)bytesSent
	   receiver: (of_socket_address_t *)receiver
	    context: (OFDNSResolverQuery *)query
	  exception: (id)exception
{
	if (exception != nil) {
		query = [[query retain] autorelease];
		[_queries removeObjectForKey: query->_ID];

		callback(query->_target, query->_selector, self,
		    query->_domainName, nil, nil, nil, query->_context,
		    exception);

		return 0;
	}

	/*
	 * Pass the query as context to make sure that its buffer stays around
	 * for as long as our receive is pending.
	 */
	[sock asyncReceiveIntoBuffer: [query allocMemoryWithSize: 512]
			      length: 512
			 runLoopMode: [[OFRunLoop currentRunLoop] currentMode]
			      target: self
			    selector: @selector(of_socket:didReceiveIntoBuffer:
					  length:sender:context:exception:)
			     context: query];

	return 0;
}

-      (bool)of_socket: (OFUDPSocket *)sock
  didReceiveIntoBuffer: (unsigned char *)buffer
		length: (size_t)length
		sender: (of_socket_address_t)sender
	       context: (id)context
	     exception: (id)exception
{

	OFDictionary *answerRecords = nil, *authorityRecords = nil;
	OFDictionary *additionalRecords = nil;
	OFNumber *ID;
	OFDNSResolverQuery *query;

	if (exception != nil) {
		if ([exception respondsToSelector: @selector(errNo)])
			return ([exception errNo] == EINTR);

		return false;
	}

	if (length < 2)
		/* We can't get the ID to get the query. Ignore packet. */
		return true;

	ID = [OFNumber numberWithUInt16: (buffer[0] << 8) | buffer[1]];
	query = [[[_queries objectForKey: ID] retain] autorelease];








>
>
>
>
>
>
>
>
>
>
>
>
>










<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


<
<

>





<
<
<
<
<
<
<







1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869










1870























1871
1872
1873


1874
1875
1876
1877
1878
1879
1880







1881
1882
1883
1884
1885
1886
1887
		       runLoopMode: [[OFRunLoop currentRunLoop] currentMode]];
		return;
	}

	query = [[query retain] autorelease];
	[_queries removeObjectForKey: query->_ID];

	/*
	 * Cancel any pending requests, to avoid a send being still pending and
	 * trying to access the query once it no longer exists.
	 */
	[_IPv4Socket cancelAsyncRequests];
	[_IPv4Socket asyncReceiveIntoBuffer: _buffer
				     length: BUFFER_LENGTH];
#ifdef OF_HAVE_IPV6
	[_IPv6Socket cancelAsyncRequests];
	[_IPv6Socket asyncReceiveIntoBuffer: _buffer
				     length: BUFFER_LENGTH];
#endif

	exception = [OFResolveHostFailedException
	    exceptionWithHost: query->_host
		  recordClass: query->_recordClass
		   recordType: query->_recordType
			error: OF_DNS_RESOLVER_ERROR_TIMEOUT];

	callback(query->_target, query->_selector, self, query->_domainName,
	    nil, nil, nil, query->_context, exception);
}











-	  (bool)socket: (OF_KINDOF(OFUDPSocket *))sock























  didReceiveIntoBuffer: (void *)buffer_
		length: (size_t)length
		sender: (of_socket_address_t)sender


{
	unsigned char *buffer = buffer_;
	OFDictionary *answerRecords = nil, *authorityRecords = nil;
	OFDictionary *additionalRecords = nil;
	OFNumber *ID;
	OFDNSResolverQuery *query;








	if (length < 2)
		/* We can't get the ID to get the query. Ignore packet. */
		return true;

	ID = [OFNumber numberWithUInt16: (buffer[0] << 8) | buffer[1]];
	query = [[[_queries objectForKey: ID] retain] autorelease];

1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
				    nameServersIndex: query->_nameServersIndex
				  searchDomainsIndex: query->_searchDomainsIndex
					 runLoopMode: runLoopMode
					      target: query->_target
					    selector: query->_selector
					     context: query->_context];

				return false;
			}

			error = OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR;
			break;
		case 4:
			error = OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED;
			break;







|







1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
				    nameServersIndex: query->_nameServersIndex
				  searchDomainsIndex: query->_searchDomainsIndex
					 runLoopMode: runLoopMode
					      target: query->_target
					    selector: query->_selector
					     context: query->_context];

				return true;
			}

			error = OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR;
			break;
		case 4:
			error = OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED;
			break;
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
		authorityRecords = parseSection(buffer, length, &i,
		    numAuthorityRecords);
		additionalRecords = parseSection(buffer, length, &i,
		    numAdditionalRecords);
	} @catch (id e) {
		callback(query->_target, query->_selector, self,
		    query->_domainName, nil, nil, nil, query->_context, e);
		return false;
	}

	callback(query->_target, query->_selector, self, query->_domainName,
	    answerRecords, authorityRecords, additionalRecords,
	    query->_context, nil);

	return false;
}

- (void)asyncResolveSocketAddressesForHost: (OFString *)host
				    target: (id)target
				  selector: (SEL)selector
				   context: (id)context
{







|






|







1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
		authorityRecords = parseSection(buffer, length, &i,
		    numAuthorityRecords);
		additionalRecords = parseSection(buffer, length, &i,
		    numAdditionalRecords);
	} @catch (id e) {
		callback(query->_target, query->_selector, self,
		    query->_domainName, nil, nil, nil, query->_context, e);
		return true;
	}

	callback(query->_target, query->_selector, self, query->_domainName,
	    answerRecords, authorityRecords, additionalRecords,
	    query->_context, nil);

	return true;
}

- (void)asyncResolveSocketAddressesForHost: (OFString *)host
				    target: (id)target
				  selector: (SEL)selector
				   context: (id)context
{

Modified src/OFRunLoop+Private.h from [de6ad95d5c] to [eef6adb385].

21
22
23
24
25
26
27





28
29
30
31
32
33
34
# import "OFTCPSocket.h"
# import "OFUDPSocket.h"
#endif

OF_ASSUME_NONNULL_BEGIN

@class OFRunLoop_State;






@interface OFRunLoop ()
+ (void)of_setMainRunLoop: (OFRunLoop *)runLoop;
#ifdef OF_HAVE_SOCKETS
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer







>
>
>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# import "OFTCPSocket.h"
# import "OFUDPSocket.h"
#endif

OF_ASSUME_NONNULL_BEGIN

@class OFRunLoop_State;

@protocol OFTCPSocketDelegate_Private <OFObject>
- (void)of_socketDidConnect: (OF_KINDOF(OFTCPSocket *))socket
		  exception: (nullable id)exception;
@end

@interface OFRunLoop ()
+ (void)of_setMainRunLoop: (OFRunLoop *)runLoop;
#ifdef OF_HAVE_SOCKETS
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
				       stream
			   buffer: (const void *)buffer
			   length: (size_t)length
			     mode: (of_run_loop_mode_t)mode
			 delegate: (id <OFStreamDelegate>)delegate;
+ (void)of_addAsyncConnectForTCPSocket: (OFTCPSocket *)socket
				  mode: (of_run_loop_mode_t)mode
				target: (id)target
			      selector: (SEL)selector;
+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)socket
				 mode: (of_run_loop_mode_t)mode
			     delegate: (id <OFTCPSocketDelegate>)delegate;
+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket
				buffer: (void *)buffer
				length: (size_t)length
				  mode: (of_run_loop_mode_t)mode
				target: (id)target
			      selector: (SEL)selector
			       context: (nullable id)context;
+ (void)of_addAsyncSendForUDPSocket: (OFUDPSocket *)socket
			     buffer: (const void *)buffer
			     length: (size_t)length
			   receiver: (of_socket_address_t)receiver
			       mode: (of_run_loop_mode_t)mode
			     target: (id)target
			   selector: (SEL)selector
			    context: (nullable id)context;
# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
			  length: (size_t)length
			    mode: (of_run_loop_mode_t)mode
			   block: (of_stream_async_read_block_t)block;







|
|







|
<
<





|
<
<







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71


72
73
74
75
76
77


78
79
80
81
82
83
84
				       stream
			   buffer: (const void *)buffer
			   length: (size_t)length
			     mode: (of_run_loop_mode_t)mode
			 delegate: (id <OFStreamDelegate>)delegate;
+ (void)of_addAsyncConnectForTCPSocket: (OFTCPSocket *)socket
				  mode: (of_run_loop_mode_t)mode
			      delegate: (id <OFTCPSocketDelegate_Private>)
					    delegate;
+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)socket
				 mode: (of_run_loop_mode_t)mode
			     delegate: (id <OFTCPSocketDelegate>)delegate;
+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket
				buffer: (void *)buffer
				length: (size_t)length
				  mode: (of_run_loop_mode_t)mode
			      delegate: (id <OFUDPSocketDelegate>)delegate;


+ (void)of_addAsyncSendForUDPSocket: (OFUDPSocket *)socket
			     buffer: (const void *)buffer
			     length: (size_t)length
			   receiver: (of_socket_address_t)receiver
			       mode: (of_run_loop_mode_t)mode
			   delegate: (id <OFUDPSocketDelegate>)delegate;


# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
			  length: (size_t)length
			    mode: (of_run_loop_mode_t)mode
			   block: (of_stream_async_read_block_t)block;

Modified src/OFRunLoop.m from [1cb22455c7] to [536375a07c].

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
@end

#ifdef OF_HAVE_SOCKETS
@interface OFRunLoop_QueueItem: OFObject
{
@public
	id _delegate;
	/* TODO: Remove once everything is moved to using delegates */
	id _target;
	SEL _selector;
	id _context;
}

- (bool)handleObject: (id)object;
@end

@interface OFRunLoop_ReadQueueItem: OFRunLoop_QueueItem
{







<
<
<
<







71
72
73
74
75
76
77




78
79
80
81
82
83
84
@end

#ifdef OF_HAVE_SOCKETS
@interface OFRunLoop_QueueItem: OFObject
{
@public
	id _delegate;




}

- (bool)handleObject: (id)object;
@end

@interface OFRunLoop_ReadQueueItem: OFRunLoop_QueueItem
{
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)dealloc
{
	[_delegate release];
	[_target release];
	[_context release];

	[super dealloc];
}
@end

@implementation OFRunLoop_ReadQueueItem
- (bool)handleObject: (id)object







<
<







295
296
297
298
299
300
301


302
303
304
305
306
307
308
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)dealloc
{
	[_delegate release];



	[super dealloc];
}
@end

@implementation OFRunLoop_ReadQueueItem
- (bool)handleObject: (id)object
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560


561
562
563
564
565
566
567
568
@end

@implementation OFRunLoop_ConnectQueueItem
- (bool)handleObject: (id)object
{
	id exception = nil;
	int errNo;
	void (*func)(id, SEL, OFTCPSocket *, id, id);

	if ((errNo = [object of_socketError]) != 0)
		exception = [OFConnectionFailedException
		    exceptionWithHost: nil
				 port: 0
			       socket: object
				errNo: errNo];

	func = (void (*)(id, SEL, OFTCPSocket *, id, id))
	    [_target methodForSelector: _selector];


	func(_target, _selector, object, _context, exception);

	return false;
}
@end

@implementation OFRunLoop_AcceptQueueItem
- (bool)handleObject: (id)object







<








<
|
>
>
|







537
538
539
540
541
542
543

544
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559
560
561
562
@end

@implementation OFRunLoop_ConnectQueueItem
- (bool)handleObject: (id)object
{
	id exception = nil;
	int errNo;


	if ((errNo = [object of_socketError]) != 0)
		exception = [OFConnectionFailedException
		    exceptionWithHost: nil
				 port: 0
			       socket: object
				errNo: errNo];


	if ([_delegate respondsToSelector:
	    @selector(of_socketDidConnect:exception:)])
		[_delegate of_socketDidConnect: object
				     exception: exception];

	return false;
}
@end

@implementation OFRunLoop_AcceptQueueItem
- (bool)handleObject: (id)object
629
630
631
632
633
634
635
636
637


638



639

640



641
642
643

644
645
646
647
648
649
650
	}

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, _buffer, length, address, exception);
	else {
# endif
		bool (*func)(id, SEL, OFUDPSocket *, void *, size_t,
		    of_socket_address_t, id, id) =


		    (bool (*)(id, SEL, OFUDPSocket *, void *, size_t,



		    of_socket_address_t, id, id))

		    [_target methodForSelector: _selector];




		return func(_target, _selector, object, _buffer, length,
		    address, _context, exception);

# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc







|
|
>
>
|
>
>
>
|
>
|
>
>
>

|
<
>







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653
	}

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, _buffer, length, address, exception);
	else {
# endif
		if (exception == nil) {
			if (![_delegate respondsToSelector: @selector(socket:
			    didReceiveIntoBuffer:length:sender:)])
				return false;

			return [_delegate socket: object
			    didReceiveIntoBuffer: _buffer
					  length: length
					  sender: address];
		} else {
			if ([_delegate respondsToSelector:
			    @selector(socket:didFailToReceiveWithException:)])
				[_delegate		   socket: object
				    didFailToReceiveWithException: exception];

			return false;

		}
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
673
674
675
676
677
678
679
680

681

682
683

684

685
686


687

688
689
690

691
692
693
694
695
696
697
	if (_block != NULL) {
		_length = _block(object, &_buffer,
		    (exception == nil ? _length : 0), &_receiver, exception);

		return (_length > 0);
	} else {
# endif
		size_t (*func)(id, SEL, OFUDPSocket *, const void *, size_t,

		    of_socket_address_t *, id, id) =

		    (size_t (*)(id, SEL, OFUDPSocket *, const void *, size_t,
		    of_socket_address_t *, id, id))

		    [_target methodForSelector: _selector];


		_length = func(_target, _selector, object, &_buffer,


		    (exception == nil ? _length : 0), &_receiver, _context,

		    exception);

		return (_length > 0);

# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc







|
>
|
>
|
|
>
|
>

|
>
>
|
>
|

|
>







676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
	if (_block != NULL) {
		_length = _block(object, &_buffer,
		    (exception == nil ? _length : 0), &_receiver, exception);

		return (_length > 0);
	} else {
# endif
		if (exception == nil) {
			if (![_delegate respondsToSelector:
			    @selector(socket:didSendBuffer:length:receiver:)])
				return false;

			_length = [_delegate socket: object
				      didSendBuffer: &_buffer
					     length: _length
					   receiver: &_receiver];

			return (_length > 0);
		} else {
			if ([_delegate respondsToSelector:
			    @selector(socket:didFailToSendWithException:)])
				[_delegate		socket: object
				    didFailToSendWithException: exception];

			return false;
		}
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncConnectForTCPSocket: (OFTCPSocket *)stream
				  mode: (of_run_loop_mode_t)mode
				target: (id)target
			      selector: (SEL)selector
{
	ADD_WRITE(OFRunLoop_ConnectQueueItem, stream, mode, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
	})
}

+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)stream
				 mode: (of_run_loop_mode_t)mode
			     delegate: (id <OFTCPSocketDelegate>)delegate
{
	ADD_READ(OFRunLoop_AcceptQueueItem, stream, mode, {
		queueItem->_delegate = [delegate retain];
	})
}

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)sock
				buffer: (void *)buffer
				length: (size_t)length
				  mode: (of_run_loop_mode_t)mode
				target: (id)target
			      selector: (SEL)selector
			       context: (id)context
{
	ADD_READ(OFRunLoop_UDPReceiveQueueItem, sock, mode, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncSendForUDPSocket: (OFUDPSocket *)sock
			     buffer: (const void *)buffer
			     length: (size_t)length
			   receiver: (of_socket_address_t)receiver
			       mode: (of_run_loop_mode_t)mode
			     target: (id)target
			   selector: (SEL)selector
			    context: (id)context
{
	ADD_WRITE(OFRunLoop_UDPSendQueueItem, sock, mode, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_receiver = receiver;
	})
}

# ifdef OF_HAVE_BLOCKS







|
|


<
|
















|
<
<


<
|
<










|
<
<


<
|
<







837
838
839
840
841
842
843
844
845
846
847

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865


866
867

868

869
870
871
872
873
874
875
876
877
878
879


880
881

882

883
884
885
886
887
888
889
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncConnectForTCPSocket: (OFTCPSocket *)stream
				  mode: (of_run_loop_mode_t)mode
			      delegate: (id <OFTCPSocketDelegate_Private>)
					    delegate
{
	ADD_WRITE(OFRunLoop_ConnectQueueItem, stream, mode, {

		queueItem->_delegate = [delegate retain];
	})
}

+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)stream
				 mode: (of_run_loop_mode_t)mode
			     delegate: (id <OFTCPSocketDelegate>)delegate
{
	ADD_READ(OFRunLoop_AcceptQueueItem, stream, mode, {
		queueItem->_delegate = [delegate retain];
	})
}

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)sock
				buffer: (void *)buffer
				length: (size_t)length
				  mode: (of_run_loop_mode_t)mode
			      delegate: (id <OFUDPSocketDelegate>)delegate


{
	ADD_READ(OFRunLoop_UDPReceiveQueueItem, sock, mode, {

		queueItem->_delegate = [delegate retain];

		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncSendForUDPSocket: (OFUDPSocket *)sock
			     buffer: (const void *)buffer
			     length: (size_t)length
			   receiver: (of_socket_address_t)receiver
			       mode: (of_run_loop_mode_t)mode
			   delegate: (id <OFUDPSocketDelegate>)delegate


{
	ADD_WRITE(OFRunLoop_UDPSendQueueItem, sock, mode, {

		queueItem->_delegate = [delegate retain];

		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_receiver = receiver;
	})
}

# ifdef OF_HAVE_BLOCKS

Modified src/OFTCPSocket.m from [855c7eb790] to [349339a041].

60
61
62
63
64
65
66
67

68
69
70
71
72
73
74

Class of_tls_socket_class = Nil;

static of_run_loop_mode_t connectRunLoopMode = @"of_tcp_socket_connect_mode";
static OFString *defaultSOCKS5Host = nil;
static uint16_t defaultSOCKS5Port = 1080;

@interface OFTCPSocket_AsyncConnectContext: OFObject <OFTCPSocketDelegate>

{
	OFTCPSocket *_socket;
	OFString *_host;
	uint16_t _port;
	OFString *_SOCKS5Host;
	uint16_t _SOCKS5Port;
	id <OFTCPSocketDelegate> _delegate;







|
>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

Class of_tls_socket_class = Nil;

static of_run_loop_mode_t connectRunLoopMode = @"of_tcp_socket_connect_mode";
static OFString *defaultSOCKS5Host = nil;
static uint16_t defaultSOCKS5Port = 1080;

@interface OFTCPSocket_AsyncConnectContext: OFObject <OFTCPSocketDelegate,
    OFTCPSocketDelegate_Private>
{
	OFTCPSocket *_socket;
	OFString *_host;
	uint16_t _port;
	OFString *_SOCKS5Host;
	uint16_t _SOCKS5Port;
	id <OFTCPSocketDelegate> _delegate;
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
			  host: (OFString *)host
			  port: (uint16_t)port
		    SOCKS5Host: (OFString *)SOCKS5Host
		    SOCKS5Port: (uint16_t)SOCKS5Port
			 block: (of_tcp_socket_async_connect_block_t)block;
#endif
- (void)didConnect;
- (void)socketDidConnect: (OFTCPSocket *)sock
	       exception: (id)exception;
- (void)tryNextAddressWithRunLoopMode: (of_run_loop_mode_t)runLoopMode;
-	(void)resolver: (OFDNSResolver *)resolver
  didResolveDomainName: (OFString *)domainName
       socketAddresses: (OFData *)socketAddresses
	       context: (id)context
	     exception: (id)exception;
- (void)startWithRunLoopMode: (of_run_loop_mode_t)runLoopMode;







<
<







103
104
105
106
107
108
109


110
111
112
113
114
115
116
			  host: (OFString *)host
			  port: (uint16_t)port
		    SOCKS5Host: (OFString *)SOCKS5Host
		    SOCKS5Port: (uint16_t)SOCKS5Port
			 block: (of_tcp_socket_async_connect_block_t)block;
#endif
- (void)didConnect;


- (void)tryNextAddressWithRunLoopMode: (of_run_loop_mode_t)runLoopMode;
-	(void)resolver: (OFDNSResolver *)resolver
  didResolveDomainName: (OFString *)domainName
       socketAddresses: (OFData *)socketAddresses
	       context: (id)context
	     exception: (id)exception;
- (void)startWithRunLoopMode: (of_run_loop_mode_t)runLoopMode;
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
							     port: _port];
		}
#ifdef OF_HAVE_BLOCKS
	}
#endif
}

- (void)socketDidConnect: (OFTCPSocket *)sock
	       exception: (id)exception
{
	if (exception != nil) {
		if (_socketAddressesIndex >= [_socketAddresses count]) {
			_exception = [exception retain];
			[self didConnect];
		} else {
			[self tryNextAddressWithRunLoopMode:







|
|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
							     port: _port];
		}
#ifdef OF_HAVE_BLOCKS
	}
#endif
}

- (void)of_socketDidConnect: (OF_KINDOF(OFTCPSocket *))sock
		  exception: (id)exception
{
	if (exception != nil) {
		if (_socketAddressesIndex >= [_socketAddresses count]) {
			_exception = [exception retain];
			[self didConnect];
		} else {
			[self tryNextAddressWithRunLoopMode:
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
	}

	[_socket setBlocking: false];

	if (![_socket of_connectSocketToAddress: &address
					  errNo: &errNo]) {
		if (errNo == EINPROGRESS) {
			SEL selector = @selector(socketDidConnect:exception:);

			[OFRunLoop of_addAsyncConnectForTCPSocket: _socket
							     mode: runLoopMode
							   target: self
							 selector: selector];
			return;
		} else {
			[_socket of_closeSocket];

			if (_socketAddressesIndex >= [_socketAddresses count]) {
				_exception = [[OFConnectionFailedException
				    alloc] initWithHost: _host







<
<


|
<







280
281
282
283
284
285
286


287
288
289

290
291
292
293
294
295
296
	}

	[_socket setBlocking: false];

	if (![_socket of_connectSocketToAddress: &address
					  errNo: &errNo]) {
		if (errNo == EINPROGRESS) {


			[OFRunLoop of_addAsyncConnectForTCPSocket: _socket
							     mode: runLoopMode
							 delegate: self];

			return;
		} else {
			[_socket of_closeSocket];

			if (_socketAddressesIndex >= [_socketAddresses count]) {
				_exception = [[OFConnectionFailedException
				    alloc] initWithHost: _host

Modified src/OFUDPSocket.h from [201326e03a] to [6654ade8b5].

62
63
64
65
66
67
68





























































69
70
71
72
73
74
75
 *	   stays the same.
 */
typedef size_t (^of_udp_socket_async_send_block_t)(OFUDPSocket *socket,
    const void *_Nonnull *_Nonnull buffer, size_t bytesSent,
    of_socket_address_t *_Nonnull receiver, id exception);
#endif






























































/*!
 * @class OFUDPSocket OFUDPSocket.h ObjFW/OFUDPSocket.h
 *
 * @brief A class which provides methods to create and use UDP sockets.
 *
 * Addresses are of type @ref of_socket_address_t. You can use the current
 * thread's @ref OFDNSResolver to create an address for a host / port pair and







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
 *	   stays the same.
 */
typedef size_t (^of_udp_socket_async_send_block_t)(OFUDPSocket *socket,
    const void *_Nonnull *_Nonnull buffer, size_t bytesSent,
    of_socket_address_t *_Nonnull receiver, id exception);
#endif

/*!
 * @protocol OFUDPSocketDelegate OFUDPSocket.h ObjFW/OFUDPSocket.h
 *
 * @brief A delegate for OFUDPSocket.
 */
@protocol OFUDPSocketDelegate <OFObject>
@optional
/*!
 * @brief This method is called when a packet has been received.
 *
 * @param socket The UDP socket which received a packet
 * @param buffer The buffer the packet has been written to
 * @param length The length of the packet
 * @param sender The address of the sender of the packet
 * @return A bool whether the same block should be used for the next receive
 */
-	  (bool)socket: (OF_KINDOF(OFUDPSocket *))socket
  didReceiveIntoBuffer: (void *)buffer
		length: (size_t)length
		sender: (of_socket_address_t)sender;

/*!
 * @brief This which is called when a packet has been sent.
 *
 * @param socket The UDP socket which sent a packet
 * @param buffer A pointer to the buffer which was sent. This can be changed to
 *		 point to a different buffer to be used on the next send.
 * @param length The length of the buffer that has been sent
 * @param receiver The receiver for the UDP packet. This may be set to a new
 *		   receiver to which the next packet is sent.
 * @return The length to repeat the send with or 0 if it should not repeat.
 *	   The buffer and receiver may be changed, so that every time a new
 *	   buffer, length and receiver can be specified while the callback
 *	   stays the same.
 */
- (size_t)socket: (OF_KINDOF(OFUDPSocket *))socket
   didSendBuffer: (const void *_Nonnull *_Nonnull)buffer
	  length: (size_t)length
	receiver: (of_socket_address_t *_Nonnull)receiver;

/*!
 * @brief This method is called when an exception occurred during an
 *	  asynchronous receive on the socket.
 *
 * @param socket The socket for which an exception occurred
 * @param exception The exception which occurred for the socket
 */
-		   (void)socket: (OF_KINDOF(OFUDPSocket *))socket
  didFailToReceiveWithException: (id)exception;

/*!
 * @brief This method is called when an exception occurred during an
 *	  asynchronous send on the socket.
 *
 * @param socket The socket for which an exception occurred
 * @param exception The exception which occurred for the socket
 */
-		(void)socket: (OF_KINDOF(OFUDPSocket *))socket
  didFailToSendWithException: (id)exception;
@end

/*!
 * @class OFUDPSocket OFUDPSocket.h ObjFW/OFUDPSocket.h
 *
 * @brief A class which provides methods to create and use UDP sockets.
 *
 * Addresses are of type @ref of_socket_address_t. You can use the current
 * thread's @ref OFDNSResolver to create an address for a host / port pair and
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104









105
106
107
108
109
110
111
    OFReadyForWritingObserving>
{
	of_socket_t _socket;
#ifdef OF_WII
	uint16_t _port;
#endif
	bool _blocking;

}

/*!
 * @brief Whether the socket is in blocking mode.
 *
 * By default, a socket is in blocking mode.
 */
@property (nonatomic, getter=isBlocking) bool blocking;










/*!
 * @brief Returns a new, autoreleased OFUDPSocket.
 *
 * @return A new, autoreleased OFUDPSocket
 */
+ (instancetype)socket;








>









>
>
>
>
>
>
>
>
>







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
    OFReadyForWritingObserving>
{
	of_socket_t _socket;
#ifdef OF_WII
	uint16_t _port;
#endif
	bool _blocking;
	id _Nullable _delegate;
}

/*!
 * @brief Whether the socket is in blocking mode.
 *
 * By default, a socket is in blocking mode.
 */
@property (nonatomic, getter=isBlocking) bool blocking;

/*!
 * @brief The delegate for asynchronous operations on the socket.
 *
 * @note The delegate is retained for as long as asynchronous operations are
 *	 still outstanding.
 */
@property OF_NULLABLE_PROPERTY (assign, nonatomic)
    id <OFUDPSocketDelegate> delegate;

/*!
 * @brief Returns a new, autoreleased OFUDPSocket.
 *
 * @return A new, autoreleased OFUDPSocket
 */
+ (instancetype)socket;

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
 *
 * @param buffer The buffer to write the datagram to
 * @param length The length of the buffer
 * @param target The target on which the selector should be called when the
 *		 datagram has been received. If the method returns true, it
 *		 will be called again with the same buffer and maximum length
 *		 when more datagrams have been received. If you want the next
 *		 method in the queue to handle the datagram received next, you
 *		 need to return false from the method.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFUDPSocket *socket, void *buffer, size_t length,
 *		   of_socket_address_t sender, id context, id exception)`.
 * @param context A context object to pass along to the target
 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
			target: (id)target
		      selector: (SEL)selector
		       context: (nullable id)context;

/*!
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
 *
 * @param buffer The buffer to write the datagram to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the async receive
 * @param target The target on which the selector should be called when the
 *		 datagram has been received. If the method returns true, it
 *		 will be called again with the same buffer and maximum length
 *		 when more datagrams have been received. If you want the next
 *		 method in the queue to handle the datagram received next, you
 *		 need to return false from the method.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFUDPSocket *socket, void *buffer, size_t length,
 *		   of_socket_address_t sender, id context, id exception)`.
 * @param context A context object to pass along to the target
 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
		   runLoopMode: (of_run_loop_mode_t)runLoopMode
			target: (id)target
		      selector: (SEL)selector
		       context: (nullable id)context;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.







<
<
<
<
<
<
<
<
<
<


|
<
<
<










<
<
<
<
<
<
<
<
<
<



|
<
<
<







211
212
213
214
215
216
217










218
219
220



221
222
223
224
225
226
227
228
229
230










231
232
233
234



235
236
237
238
239
240
241
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
 *
 * @param buffer The buffer to write the datagram to
 * @param length The length of the buffer










 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length;




/*!
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
 *
 * @param buffer The buffer to write the datagram to
 * @param length The length of the buffer
 * @param runLoopMode The run loop mode in which to perform the async receive










 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
		   runLoopMode: (of_run_loop_mode_t)runLoopMode;




#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously receives a datagram and stores it into the specified
 *	  buffer.
 *
 * If the buffer is too small, the datagram is truncated.
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*!
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param buffer The buffer to send as a datagram
 * @param length The length of the buffer
 * @param receiver A pointer to an @ref of_socket_address_t to which the
 *		   datagram should be sent
 * @param target The target on which the selector should be called when the
 *		 packet has been sent. The method should return the length for
 *		 the next send with the same callback or 0 if it should not
 *		 repeat. The buffer and receiver may be changed, so that every
 *		 time a new buffer, length and receiver can be specified while
 *		 the callback stays the same.
 * @param selector The selector to call on the target. The signature must be
 *		   `size_t (OFUDPSocket *socket, const void **buffer,
 *		   size_t bytesSent, of_socket_address_t *receiver, id context,
 *		   id exception)`.
 * @param context A context object to pass along to the target
 */
- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver
		 target: (id)target
	       selector: (SEL)selector
		context: (nullable id)context;

/*!
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param buffer The buffer to send as a datagram
 * @param length The length of the buffer
 * @param receiver A pointer to an @ref of_socket_address_t to which the
 *		   datagram should be sent
 * @param runLoopMode The run loop mode in which to perform the async send
 * @param target The target on which the selector should be called when the
 *		 packet has been sent. The method should return the length for
 *		 the next send with the same callback or 0 if it should not
 *		 repeat. The buffer and receiver may be changed, so that every
 *		 time a new buffer, length and receiver can be specified while
 *		 the callback stays the same.
 * @param selector The selector to call on the target. The signature must be
 *		   `size_t (OFUDPSocket *socket, const void **buffer,
 *		   size_t bytesSent, of_socket_address_t *receiver, id context,
 *		   id exception)`.
 * @param context A context object to pass along to the target
 */
- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver
	    runLoopMode: (of_run_loop_mode_t)runLoopMode
		 target: (id)target
	       selector: (SEL)selector
		context: (nullable id)context;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param buffer The buffer to send as a datagram
 * @param length The length of the buffer







<
<
<
<
<
<
<
<
<
<
<



|
<
<
<









<
<
<
<
<
<
<
<
<
<
<




|
<
<
<







290
291
292
293
294
295
296











297
298
299
300



301
302
303
304
305
306
307
308
309











310
311
312
313
314



315
316
317
318
319
320
321
/*!
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param buffer The buffer to send as a datagram
 * @param length The length of the buffer
 * @param receiver A pointer to an @ref of_socket_address_t to which the
 *		   datagram should be sent











 */
- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver;




/*!
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param buffer The buffer to send as a datagram
 * @param length The length of the buffer
 * @param receiver A pointer to an @ref of_socket_address_t to which the
 *		   datagram should be sent
 * @param runLoopMode The run loop mode in which to perform the async send











 */
- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver
	    runLoopMode: (of_run_loop_mode_t)runLoopMode;




#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously sends the specified datagram to the specified address.
 *
 * @param buffer The buffer to send as a datagram
 * @param length The length of the buffer

Modified src/OFUDPSocket.m from [c73a7a1b74] to [a173a95dac].

44
45
46
47
48
49
50


51
52
53
54
55
56
57
#import "OFSetOptionFailedException.h"
#import "OFWriteFailedException.h"

#import "socket.h"
#import "socket_helpers.h"

@implementation OFUDPSocket


+ (void)initialize
{
	if (self != [OFUDPSocket class])
		return;

	if (!of_socket_init())
		@throw [OFInitializationFailedException







>
>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#import "OFSetOptionFailedException.h"
#import "OFWriteFailedException.h"

#import "socket.h"
#import "socket_helpers.h"

@implementation OFUDPSocket
@synthesize delegate = _delegate;

+ (void)initialize
{
	if (self != [OFUDPSocket class])
		return;

	if (!of_socket_init())
		@throw [OFInitializationFailedException
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
	}

	return ret;
}

- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
			target: (id)target
		      selector: (SEL)selector
		       context: (id)context
{
	[self asyncReceiveIntoBuffer: buffer
			      length: length
			 runLoopMode: of_run_loop_mode_default
			      target: target
			    selector: selector
			     context: context];
}

- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
		   runLoopMode: (of_run_loop_mode_t)runLoopMode
			target: (id)target
		      selector: (SEL)selector
		       context: (id)context
{
	[OFRunLoop of_addAsyncReceiveForUDPSocket: self
					   buffer: buffer
					   length: length
					     mode: runLoopMode
					   target: target
					 selector: selector
					  context: context];
}

#ifdef OF_HAVE_BLOCKS
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
			 block: (of_udp_socket_async_receive_block_t)block
{







<
<
<



|
<
<
<





<
<
<





<
|
<







325
326
327
328
329
330
331



332
333
334
335



336
337
338
339
340



341
342
343
344
345

346

347
348
349
350
351
352
353
	}

	return ret;
}

- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length



{
	[self asyncReceiveIntoBuffer: buffer
			      length: length
			 runLoopMode: of_run_loop_mode_default];



}

- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
		   runLoopMode: (of_run_loop_mode_t)runLoopMode



{
	[OFRunLoop of_addAsyncReceiveForUDPSocket: self
					   buffer: buffer
					   length: length
					     mode: runLoopMode

					 delegate: _delegate];

}

#ifdef OF_HAVE_BLOCKS
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
			 block: (of_udp_socket_async_receive_block_t)block
{
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
						      bytesWritten: bytesWritten
							     errNo: 0];
}

- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver
		 target: (id)target
	       selector: (SEL)selector
		context: (id)context
{
	[self asyncSendBuffer: buffer
		       length: length
		     receiver: receiver
		  runLoopMode: of_run_loop_mode_default
		       target: target
		     selector: selector
		      context: context];
}

- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver
	    runLoopMode: (of_run_loop_mode_t)runLoopMode
		 target: (id)target
	       selector: (SEL)selector
		context: (id)context
{
	[OFRunLoop of_addAsyncSendForUDPSocket: self
					buffer: buffer
					length: length
				      receiver: receiver
					  mode: runLoopMode
					target: target
				      selector: selector
				       context: context];
}

#ifdef OF_HAVE_BLOCKS
- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver
		  block: (of_udp_socket_async_send_block_t)block







<
<
<




|
<
<
<






<
<
<






<
|
<







411
412
413
414
415
416
417



418
419
420
421
422



423
424
425
426
427
428



429
430
431
432
433
434

435

436
437
438
439
440
441
442
						      bytesWritten: bytesWritten
							     errNo: 0];
}

- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver



{
	[self asyncSendBuffer: buffer
		       length: length
		     receiver: receiver
		  runLoopMode: of_run_loop_mode_default];



}

- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver
	    runLoopMode: (of_run_loop_mode_t)runLoopMode



{
	[OFRunLoop of_addAsyncSendForUDPSocket: self
					buffer: buffer
					length: length
				      receiver: receiver
					  mode: runLoopMode

				      delegate: _delegate];

}

#ifdef OF_HAVE_BLOCKS
- (void)asyncSendBuffer: (const void *)buffer
		 length: (size_t)length
	       receiver: (of_socket_address_t)receiver
		  block: (of_udp_socket_async_send_block_t)block