ObjFW  Check-in [1084b23ef7]

Overview
Comment:OFStream: More flexible repeating async writes
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 1084b23ef749fa92c0f3a737c9eae58ee67bc204b8090257bc9dc8486bf7ee7c
User & Date: js on 2017-09-24 15:13:55
Other Links: manifest | tags
Context
2017-09-24
15:18
Make GCC happy again check-in: 55a159ff58 user: js tags: trunk
15:13
OFStream: More flexible repeating async writes check-in: 1084b23ef7 user: js tags: trunk
13:31
OFHTTPClient: Use asynchronous writes check-in: 502a688f3d user: js tags: trunk
Changes

Modified src/OFHTTPClient.m from [efcbdf0935] to [87324b6d23].

516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
		[_client->_delegate client: _client
		     didEncounterException: e
				forRequest: _request];
		return false;
	}
}

-    (bool)socket: (OFTCPSocket *)socket
  didWriteRequest: (const void *)request
	   length: (size_t)length
	  context: (id)context
	exception: (id)exception
{
	OFData *body;

	if (exception != nil) {







|
|







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
		[_client->_delegate client: _client
		     didEncounterException: e
				forRequest: _request];
		return false;
	}
}

-  (size_t)socket: (OFTCPSocket *)socket
  didWriteRequest: (const void **)request
	   length: (size_t)length
	  context: (id)context
	exception: (id)exception
{
	OFData *body;

	if (exception != nil) {
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
	if ((body = [_request body]) != nil) {
		[socket asyncWriteBuffer: [body items]
				  length: [body count] * [body itemSize]
				  target: self
				selector: @selector(socket:didWriteBody:length:
					      context:exception:)
				 context: nil];
		return false;
	} else
		return [self socket: socket
		       didWriteBody: NULL
			     length: 0
			    context: nil
			  exception: nil];
}

- (bool)socket: (OFTCPSocket *)socket
  didWriteBody: (const void *)body
	length: (size_t)length
       context: (id)context
     exception: (id)exception
{
	[socket asyncReadLineWithTarget: self
			       selector: @selector(socket:didReadLine:context:
					      exception:)
				context: nil];
	return false;
}

- (void)handleSocket: (OFTCPSocket *)socket
{
	/*
	 * As a work around for a bug with split packets in lighttpd when using
	 * HTTPS, we construct the complete request in a buffer string and then







|








|
|
|
|
|





|







546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
	if ((body = [_request body]) != nil) {
		[socket asyncWriteBuffer: [body items]
				  length: [body count] * [body itemSize]
				  target: self
				selector: @selector(socket:didWriteBody:length:
					      context:exception:)
				 context: nil];
		return 0;
	} else
		return [self socket: socket
		       didWriteBody: NULL
			     length: 0
			    context: nil
			  exception: nil];
}

- (size_t)socket: (OFTCPSocket *)socket
    didWriteBody: (const void **)body
	  length: (size_t)length
	 context: (id)context
       exception: (id)exception
{
	[socket asyncReadLineWithTarget: self
			       selector: @selector(socket:didReadLine:context:
					      exception:)
				context: nil];
	return 0;
}

- (void)handleSocket: (OFTCPSocket *)socket
{
	/*
	 * As a work around for a bug with split packets in lighttpd when using
	 * HTTPS, we construct the complete request in a buffer string and then

Modified src/OFRunLoop.m from [8ab72d20c1] to [20e274a7c7].

283
284
285
286
287
288
289
290


291
292
293
294
295
296
297
298
299
300
301
302


303
304
305
306
307
308
309
	_writtenLength += length;

	if (_writtenLength != _length && exception == nil)
		return true;

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL) {
		if (!_block(object, _buffer, _writtenLength, exception))


			return false;

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

		if (!func(_target, _selector, object, _buffer, _writtenLength,
		    _context, exception))


			return false;

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







|
>
>










|
|
>
>







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
	_writtenLength += length;

	if (_writtenLength != _length && exception == nil)
		return true;

# ifdef OF_HAVE_BLOCKS
	if (_block != NULL) {
		_length = _block(object, &_buffer, _writtenLength, exception);

		if (_length == 0)
			return false;

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

		_length = func(_target, _selector, object, &_buffer,
		    _writtenLength, _context, exception);

		if (_length == 0)
			return false;

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

Modified src/OFStream.h from [7472119df2] to [c63c26554d].

64
65
66
67
68
69
70
71


72
73
74

75
76
77

78
79
80
81
82
83
84
85
    OFString *_Nullable line, id _Nullable exception);

/*!
 * @brief A block which is called when data was written to the stream.
 *
 * @param stream The stream to which data was written
 * @param buffer The buffer which was written to the stream
 * @param length The length of the data that bas been written


 * @param exception An exception which occurred while reading or `nil` on
 *		    success
 * @return A bool whether another write with the same buffer, length and

 *	   callback block should be performed
 */
typedef bool (^of_stream_async_write_block_t)(OFStream *stream,

    const void *buffer, size_t length, id _Nullable exception);
#endif

/*!
 * @class OFStream OFStream.h ObjFW/OFStream.h
 *
 * @brief A base class for different types of streams.
 *







|
>
>


|
>
|

|
>
|







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
    OFString *_Nullable line, id _Nullable exception);

/*!
 * @brief A block which is called when data was written to the stream.
 *
 * @param stream The stream to which data was written
 * @param buffer The buffer which was written to the stream
 * @param bytesWritten The number of bytes which have been written. This
 *		       matches the length specified on the asynchronous write
 *		       if no exception was encountered.
 * @param exception An exception which occurred while reading or `nil` on
 *		    success
 * @return The length to repeat the write with or 0 if it should not repeat.
 *	   The buffer may be changed, so that every time a new buffer and length
 *	   can be specified while the callback stays the same.
 */
typedef size_t (^of_stream_async_write_block_t)(OFStream *stream,
    const void *_Nonnull *_Nonnull buffer, size_t bytesWritten,
    id _Nullable exception);
#endif

/*!
 * @class OFStream OFStream.h ObjFW/OFStream.h
 *
 * @brief A base class for different types of streams.
 *
803
804
805
806
807
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
836
837
838
839
840
 * @note The stream must implement @ref fileDescriptorForWriting and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer from which the data is written into the stream. The
 *		 buffer needs to be valid until the write request is completed!
 * @param length The length of the data that should be written
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, the same


 *		 buffer and length will be written again and same method will
 *		 be called again.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, const void *buffer, size_t length,
 *		   id context, id exception)`.
 */
- (void)asyncWriteBuffer: (const void *)buffer
		  length: (size_t)length
		  target: (id)target
		selector: (SEL)selector
		 context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously writes a buffer into the stream.
 *
 * @note The stream must implement @ref fileDescriptorForWriting and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer from which the data is written into the stream. The
 *		 buffer needs to be valid until the write request is completed!
 * @param length The length of the data that should be written
 * @param block The block to call when the data has been written




 */
- (void)asyncWriteBuffer: (const void *)buffer
		  length: (size_t)length
		   block: (of_stream_async_write_block_t)block;
# endif
#endif








|
>
>
|
|

|
|

















|
>
>
>
>







807
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
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
 * @note The stream must implement @ref fileDescriptorForWriting and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer from which the data is written into the stream. The
 *		 buffer needs to be valid until the write request is completed!
 * @param length The length of the data that should be written
 * @param target The target on which the selector should be called when the
 *		 data has been written. The method should return the length for
 *		 the next write with the same callback or 0 if it should not
 *		 repeat. The buffer may be changed, so that every time a new
 *		 buffer and length can be specified while the callback stays
 *		 the same.
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, const void *buffer,
 *		   size_t bytesWritten, id context, id exception)`.
 */
- (void)asyncWriteBuffer: (const void *)buffer
		  length: (size_t)length
		  target: (id)target
		selector: (SEL)selector
		 context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously writes a buffer into the stream.
 *
 * @note The stream must implement @ref fileDescriptorForWriting and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer from which the data is written into the stream. The
 *		 buffer needs to be valid until the write request is completed!
 * @param length The length of the data that should be written
 * @param block The block to call when the data has been written. It should
 *		return the length for the next write with the same callback or
 *		0 if it should not repeat. The buffer may be changed, so that
 *		every time a new buffer and length can be specified while the
 *		callback stays the same.
 */
- (void)asyncWriteBuffer: (const void *)buffer
		  length: (size_t)length
		   block: (of_stream_async_write_block_t)block;
# endif
#endif