ObjFW  Check-in [958da109d3]

Overview
Comment:Support for passing a context to async IO handlers
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 958da109d3850e09d02d50cecc25ef17abf5b1c2eb42df05ac353b89cad27528
User & Date: js on 2017-09-23 22:07:34
Other Links: manifest | tags
Context
2017-09-24
00:59
Make OFHTTPClient asynchronous check-in: 56a18442e2 user: js tags: trunk
2017-09-23
22:07
Support for passing a context to async IO handlers check-in: 958da109d3 user: js tags: trunk
20:35
ofhttp: Refactor for asynchronous OFHTTPClient check-in: c26c8ca746 user: js tags: trunk
Changes

Modified src/OFHTTPServer.m from [c477e44d18] to [f88ae06cce].

45
46
47
48
49
50
51

52
53
54
55
56
57
58
 * FIXME: Key normalization replaces headers like "DNT" with "Dnt".
 * FIXME: Errors are not reported to the user.
 */

@interface OFHTTPServer ()
- (bool)of_socket: (OFTCPSocket *)socket
  didAcceptSocket: (OFTCPSocket *)clientSocket

	exception: (OFException *)exception;
@end

static const char *
statusCodeToString(short code)
{
	switch (code) {







>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
 * FIXME: Key normalization replaces headers like "DNT" with "Dnt".
 * FIXME: Errors are not reported to the user.
 */

@interface OFHTTPServer ()
- (bool)of_socket: (OFTCPSocket *)socket
  didAcceptSocket: (OFTCPSocket *)clientSocket
	  context: (id)context
	exception: (OFException *)exception;
@end

static const char *
statusCodeToString(short code)
{
	switch (code) {
338
339
340
341
342
343
344

345
346
347
348
349
350

351
352
353
354
355
356
357
	OFMutableData *_body;
}

- initWithSocket: (OFTCPSocket *)socket
	  server: (OFHTTPServer *)server;
- (bool)socket: (OFTCPSocket *)socket
   didReadLine: (OFString *)line

     exception: (OFException *)exception;
- (bool)parseProlog: (OFString *)line;
- (bool)parseHeaders: (OFString *)line;
-      (bool)socket: (OFTCPSocket *)socket
  didReadIntoBuffer: (char *)buffer
	     length: (size_t)length

	  exception: (OFException *)exception;
- (bool)sendErrorAndClose: (short)statusCode;
- (void)createResponse;
@end

@implementation OFHTTPServer_Connection
- initWithSocket: (OFTCPSocket *)socket







>






>







339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
	OFMutableData *_body;
}

- initWithSocket: (OFTCPSocket *)socket
	  server: (OFHTTPServer *)server;
- (bool)socket: (OFTCPSocket *)socket
   didReadLine: (OFString *)line
       context: (id)context
     exception: (OFException *)exception;
- (bool)parseProlog: (OFString *)line;
- (bool)parseHeaders: (OFString *)line;
-      (bool)socket: (OFTCPSocket *)socket
  didReadIntoBuffer: (char *)buffer
	     length: (size_t)length
	    context: (id)context
	  exception: (OFException *)exception;
- (bool)sendErrorAndClose: (short)statusCode;
- (void)createResponse;
@end

@implementation OFHTTPServer_Connection
- initWithSocket: (OFTCPSocket *)socket
391
392
393
394
395
396
397

398
399
400
401
402
403
404
	[_body release];

	[super dealloc];
}

- (bool)socket: (OFTCPSocket *)socket
   didReadLine: (OFString *)line

     exception: (OFException *)exception
{
	if (line == nil || exception != nil)
		return false;

	@try {
		switch (_state) {







>







394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
	[_body release];

	[super dealloc];
}

- (bool)socket: (OFTCPSocket *)socket
   didReadLine: (OFString *)line
       context: (id)context
     exception: (OFException *)exception
{
	if (line == nil || exception != nil)
		return false;

	@try {
		switch (_state) {
503
504
505
506
507
508
509

510

511
512
513
514
515
516
517
			_body = [[OFMutableData alloc] init];

			[_socket asyncReadIntoBuffer: buffer
					      length: BUFFER_SIZE
					      target: self
					    selector: @selector(socket:
							  didReadIntoBuffer:

							  length:exception:)];

			[_timer setFireDate:
			    [OFDate dateWithTimeIntervalSinceNow: 5]];

			return false;
		}

		_state = SEND_RESPONSE;







>
|
>







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
			_body = [[OFMutableData alloc] init];

			[_socket asyncReadIntoBuffer: buffer
					      length: BUFFER_SIZE
					      target: self
					    selector: @selector(socket:
							  didReadIntoBuffer:
							  length:context:
							  exception:)
					     context: nil];
			[_timer setFireDate:
			    [OFDate dateWithTimeIntervalSinceNow: 5]];

			return false;
		}

		_state = SEND_RESPONSE;
568
569
570
571
572
573
574

575
576
577
578
579
580
581

	return true;
}

-      (bool)socket: (OFTCPSocket *)socket
  didReadIntoBuffer: (char *)buffer
	     length: (size_t)length

	  exception: (OFException *)exception
{
	if ([socket isAtEndOfStream] || exception != nil)
		return false;

	[_body addItems: buffer
		  count: length];







>







574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

	return true;
}

-      (bool)socket: (OFTCPSocket *)socket
  didReadIntoBuffer: (char *)buffer
	     length: (size_t)length
	    context: (id)context
	  exception: (OFException *)exception
{
	if ([socket isAtEndOfStream] || exception != nil)
		return false;

	[_body addItems: buffer
		  count: length];
718
719
720
721
722
723
724
725
726

727
728
729
730
731
732
733
734
735
736
737

738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

758
759
760
761
	_listeningSocket = [[OFTCPSocket alloc] init];
	_port = [_listeningSocket bindToHost: _host
					port: _port];
	[_listeningSocket listen];

	[_listeningSocket asyncAcceptWithTarget: self
				       selector: @selector(of_socket:
						     didAcceptSocket:
						     exception:)];

}

- (void)stop
{
	[_listeningSocket cancelAsyncRequests];
	[_listeningSocket release];
	_listeningSocket = nil;
}

- (bool)of_socket: (OFTCPSocket *)socket
  didAcceptSocket: (OFTCPSocket *)clientSocket

	exception: (OFException *)exception
{
	OFHTTPServer_Connection *connection;

	if (exception != nil) {
		if ([_delegate respondsToSelector:
		    @selector(server:didReceiveExceptionOnListeningSocket:)])
			return [_delegate		  server: self
			    didReceiveExceptionOnListeningSocket: exception];

		return false;
	}

	connection = [[[OFHTTPServer_Connection alloc]
	    initWithSocket: clientSocket
		    server: self] autorelease];

	[clientSocket asyncReadLineWithTarget: connection
				     selector: @selector(socket:didReadLine:
						  exception:)];


	return true;
}
@end







|
|
>











>



















|
>




725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
	_listeningSocket = [[OFTCPSocket alloc] init];
	_port = [_listeningSocket bindToHost: _host
					port: _port];
	[_listeningSocket listen];

	[_listeningSocket asyncAcceptWithTarget: self
				       selector: @selector(of_socket:
						     didAcceptSocket:context:
						     exception:)
					context: nil];
}

- (void)stop
{
	[_listeningSocket cancelAsyncRequests];
	[_listeningSocket release];
	_listeningSocket = nil;
}

- (bool)of_socket: (OFTCPSocket *)socket
  didAcceptSocket: (OFTCPSocket *)clientSocket
	  context: (id)context
	exception: (OFException *)exception
{
	OFHTTPServer_Connection *connection;

	if (exception != nil) {
		if ([_delegate respondsToSelector:
		    @selector(server:didReceiveExceptionOnListeningSocket:)])
			return [_delegate		  server: self
			    didReceiveExceptionOnListeningSocket: exception];

		return false;
	}

	connection = [[[OFHTTPServer_Connection alloc]
	    initWithSocket: clientSocket
		    server: self] autorelease];

	[clientSocket asyncReadLineWithTarget: connection
				     selector: @selector(socket:didReadLine:
						  context:exception:)
				      context: nil];

	return true;
}
@end

Modified src/OFRunLoop+Private.h from [6cb34b1a9e] to [d3aaadeae6].

25
26
27
28
29
30
31
32

33
34
35
36
37

38
39
40
41

42
43
44

45
46
47
48
49

50
51
52
53
54
55
56
@interface OFRunLoop ()
+ (void)of_setMainRunLoop: (OFRunLoop *)runLoop;
#ifdef OF_HAVE_SOCKETS
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
			  length: (size_t)length
			  target: (id)target
			selector: (SEL)selector;

+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
		     exactLength: (size_t)length
			  target: (id)target
			selector: (SEL)selector;

+ (void)of_addAsyncReadLineForStream: (OFStream *)stream
			    encoding: (of_string_encoding_t)encoding
			      target: (id)target
			    selector: (SEL)selector;

+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)socket
			       target: (id)target
			     selector: (SEL)selector;

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket
				buffer: (void *)buffer
				length: (size_t)length
				target: (id)target
			      selector: (SEL)selector;

# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
			  length: (size_t)length
			   block: (of_stream_async_read_block_t)block;
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer







|
>




|
>



|
>


|
>




|
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@interface OFRunLoop ()
+ (void)of_setMainRunLoop: (OFRunLoop *)runLoop;
#ifdef OF_HAVE_SOCKETS
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
			  length: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (nullable id)context;
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
		     exactLength: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (nullable id)context;
+ (void)of_addAsyncReadLineForStream: (OFStream *)stream
			    encoding: (of_string_encoding_t)encoding
			      target: (id)target
			    selector: (SEL)selector
			     context: (nullable id)context;
+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)socket
			       target: (id)target
			     selector: (SEL)selector
			      context: (nullable id)context;
+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket
				buffer: (void *)buffer
				length: (size_t)length
				target: (id)target
			      selector: (SEL)selector
			       context: (nullable id)context;
# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
			  length: (size_t)length
			   block: (of_stream_async_read_block_t)block;
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer

Modified src/OFRunLoop.m from [2bcc651795] to [35d1810bb5].

41
42
43
44
45
46
47

48
49
50
51
52
53
54

#ifdef OF_HAVE_SOCKETS
@interface OFRunLoop_QueueItem: OFObject
{
@public
	id _target;
	SEL _selector;

}

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

@interface OFRunLoop_ReadQueueItem: OFRunLoop_QueueItem
{







>







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

#ifdef OF_HAVE_SOCKETS
@interface OFRunLoop_QueueItem: OFObject
{
@public
	id _target;
	SEL _selector;
	id _context;
}

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

@interface OFRunLoop_ReadQueueItem: OFRunLoop_QueueItem
{
107
108
109
110
111
112
113

114
115
116
117
118
119
120
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)dealloc
{
	[_target release];


	[super dealloc];
}
@end

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







>







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
{
	OF_UNRECOGNIZED_SELECTOR
}

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

	[super dealloc];
}
@end

@implementation OFRunLoop_ReadQueueItem
- (bool)handleForObject: (id)object
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
	}

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, _buffer, length, exception);
	else {
# endif
		bool (*func)(id, SEL, OFStream *, void *, size_t,
		    OFException *) = (bool (*)(id, SEL, OFStream *, void *,
		    size_t, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, _buffer, length,
		    exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc







|

|



|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
	}

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, _buffer, length, exception);
	else {
# endif
		bool (*func)(id, SEL, OFStream *, void *, size_t, id,
		    OFException *) = (bool (*)(id, SEL, OFStream *, void *,
		    size_t, id, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, _buffer, length,
		    _context, exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
		if (!_block(object, _buffer, _readLength, exception))
			return false;

		_readLength = 0;
		return true;
	} else {
# endif
		bool (*func)(id, SEL, OFStream *, void *, size_t,
		    OFException *) = (bool (*)(id, SEL, OFStream *, void *,
		    size_t, OFException *))
		    [_target methodForSelector: _selector];

		if (!func(_target, _selector, object, _buffer, _readLength,
		    exception))
			return false;

		_readLength = 0;
		return true;
# ifdef OF_HAVE_BLOCKS
	}
# endif







|

|



|







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
		if (!_block(object, _buffer, _readLength, exception))
			return false;

		_readLength = 0;
		return true;
	} else {
# endif
		bool (*func)(id, SEL, OFStream *, void *, size_t, id,
		    OFException *) = (bool (*)(id, SEL, OFStream *, void *,
		    size_t, id, OFException *))
		    [_target methodForSelector: _selector];

		if (!func(_target, _selector, object, _buffer, _readLength,
		    _context, exception))
			return false;

		_readLength = 0;
		return true;
# ifdef OF_HAVE_BLOCKS
	}
# endif
229
230
231
232
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
		return true;

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, line, exception);
	else {
# endif
		bool (*func)(id, SEL, OFStream *, OFString *, OFException *) =
		    (bool (*)(id, SEL, OFStream *, OFString *, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, line, exception);

# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc







|
|
|

|
>







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
		return true;

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, line, exception);
	else {
# endif
		bool (*func)(id, SEL, OFStream *, OFString *, id,
		    OFException *) = (bool (*)(id, SEL, OFStream *, OFString *,
		    id, OFException *))[_target methodForSelector: _selector];

		return func(_target, _selector, object, line, _context,
		    exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
267
268
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
	}

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, newSocket, exception);
	else {
# endif
		bool (*func)(id, SEL, OFTCPSocket *, OFTCPSocket *,
		    OFException *) = (bool (*)(id, SEL, OFTCPSocket *,
		    OFTCPSocket *, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, newSocket, exception);

# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc







|

|


|
>







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
	}

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		return _block(object, newSocket, exception);
	else {
# endif
		bool (*func)(id, SEL, OFTCPSocket *, OFTCPSocket *, id,
		    OFException *) = (bool (*)(id, SEL, OFTCPSocket *,
		    OFTCPSocket *, id, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, newSocket, _context,
		    exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

# 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_udp_socket_address_t address, OFException *) =
		    (bool (*)(id, SEL, OFUDPSocket *, void *, size_t,
		    of_udp_socket_address_t, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, _buffer, length,
		    address, exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc







|

|



|







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

# 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_udp_socket_address_t address, id, OFException *) =
		    (bool (*)(id, SEL, OFUDPSocket *, void *, size_t,
		    of_udp_socket_address_t, id, OFException *))
		    [_target methodForSelector: _selector];

		return func(_target, _selector, object, _buffer, length,
		    address, _context, exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

# ifdef OF_HAVE_BLOCKS
- (void)dealloc
381
382
383
384
385
386
387

388
389
390
391

392
393
394
395
396
397
398
399
400
401

402
403
404
405

406
407
408
409
410
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
443



444
445
446
447
448
449
450
	objc_autoreleasePoolPop(pool);

+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
			  length: (size_t)length
			  target: (id)target
			selector: (SEL)selector

{
	ADD_READ(OFRunLoop_ReadQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;

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

+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
		     exactLength: (size_t)exactLength
			  target: (id)target
			selector: (SEL)selector

{
	ADD_READ(OFRunLoop_ExactReadQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;

		queueItem->_buffer = buffer;
		queueItem->_exactLength = exactLength;
	})
}

+ (void)of_addAsyncReadLineForStream: (OFStream *)stream
			    encoding: (of_string_encoding_t)encoding
			      target: (id)target
			    selector: (SEL)selector

{
	ADD_READ(OFRunLoop_ReadLineQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;

		queueItem->_encoding = encoding;
	})
}

+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)stream
			       target: (id)target
			     selector: (SEL)selector

{
	ADD_READ(OFRunLoop_AcceptQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;

	})
}

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket
				buffer: (void *)buffer
				length: (size_t)length
				target: (id)target
			      selector: (SEL)selector

{
	ADD_READ(OFRunLoop_UDPReceiveQueueItem, socket, {
		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_target = [target retain];
		queueItem->_selector = selector;



	})
}

# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
			  length: (size_t)length







>




>










>




>









>




>







>




>








>


<
<


>
>
>







385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
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
443
444
445
446
447
448
449
450
451
452


453
454
455
456
457
458
459
460
461
462
463
464
	objc_autoreleasePoolPop(pool);

+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
			  length: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (id)context
{
	ADD_READ(OFRunLoop_ReadQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
		     exactLength: (size_t)exactLength
			  target: (id)target
			selector: (SEL)selector
			 context: (id)context
{
	ADD_READ(OFRunLoop_ExactReadQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_exactLength = exactLength;
	})
}

+ (void)of_addAsyncReadLineForStream: (OFStream *)stream
			    encoding: (of_string_encoding_t)encoding
			      target: (id)target
			    selector: (SEL)selector
			     context: (id)context
{
	ADD_READ(OFRunLoop_ReadLineQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_encoding = encoding;
	})
}

+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)stream
			       target: (id)target
			     selector: (SEL)selector
			      context: (id)context
{
	ADD_READ(OFRunLoop_AcceptQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
	})
}

+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket
				buffer: (void *)buffer
				length: (size_t)length
				target: (id)target
			      selector: (SEL)selector
			       context: (id)context
{
	ADD_READ(OFRunLoop_UDPReceiveQueueItem, socket, {


		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream *)stream
			  buffer: (void *)buffer
			  length: (size_t)length

Modified src/OFStream.h from [fc84511d6f] to [39526e7198].

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
197
198
199
200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
#ifdef OF_HAVE_SOCKETS
/*!
 * @brief Asynchronously reads *at most* size bytes from the stream into a
 *	  buffer.
 *
 * On network streams, this might read less than the specified number of bytes.
 * If you want to read exactly the specified number of bytes, use
 * @ref asyncReadIntoBuffer:exactLength:block:. Note that a read can even
 * return 0 bytes - this does not necessarily mean that the stream ended, so
 * you still need to check @ref isAtEndOfStream.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer into which the data is read.
 *		 The buffer must not be freed before the async read completed!
 * @param length The length of the data that should be read at most.
 *		 The buffer *must* be *at least* this big!
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, it will be
 *		 called again with the same buffer and maximum length when more
 *		 data has been received. If you want the next method in the
 *		 queue to handle the data received next, you need to return
 *		 false from the method.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, void *buffer, size_t length,
 *		   OFException *exception)`.
 */
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		     target: (id)target
		   selector: (SEL)selector;


/*!
 * @brief Asynchronously reads exactly the specified length bytes from the
 *	  stream into a buffer.
 *
 * Unlike @ref asyncReadIntoBuffer:length:target:selector:, this method does
 * not call the method when less than the specified length has been read -
 * instead, it waits until it got exactly the specified length, the stream has
 * ended or an exception occurred.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer into which the data is read
 * @param length The length of the data that should be read.
 *		 The buffer *must* be *at least* this big!
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, it will be
 *		 called again with the same buffer and exact length when more
 *		 data has been received. If you want the next method in the
 *		 queue to handle the data received next, you need to return
 *		 false from the method.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, void *buffer, size_t size,
 *		   OFException *exception)`.
 */
- (void)asyncReadIntoBuffer: (void *)buffer
		exactLength: (size_t)length
		     target: (id)target
		   selector: (SEL)selector;


# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously reads *at most* ref size bytes from the stream into a
 *	  buffer.
 *
 * On network streams, this might read less than the specified number of bytes.







|
|
|
















|




|
>





|
|

















|




|
>







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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#ifdef OF_HAVE_SOCKETS
/*!
 * @brief Asynchronously reads *at most* size bytes from the stream into a
 *	  buffer.
 *
 * On network streams, this might read less than the specified number of bytes.
 * If you want to read exactly the specified number of bytes, use
 * @ref asyncReadIntoBuffer:exactLength:target:selector:context:. Note that a
 * read can even return 0 bytes - this does not necessarily mean that the
 * stream ended, so you still need to check @ref isAtEndOfStream.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer into which the data is read.
 *		 The buffer must not be freed before the async read completed!
 * @param length The length of the data that should be read at most.
 *		 The buffer *must* be *at least* this big!
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, it will be
 *		 called again with the same buffer and maximum length when more
 *		 data has been received. If you want the next method in the
 *		 queue to handle the data received next, you need to return
 *		 false from the method.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, void *buffer, size_t length,
 *		   id context, OFException *exception)`.
 */
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		     target: (id)target
		   selector: (SEL)selector
		    context: (nullable id)context;

/*!
 * @brief Asynchronously reads exactly the specified length bytes from the
 *	  stream into a buffer.
 *
 * Unlike @ref asyncReadIntoBuffer:length:target:selector:context:, this method
 * does not call the method when less than the specified length has been read -
 * instead, it waits until it got exactly the specified length, the stream has
 * ended or an exception occurred.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer into which the data is read
 * @param length The length of the data that should be read.
 *		 The buffer *must* be *at least* this big!
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, it will be
 *		 called again with the same buffer and exact length when more
 *		 data has been received. If you want the next method in the
 *		 queue to handle the data received next, you need to return
 *		 false from the method.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, void *buffer, size_t size,
 *		   id context, OFException *exception)`.
 */
- (void)asyncReadIntoBuffer: (void *)buffer
		exactLength: (size_t)length
		     target: (id)target
		   selector: (SEL)selector
		    context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously reads *at most* ref size bytes from the stream into a
 *	  buffer.
 *
 * On network streams, this might read less than the specified number of bytes.
617
618
619
620
621
622
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
654
655
656
 *
 * @param target The target on which to call the selector when the data has
 *		 been received. If the method returns true, it will be called
 *		 again when the next line has been received. If you want the
 *		 next method in the queue to handle the next line, you need to
 *		 return false from the method
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, OFString *line,
 *		   OFException *exception)`.
 */
- (void)asyncReadLineWithTarget: (id)target
		       selector: (SEL)selector;


/*!
 * @brief Asynchronously reads with the specified encoding until a newline,
 *	  `\0`, end of stream or an exception occurs.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param encoding The encoding used by the stream
 * @param target The target on which to call the selector when the data has
 *		 been received. If the method returns true, it will be called
 *		 again when the next line has been received. If you want the
 *		 next method in the queue to handle the next line, you need to
 *		 return false from the method
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, OFString *line,
 *		   OFException *exception)`.
 */
- (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding
			   target: (id)target
			 selector: (SEL)selector;


# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously reads until a newline, `\0`, end of stream or an
 *	  exception occurs.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a







|



|
>
















|



|
>







619
620
621
622
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
654
655
656
657
658
659
660
 *
 * @param target The target on which to call the selector when the data has
 *		 been received. If the method returns true, it will be called
 *		 again when the next line has been received. If you want the
 *		 next method in the queue to handle the next line, you need to
 *		 return false from the method
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, OFString *line, id context,
 *		   OFException *exception)`.
 */
- (void)asyncReadLineWithTarget: (id)target
		       selector: (SEL)selector
			context: (nullable id)context;

/*!
 * @brief Asynchronously reads with the specified encoding until a newline,
 *	  `\0`, end of stream or an exception occurs.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param encoding The encoding used by the stream
 * @param target The target on which to call the selector when the data has
 *		 been received. If the method returns true, it will be called
 *		 again when the next line has been received. If you want the
 *		 next method in the queue to handle the next line, you need to
 *		 return false from the method
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, OFString *line,
 *		   id context, OFException *exception)`.
 */
- (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding
			   target: (id)target
			 selector: (SEL)selector
			  context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously reads until a newline, `\0`, end of stream or an
 *	  exception occurs.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a

Modified src/OFStream.m from [e45f32eef4] to [3923d7b75a].

188
189
190
191
192
193
194

195
196
197
198
199
200

201
202
203
204
205
206

207
208
209
210
211
212

213
214
215
216
217
218
219
}

#ifdef OF_HAVE_SOCKETS
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		     target: (id)target
		   selector: (SEL)selector

{
	[OFRunLoop of_addAsyncReadForStream: self
				     buffer: buffer
				     length: length
				     target: target
				   selector: selector];

}

- (void)asyncReadIntoBuffer: (void *)buffer
		exactLength: (size_t)length
		     target: (id)target
		   selector: (SEL)selector

{
	[OFRunLoop of_addAsyncReadForStream: self
				     buffer: buffer
				exactLength: length
				     target: target
				   selector: selector];

}

# ifdef OF_HAVE_BLOCKS
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		      block: (of_stream_async_read_block_t)block
{







>





|
>






>





|
>







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
}

#ifdef OF_HAVE_SOCKETS
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		     target: (id)target
		   selector: (SEL)selector
		    context: (id)context
{
	[OFRunLoop of_addAsyncReadForStream: self
				     buffer: buffer
				     length: length
				     target: target
				   selector: selector
				    context: context];
}

- (void)asyncReadIntoBuffer: (void *)buffer
		exactLength: (size_t)length
		     target: (id)target
		   selector: (SEL)selector
		    context: (id)context
{
	[OFRunLoop of_addAsyncReadForStream: self
				     buffer: buffer
				exactLength: length
				     target: target
				   selector: selector
				    context: context];
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		      block: (of_stream_async_read_block_t)block
{
808
809
810
811
812
813
814

815
816
817
818

819
820
821
822
823

824
825
826
827
828

829
830
831
832
833
834
835

	return line;
}

#ifdef OF_HAVE_SOCKETS
- (void)asyncReadLineWithTarget: (id)target
		       selector: (SEL)selector

{
	[self asyncReadLineWithEncoding: OF_STRING_ENCODING_UTF_8
				 target: target
			       selector: selector];

}

- (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding
			   target: (id)target
			 selector: (SEL)selector

{
	[OFRunLoop of_addAsyncReadLineForStream: self
				       encoding: encoding
					 target: target
				       selector: selector];

}

# ifdef OF_HAVE_BLOCKS
- (void)asyncReadLineWithBlock: (of_stream_async_read_line_block_t)block
{
	[self asyncReadLineWithEncoding: OF_STRING_ENCODING_UTF_8
				  block: block];







>



|
>





>




|
>







812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843

	return line;
}

#ifdef OF_HAVE_SOCKETS
- (void)asyncReadLineWithTarget: (id)target
		       selector: (SEL)selector
			context: (id)context
{
	[self asyncReadLineWithEncoding: OF_STRING_ENCODING_UTF_8
				 target: target
			       selector: selector
				context: context];
}

- (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding
			   target: (id)target
			 selector: (SEL)selector
			  context: (id)context
{
	[OFRunLoop of_addAsyncReadLineForStream: self
				       encoding: encoding
					 target: target
				       selector: selector
					context: context];
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncReadLineWithBlock: (of_stream_async_read_line_block_t)block
{
	[self asyncReadLineWithEncoding: OF_STRING_ENCODING_UTF_8
				  block: block];

Modified src/OFTCPSocket.h from [fe4d222a18] to [d70cc2f958].

123
124
125
126
127
128
129
130

131
132
133
134
135

136
137
138
139
140
141
142
 * @brief Asynchronously connect the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @param target The target on which to call the selector once the connection
 *		 has been established
 * @param selector The selector to call on the target. The signature must be
 *		   `void (OFTCPSocket *socket, OFException *exception)`.

 */
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
		    target: (id)target
		  selector: (SEL)selector;


# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously connect the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to







|
>




|
>







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 * @brief Asynchronously connect the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
 * @param target The target on which to call the selector once the connection
 *		 has been established
 * @param selector The selector to call on the target. The signature must be
 *		   `void (OFTCPSocket *socket, id context,
 *		   OFException *exception)`.
 */
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
		    target: (id)target
		  selector: (SEL)selector
		   context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously connect the OFTCPSocket to the specified destination.
 *
 * @param host The host to connect to
 * @param port The port on the host to connect to
184
185
186
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
 *
 * @param target The target on which to execute the selector when a new
 *		 connection has been accepted. The method returns whether the
 *		 next incoming connection should be accepted by the specified
 *		 block as well.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFTCPSocket *socket, OFTCPSocket *acceptedSocket,
 *		   OFException *exception)`.
 */
- (void)asyncAcceptWithTarget: (id)target
		     selector: (SEL)selector;


#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously accept an incoming connection.
 *
 * @param block The block to execute when a new connection has been accepted.
 *		Returns whether the next incoming connection should be accepted







|


|
>







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
 *
 * @param target The target on which to execute the selector when a new
 *		 connection has been accepted. The method returns whether the
 *		 next incoming connection should be accepted by the specified
 *		 block as well.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFTCPSocket *socket, OFTCPSocket *acceptedSocket,
 *		   id context, OFException *exception)`.
 */
- (void)asyncAcceptWithTarget: (id)target
		     selector: (SEL)selector
		      context: (nullable id)context;

#ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously accept an incoming connection.
 *
 * @param block The block to execute when a new connection has been accepted.
 *		Returns whether the next incoming connection should be accepted

Modified src/OFTCPSocket.m from [9870a76e72] to [e7861c7baa].

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
{
	OFThread *_sourceThread;
	OFTCPSocket *_socket;
	OFString *_host;
	uint16_t _port;
	id _target;
	SEL _selector;

# ifdef OF_HAVE_BLOCKS
	of_tcp_socket_async_connect_block_t _block;
# endif
	OFException *_exception;
}

- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)socket
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector;

# ifdef OF_HAVE_BLOCKS
- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)socket
		  host: (OFString *)host
		  port: (uint16_t)port
		 block: (of_tcp_socket_async_connect_block_t)block;
# endif
@end

@implementation OFTCPSocket_ConnectThread
- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)socket
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector

{
	self = [super init];

	@try {
		_sourceThread = [sourceThread retain];
		_socket = [socket retain];
		_host = [host copy];
		_port = port;
		_target = [target retain];
		_selector = selector;

	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}







>











|
>
















>










>







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
{
	OFThread *_sourceThread;
	OFTCPSocket *_socket;
	OFString *_host;
	uint16_t _port;
	id _target;
	SEL _selector;
	id _context;
# ifdef OF_HAVE_BLOCKS
	of_tcp_socket_async_connect_block_t _block;
# endif
	OFException *_exception;
}

- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)socket
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector
	       context: (id)context;
# ifdef OF_HAVE_BLOCKS
- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)socket
		  host: (OFString *)host
		  port: (uint16_t)port
		 block: (of_tcp_socket_async_connect_block_t)block;
# endif
@end

@implementation OFTCPSocket_ConnectThread
- initWithSourceThread: (OFThread *)sourceThread
		socket: (OFTCPSocket *)socket
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector
	       context: (id)context
{
	self = [super init];

	@try {
		_sourceThread = [sourceThread retain];
		_socket = [socket retain];
		_host = [host copy];
		_port = port;
		_target = [target retain];
		_selector = selector;
		_context = [context retain];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
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

- (void)dealloc
{
	[_sourceThread release];
	[_socket release];
	[_host release];
	[_target release];

# ifdef OF_HAVE_BLOCKS
	[_block release];
# endif
	[_exception release];

	[super dealloc];
}

- (void)didConnect
{
	[self join];

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		_block(_socket, _exception);
	else {
# endif
		void (*func)(id, SEL, OFTCPSocket *, OFException *) =
		    (void (*)(id, SEL, OFTCPSocket *, OFException *))[_target
		    methodForSelector: _selector];

		func(_target, _selector, _socket, _exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

- (id)main
{







>

















|
|
|

|







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

- (void)dealloc
{
	[_sourceThread release];
	[_socket release];
	[_host release];
	[_target release];
	[_context release];
# ifdef OF_HAVE_BLOCKS
	[_block release];
# endif
	[_exception release];

	[super dealloc];
}

- (void)didConnect
{
	[self join];

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		_block(_socket, _exception);
	else {
# endif
		void (*func)(id, SEL, OFTCPSocket *, id, OFException *) =
		    (void (*)(id, SEL, OFTCPSocket *, id, OFException *))
		    [_target methodForSelector: _selector];

		func(_target, _selector, _socket, _context, _exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

- (id)main
{
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335
}

#ifdef OF_HAVE_THREADS
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
		    target: (id)target
		  selector: (SEL)selector

{
	void *pool = objc_autoreleasePoolPush();

	[[[[OFTCPSocket_ConnectThread alloc]
	    initWithSourceThread: [OFThread currentThread]
			  socket: self
			    host: host
			    port: port
			  target: target
			selector: selector] autorelease] start];


	objc_autoreleasePoolPop(pool);
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port







>









|
>







317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
}

#ifdef OF_HAVE_THREADS
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
		    target: (id)target
		  selector: (SEL)selector
		   context: (id)context
{
	void *pool = objc_autoreleasePoolPush();

	[[[[OFTCPSocket_ConnectThread alloc]
	    initWithSourceThread: [OFThread currentThread]
			  socket: self
			    host: host
			    port: port
			  target: target
			selector: selector
			 context: context] autorelease] start];

	objc_autoreleasePoolPop(pool);
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncConnectToHost: (OFString *)host
		      port: (uint16_t)port
570
571
572
573
574
575
576

577
578
579
580

581
582
583
584
585
586
587
	}

	return client;
}

- (void)asyncAcceptWithTarget: (id)target
		     selector: (SEL)selector

{
	[OFRunLoop of_addAsyncAcceptForTCPSocket: self
					  target: target
					selector: selector];

}

#ifdef OF_HAVE_BLOCKS
- (void)asyncAcceptWithBlock: (of_tcp_socket_async_accept_block_t)block
{
	[OFRunLoop of_addAsyncAcceptForTCPSocket: self
					   block: block];







>



|
>







577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
	}

	return client;
}

- (void)asyncAcceptWithTarget: (id)target
		     selector: (SEL)selector
		      context: (id)context
{
	[OFRunLoop of_addAsyncAcceptForTCPSocket: self
					  target: target
					selector: selector
					 context: context];
}

#ifdef OF_HAVE_BLOCKS
- (void)asyncAcceptWithBlock: (of_tcp_socket_async_accept_block_t)block
{
	[OFRunLoop of_addAsyncAcceptForTCPSocket: self
					   block: block];

Modified src/OFUDPSocket.h from [05fb60ba2c] to [dea0dfc05e].

123
124
125
126
127
128
129
130

131
132
133
134
135

136
137
138
139
140
141
142
 *
 * @param host The host to resolve
 * @param port The port for the resulting address
 * @param target The target on which to call the selector once the host has been
 *		 resolved
 * @param selector The selector to call on the target. The signature must be
 *		   `void (OFString *host, uint16_t port,
 *		   of_udp_socket_address_t address, OFException *exception)`.

 */
+ (void)asyncResolveAddressForHost: (OFString *)host
			      port: (uint16_t)port
			    target: (id)target
			  selector: (SEL)selector;


# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously resolves the specified host and creates an address for
 *	  the host / port pair.
 *
 * @param host The host to resolve







|
>




|
>







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 *
 * @param host The host to resolve
 * @param port The port for the resulting address
 * @param target The target on which to call the selector once the host has been
 *		 resolved
 * @param selector The selector to call on the target. The signature must be
 *		   `void (OFString *host, uint16_t port,
 *		   of_udp_socket_address_t address, id context,
 *		   OFException *exception)`.
 */
+ (void)asyncResolveAddressForHost: (OFString *)host
			      port: (uint16_t)port
			    target: (id)target
			  selector: (SEL)selector
			   context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously resolves the specified host and creates an address for
 *	  the host / port pair.
 *
 * @param host The host to resolve
201
202
203
204
205
206
207
208

209
210
211
212
213

214
215
216
217
218
219
220
 *		 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_udp_socket_address_t, OFException *exception)`.

 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
			target: (id)target
		      selector: (SEL)selector;


#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.







|
>




|
>







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
 *		 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_udp_socket_address_t, id context,
 *		   OFException *exception)`.
 */
- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
			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.

Modified src/OFUDPSocket.m from [c8e3c83553] to [c1cf4f8ea1].

47
48
49
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
84
85
86
87
88

89
90
91
92
93
94
95
@interface OFUDPSocket_ResolveThread: OFThread
{
	OFThread *_sourceThread;
	OFString *_host;
	uint16_t _port;
	id _target;
	SEL _selector;

# ifdef OF_HAVE_BLOCKS
	of_udp_socket_async_resolve_block_t _block;
# endif
	of_udp_socket_address_t _address;
	OFException *_exception;
}

- initWithSourceThread: (OFThread *)sourceThread
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector;

# ifdef OF_HAVE_BLOCKS
- initWithSourceThread: (OFThread *)sourceThread
		  host: (OFString *)host
		  port: (uint16_t)port
		 block: (of_udp_socket_async_resolve_block_t)block;
# endif
@end

@implementation OFUDPSocket_ResolveThread
- initWithSourceThread: (OFThread *)sourceThread
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector

{
	self = [super init];

	@try {
		_sourceThread = [sourceThread retain];
		_host = [host retain];
		_port = port;
		_target = [target retain];
		_selector = selector;

	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}







>











|
>














>









>







47
48
49
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
@interface OFUDPSocket_ResolveThread: OFThread
{
	OFThread *_sourceThread;
	OFString *_host;
	uint16_t _port;
	id _target;
	SEL _selector;
	id _context;
# ifdef OF_HAVE_BLOCKS
	of_udp_socket_async_resolve_block_t _block;
# endif
	of_udp_socket_address_t _address;
	OFException *_exception;
}

- initWithSourceThread: (OFThread *)sourceThread
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector
	       context: (id)context;
# ifdef OF_HAVE_BLOCKS
- initWithSourceThread: (OFThread *)sourceThread
		  host: (OFString *)host
		  port: (uint16_t)port
		 block: (of_udp_socket_async_resolve_block_t)block;
# endif
@end

@implementation OFUDPSocket_ResolveThread
- initWithSourceThread: (OFThread *)sourceThread
		  host: (OFString *)host
		  port: (uint16_t)port
		target: (id)target
	      selector: (SEL)selector
	       context: (id)context
{
	self = [super init];

	@try {
		_sourceThread = [sourceThread retain];
		_host = [host retain];
		_port = port;
		_target = [target retain];
		_selector = selector;
		_context = [context retain];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154
# endif

- (void)dealloc
{
	[_sourceThread release];
	[_host release];
	[_target release];

# ifdef OF_HAVE_BLOCKS
	[_block release];
# endif
	[_exception release];

	[super dealloc];
}

- (void)didResolve
{
	[self join];

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		_block(_host, _port, _address, _exception);
	else {
# endif
		void (*func)(id, SEL, OFString *, uint16_t,
		    of_udp_socket_address_t, OFException *) =
		    (void (*)(id, SEL, OFString *, uint16_t,
		    of_udp_socket_address_t, OFException *))[_target
		    methodForSelector: _selector];

		func(_target, _selector, _host, _port, _address, _exception);

# ifdef OF_HAVE_BLOCKS
	}
# endif
}

- (id)main
{







>


















|

|
|

|
>







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# endif

- (void)dealloc
{
	[_sourceThread release];
	[_host release];
	[_target release];
	[_context release];
# ifdef OF_HAVE_BLOCKS
	[_block release];
# endif
	[_exception release];

	[super dealloc];
}

- (void)didResolve
{
	[self join];

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL)
		_block(_host, _port, _address, _exception);
	else {
# endif
		void (*func)(id, SEL, OFString *, uint16_t,
		    of_udp_socket_address_t, id, OFException *) =
		    (void (*)(id, SEL, OFString *, uint16_t,
		    of_udp_socket_address_t, id, OFException *))
		    [_target methodForSelector: _selector];

		func(_target, _selector, _host, _port, _address, _context,
		    _exception);
# ifdef OF_HAVE_BLOCKS
	}
# endif
}

- (id)main
{
319
320
321
322
323
324
325

326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
}

#ifdef OF_HAVE_THREADS
+ (void)asyncResolveAddressForHost: (OFString *)host
			      port: (uint16_t)port
			    target: (id)target
			  selector: (SEL)selector

{
	void *pool = objc_autoreleasePoolPush();

	[[[[OFUDPSocket_ResolveThread alloc]
	    initWithSourceThread: [OFThread currentThread]
			    host: host
			    port: port
			  target: target
			selector: selector] autorelease] start];


	objc_autoreleasePoolPop(pool);
}

# ifdef OF_HAVE_BLOCKS
+ (void)asyncResolveAddressForHost: (OFString *)host
			      port: (uint16_t)port







>








|
>







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
}

#ifdef OF_HAVE_THREADS
+ (void)asyncResolveAddressForHost: (OFString *)host
			      port: (uint16_t)port
			    target: (id)target
			  selector: (SEL)selector
			   context: (id)context
{
	void *pool = objc_autoreleasePoolPush();

	[[[[OFUDPSocket_ResolveThread alloc]
	    initWithSourceThread: [OFThread currentThread]
			    host: host
			    port: port
			  target: target
			selector: selector
			 context: context] autorelease] start];

	objc_autoreleasePoolPop(pool);
}

# ifdef OF_HAVE_BLOCKS
+ (void)asyncResolveAddressForHost: (OFString *)host
			      port: (uint16_t)port
556
557
558
559
560
561
562

563
564
565
566
567
568

569
570
571
572
573
574
575
	return ret;
}

- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
			target: (id)target
		      selector: (SEL)selector

{
	[OFRunLoop of_addAsyncReceiveForUDPSocket: self
					   buffer: buffer
					   length: length
					   target: target
					 selector: selector];

}

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







>





|
>







564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
	return ret;
}

- (void)asyncReceiveIntoBuffer: (void *)buffer
			length: (size_t)length
			target: (id)target
		      selector: (SEL)selector
		       context: (id)context
{
	[OFRunLoop of_addAsyncReceiveForUDPSocket: self
					   buffer: buffer
					   length: length
					   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
{

Modified utils/ofhttp/OFHTTP.m from [2ea2fa69f0] to [fb3cc5ba3d].

776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
	[_currentFileName release];
	_currentFileName = nil;

	[response asyncReadIntoBuffer: _buffer
			       length: [OFSystemInfo pageSize]
			       target: self
			     selector: @selector(stream:didReadIntoBuffer:
					   length:exception:)];


	return;

next:
	[_currentFileName release];
	_currentFileName = nil;

	[self performSelector: @selector(downloadNextURL)
		   afterDelay: 0];
}

-      (bool)stream: (OFHTTPResponse *)response
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length

	  exception: (OFException *)e
{
	if (e != nil) {
		OFString *URL;

		[_progressBar stop];
		[_progressBar draw];







|
>














>







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
	[_currentFileName release];
	_currentFileName = nil;

	[response asyncReadIntoBuffer: _buffer
			       length: [OFSystemInfo pageSize]
			       target: self
			     selector: @selector(stream:didReadIntoBuffer:
					   length:context:exception:)
			      context: nil];

	return;

next:
	[_currentFileName release];
	_currentFileName = nil;

	[self performSelector: @selector(downloadNextURL)
		   afterDelay: 0];
}

-      (bool)stream: (OFHTTPResponse *)response
  didReadIntoBuffer: (void *)buffer
	     length: (size_t)length
	    context: (id)context
	  exception: (OFException *)e
{
	if (e != nil) {
		OFString *URL;

		[_progressBar stop];
		[_progressBar draw];