Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -1869,16 +1869,20 @@ - (bool)socket: (OF_KINDOF(OFUDPSocket *))sock didReceiveIntoBuffer: (void *)buffer_ length: (size_t)length sender: (of_socket_address_t)sender + exception: (id)exception { unsigned char *buffer = buffer_; OFDictionary *answerRecords = nil, *authorityRecords = nil; OFDictionary *additionalRecords = nil; OFNumber *ID; OFDNSResolverQuery *query; + + if (exception != nil) + return true; if (length < 2) /* We can't get the ID to get the query. Ignore packet. */ return true; @@ -2010,17 +2014,10 @@ query->_context, nil); return true; } -- (void)socket: (OF_KINDOF(OFUDPSocket *))sock - didFailToReceiveWithException: (id)exception -{ - [sock asyncReceiveIntoBuffer: _buffer - length: BUFFER_LENGTH]; -} - - (void)asyncResolveSocketAddressesForHost: (OFString *)host target: (id)target selector: (SEL)selector context: (id)context { Index: src/OFHTTPClient.m ================================================================== --- src/OFHTTPClient.m +++ src/OFHTTPClient.m @@ -527,12 +527,22 @@ return true; } - (bool)stream: (OF_KINDOF(OFStream *))sock didReadLine: (OFString *)line + exception: (id)exception { bool ret; + + if (exception != nil) { + if ([exception isKindOfClass: + [OFInvalidEncodingException class]]) + exception = [OFInvalidServerReplyException exception]; + + [self raiseException: exception]; + return false; + } @try { if (_firstLine) { _firstLine = false; ret = [self handleFirstLine: line]; @@ -545,36 +555,28 @@ } return ret; } -- (void)stream: (OF_KINDOF(OFStream *))sock - didFailToReadWithException: (id)exception -{ - if ([exception isKindOfClass: [OFInvalidEncodingException class]]) - exception = [OFInvalidServerReplyException exception]; - - [self raiseException: exception]; -} - -- (void)stream: (OF_KINDOF(OFStream *))sock - didFailToWriteWithException: (id)exception -{ - if ([exception isKindOfClass: [OFWriteFailedException class]] && - ([exception errNo] == ECONNRESET || [exception errNo] == EPIPE)) { - /* In case a keep-alive connection timed out */ - [self closeAndReconnect]; - return; - } - - [self raiseException: exception]; -} - - (size_t)stream: (OF_KINDOF(OFStream *))sock didWriteBuffer: (const void **)request length: (size_t)length + exception: (id)exception { + if (exception != nil) { + if ([exception isKindOfClass: [OFWriteFailedException class]] && + ([exception errNo] == ECONNRESET || + [exception errNo] == EPIPE)) { + /* In case a keep-alive connection timed out */ + [self closeAndReconnect]; + return 0; + } + + [self raiseException: exception]; + return 0; + } + _firstLine = true; [_requestString release]; _requestString = nil; @@ -622,12 +624,18 @@ } - (void)socket: (OF_KINDOF(OFTCPSocket *))sock didConnectToHost: (OFString *)host port: (uint16_t)port + exception: (id)exception { [(OFTCPSocket *)sock setDelegate: self]; + + if (exception != nil) { + [self raiseException: exception]; + return; + } if ([_client->_delegate respondsToSelector: @selector(client:didCreateSocket:request:context:)]) [_client->_delegate client: _client didCreateSocket: sock Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -401,12 +401,13 @@ [super dealloc]; } - (bool)stream: (OF_KINDOF(OFStream *))sock didReadLine: (OFString *)line + exception: (id)exception { - if (line == nil) + if (line == nil || exception != nil) return false; @try { switch (_state) { case AWAITING_PROLOG: @@ -787,26 +788,28 @@ _listeningSocket = nil; } - (bool)socket: (OF_KINDOF(OFTCPSocket *))sock didAcceptSocket: (OF_KINDOF(OFTCPSocket *))acceptedSocket + exception: (id)exception { - OFHTTPServer_Connection *connection = [[[OFHTTPServer_Connection alloc] + OFHTTPServer_Connection *connection; + + if (exception != nil) { + if (![_delegate respondsToSelector: + @selector(server:didReceiveExceptionOnListeningSocket:)]) + return false; + + return [_delegate server: self + didReceiveExceptionOnListeningSocket: exception]; + } + + connection = [[[OFHTTPServer_Connection alloc] initWithSocket: acceptedSocket server: self] autorelease]; [(OFTCPSocket *)acceptedSocket setDelegate: connection]; [acceptedSocket asyncReadLine]; return true; } - -- (void)stream: (OF_KINDOF(OFStream *))stream - didFailToAcceptWithException: (id)exception -{ - if ([_delegate respondsToSelector: - @selector(server:didReceiveExceptionOnListeningSocket:)]) - if ([_delegate server: self - didReceiveExceptionOnListeningSocket: exception]) - [stream asyncAccept]; -} @end Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -321,26 +321,18 @@ # ifdef OF_HAVE_BLOCKS if (_block != NULL) return _block(object, _buffer, length, exception); else { # endif - if (exception == nil) { - if (![_delegate respondsToSelector: - @selector(stream:didReadIntoBuffer:length:)]) - return false; - - return [_delegate stream: object - didReadIntoBuffer: _buffer - length: length]; - } else { - if ([_delegate respondsToSelector: - @selector(stream:didFailToReadWithException:)]) - [_delegate stream: object - didFailToReadWithException: exception]; - - return false; - } + if (![_delegate respondsToSelector: + @selector(stream:didReadIntoBuffer:length:exception:)]) + return false; + + return [_delegate stream: object + didReadIntoBuffer: _buffer + length: length + exception: exception]; # ifdef OF_HAVE_BLOCKS } # endif } @@ -381,30 +373,22 @@ _readLength = 0; return true; } else { # endif - if (exception == nil) { - if (![_delegate respondsToSelector: - @selector(stream:didReadIntoBuffer:length:)]) - return false; - - if (![_delegate stream: object - didReadIntoBuffer: _buffer - length: _readLength]) - return false; - - _readLength = 0; - return true; - } else { - if ([_delegate respondsToSelector: - @selector(stream:didFailToReadWithException:)]) - [_delegate stream: object - didFailToReadWithException: exception]; - - return false; - } + if (![_delegate respondsToSelector: + @selector(stream:didReadIntoBuffer:length:exception:)]) + return false; + + if (![_delegate stream: object + didReadIntoBuffer: _buffer + length: _readLength + exception: exception]) + return false; + + _readLength = 0; + return true; # ifdef OF_HAVE_BLOCKS } # endif } @@ -437,25 +421,17 @@ # ifdef OF_HAVE_BLOCKS if (_block != NULL) return _block(object, line, exception); else { # endif - if (exception == nil) { - if (![_delegate respondsToSelector: - @selector(stream:didReadLine:)]) - return false; - - return [_delegate stream: object - didReadLine: line]; - } else { - if ([_delegate respondsToSelector: - @selector(stream:didFailToReadWithException:)]) - [_delegate stream: object - didFailToReadWithException: exception]; - - return false; - } + if (![_delegate respondsToSelector: + @selector(stream:didReadLine:exception:)]) + return false; + + return [_delegate stream: object + didReadLine: line + exception: exception]; # ifdef OF_HAVE_BLOCKS } # endif } @@ -497,32 +473,24 @@ _writtenLength = 0; return true; } else { # endif - if (exception == nil) { - if (![_delegate respondsToSelector: - @selector(stream:didWriteBuffer:length:)]) - return false; - - _length = [_delegate stream: object - didWriteBuffer: &_buffer - length: _length]; - - if (_length == 0) - return false; - - _writtenLength = 0; - return true; - } else { - if ([_delegate respondsToSelector: - @selector(stream:didFailToWriteWithException:)]) - [_delegate stream: object - didFailToWriteWithException: exception]; - - return false; - } + if (![_delegate respondsToSelector: + @selector(stream:didWriteBuffer:length:exception:)]) + return false; + + _length = [_delegate stream: object + didWriteBuffer: &_buffer + length: _length + exception: exception]; + + if (_length == 0) + return false; + + _writtenLength = 0; + return true; # ifdef OF_HAVE_BLOCKS } # endif } @@ -574,25 +542,17 @@ # ifdef OF_HAVE_BLOCKS if (_block != NULL) return _block(object, acceptedSocket, exception); else { # endif - if (exception == nil) { - if (![_delegate respondsToSelector: - @selector(socket:didAcceptSocket:)]) - return false; - - return [_delegate socket: object - didAcceptSocket: acceptedSocket]; - } else { - if ([_delegate respondsToSelector: - @selector(socket:didFailToAcceptWithException:)]) - [_delegate socket: object - didFailToAcceptWithException: exception]; - - return false; - } + if (![_delegate respondsToSelector: + @selector(socket:didAcceptSocket:exception:)]) + return false; + + return [_delegate socket: object + didAcceptSocket: acceptedSocket + exception: exception]; # ifdef OF_HAVE_BLOCKS } # endif } @@ -625,27 +585,19 @@ # 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; - } + if (![_delegate respondsToSelector: @selector( + socket:didReceiveIntoBuffer:length:sender:exception:)]) + return false; + + return [_delegate socket: object + didReceiveIntoBuffer: _buffer + length: length + sender: address + exception: exception]; # ifdef OF_HAVE_BLOCKS } # endif } @@ -678,29 +630,21 @@ (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; - } + if (![_delegate respondsToSelector: + @selector(socket:didSendBuffer:length:receiver:exception:)]) + return false; + + _length = [_delegate socket: object + didSendBuffer: &_buffer + length: (exception == nil ? _length : 0) + receiver: &_receiver + exception: exception]; + + return (_length > 0); # ifdef OF_HAVE_BLOCKS } # endif } Index: src/OFStream.h ================================================================== --- src/OFStream.h +++ src/OFStream.h @@ -101,27 +101,31 @@ * stream. * * @param stream The stream on which data was read * @param buffer A buffer with the data that has been read * @param length The length of the data that has been read + * @param exception An exception that occurred while reading, or nil on success * @return A bool whether the read should be repeated */ - (bool)stream: (OF_KINDOF(OFStream *))stream didReadIntoBuffer: (void *)buffer - length: (size_t)length; + length: (size_t)length + exception: (nullable id)exception; /*! * @brief This method is called when a line was read asynchronously from a * stream. * * @param stream The stream on which a line was read * @param line The line which has been read or `nil` when the end of stream * occurred + * @param exception An exception that occurred while reading, or nil on success * @return A bool whether the read should be repeated */ - (bool)stream: (OF_KINDOF(OFStream *))stream - didReadLine: (nullable OFString *)line; + didReadLine: (nullable OFString *)line + exception: (nullable id)exception; /*! * @brief This method is called when data was written asynchronously to a * stream. * @@ -128,37 +132,19 @@ * @param stream The stream to which data was written * @param buffer A pointer to the buffer which was written to the stream. This * can be changed to point to a different buffer to be used on the * next write. * @param length The length of the buffer that has been written + * @param exception An exception that occurred while writing, 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 */ - (size_t)stream: (OF_KINDOF(OFStream *))stream didWriteBuffer: (const void *_Nonnull *_Nonnull)buffer - length: (size_t)length; - -/*! - * @brief This method is called when an exception occurred during an - * asynchronous read on a stream. - * - * @param stream The stream for which an exception occurred - * @param exception The exception which occurred for the stream - */ -- (void)stream: (OF_KINDOF(OFStream *))stream - didFailToReadWithException: (id)exception; - -/*! - * @brief This method is called when an exception occurred during an - * asynchronous write on a stream. - * - * @param stream The stream for which an exception occurred - * @param exception The exception which occurred for the stream - */ -- (void)stream: (OF_KINDOF(OFStream *))stream - didFailToWriteWithException: (id)exception; + length: (size_t)length + exception: (nullable id)exception; @end /*! * @class OFStream OFStream.h ObjFW/OFStream.h * Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -62,48 +62,32 @@ @optional /*! * @brief A method which is called when a socket connected. * * @param socket The socket which connected + * @param host The host connected to + * @param port The port on the host connected to + * @param exception An exception that occurred while connecting, or nil on + * success */ - (void)socket: (OF_KINDOF(OFTCPSocket *))socket didConnectToHost: (OFString *)host - port: (uint16_t)port; + port: (uint16_t)port + exception: (nullable id)exception; /*! * @brief A method which is called when a socket accepted a connection. * * @param socket The socket which accepted the connection * @param acceptedSocket The socket which has been accepted + * @param exception An exception that occurred while accepting, or nil on + * success * @return A bool whether to accept the next incoming connection */ - (bool)socket: (OF_KINDOF(OFTCPSocket *))socket - didAcceptSocket: (OF_KINDOF(OFTCPSocket *))acceptedSocket; - -/*! - * @brief This method is called when an exception occurred during an - * asynchronous connect. - * - * @param socket The socket for which an exception occurred - * @param exception The exception which occurred for the stream - * @param host The host to which the connection failed - * @param port The port on the host to which the connection failed - */ -- (void)socket: (OF_KINDOF(OFTCPSocket *))socket - didFailToConnectWithException: (id)exception - host: (OFString *)host - port: (uint16_t)port; - -/*! - * @brief This method is called when an exception occurred during an - * asynchronous accept. - * - * @param socket The socket for which an exception occurred - * @param exception The exception which occurred for the stream - */ -- (void)socket: (OF_KINDOF(OFTCPSocket *))socket - didFailToAcceptWithException: (id)exception; + didAcceptSocket: (OF_KINDOF(OFTCPSocket *))acceptedSocket + exception: (nullable id)exception; @end /*! * @class OFTCPSocket OFTCPSocket.h ObjFW/OFTCPSocket.h * Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -210,24 +210,16 @@ _block(_socket, _exception); else { #endif [_socket setDelegate: _delegate]; - if (_exception == nil) { - if ([_delegate respondsToSelector: - @selector(socket:didConnectToHost:port:)]) - [_delegate socket: _socket - didConnectToHost: _host - port: _port]; - } else { - if ([_delegate respondsToSelector: @selector(socket: - didFailToConnectWithException:host:port:)]) - [_delegate socket: _socket - didFailToConnectWithException: _exception - host: _host - port: _port]; - } + if ([_delegate respondsToSelector: + @selector(socket:didConnectToHost:port:exception:)]) + [_delegate socket: _socket + didConnectToHost: _host + port: _port + exception: _exception]; #ifdef OF_HAVE_BLOCKS } #endif } @@ -378,18 +370,26 @@ } - (bool)stream: (OF_KINDOF(OFStream *))sock didReadIntoBuffer: (void *)buffer length: (size_t)length + exception: (id)exception { - of_run_loop_mode_t runLoopMode = - [[OFRunLoop currentRunLoop] currentMode]; + of_run_loop_mode_t runLoopMode; unsigned char *SOCKSVersion; uint8_t hostLength; unsigned char port[2]; unsigned char *response, *addressLength; + if (exception != nil) { + _exception = [exception retain]; + [self didConnect]; + return false; + } + + runLoopMode = [[OFRunLoop currentRunLoop] currentMode]; + switch (_SOCKS5State) { case SOCKS5_STATE_READ_VERSION: SOCKSVersion = buffer; if (SOCKSVersion[0] != 5 || SOCKSVersion[1] != 0) { @@ -524,13 +524,21 @@ } - (size_t)stream: (OF_KINDOF(OFStream *))sock didWriteBuffer: (const void **)buffer length: (size_t)length + exception: (id)exception { - of_run_loop_mode_t runLoopMode = - [[OFRunLoop currentRunLoop] currentMode]; + of_run_loop_mode_t runLoopMode; + + if (exception != nil) { + _exception = [exception retain]; + [self didConnect]; + return 0; + } + + runLoopMode = [[OFRunLoop currentRunLoop] currentMode]; switch (_SOCKS5State) { case SOCKS5_STATE_SEND_AUTHENTICATION: _SOCKS5State = SOCKS5_STATE_READ_VERSION; [_socket asyncReadIntoBuffer: _buffer @@ -549,24 +557,10 @@ default: assert(0); return 0; } } - -- (void)stream: (OF_KINDOF(OFStream *))sock - didFailToReadWithException: (id)exception -{ - _exception = [exception retain]; - [self didConnect]; -} - -- (void)stream: (OF_KINDOF(OFStream *))sock - didFailToWriteWithException: (id)exception -{ - _exception = [exception retain]; - [self didConnect]; -} @end @implementation OFTCPSocket_ConnectDelegate - (void)dealloc { @@ -576,16 +570,11 @@ } - (void)socket: (OF_KINDOF(OFTCPSocket *))sock didConnectToHost: (OFString *)host port: (uint16_t)port -{ - _done = true; -} - -- (void)socket: (OF_KINDOF(OFTCPSocket *))sock - didFailToConnectWithException: (id)exception + exception: (id)exception { _done = true; _exception = [exception retain]; } @end Index: src/OFUDPSocket.h ================================================================== --- src/OFUDPSocket.h +++ src/OFUDPSocket.h @@ -78,16 +78,19 @@ * * @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 + * @param exception An exception that occurred while receiving, or nil on + * success * @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; + sender: (of_socket_address_t)sender + exception: (nullable id)exception; /*! * @brief This which is called when a packet has been sent. * * @param socket The UDP socket which sent a packet @@ -94,39 +97,21 @@ * @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. + * @param exception An exception that occurred while sending, or nil on success * @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; + receiver: (of_socket_address_t *_Nonnull)receiver + exception: (nullable id)exception; @end /*! * @class OFUDPSocket OFUDPSocket.h ObjFW/OFUDPSocket.h * Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -654,11 +654,37 @@ } - (bool)stream: (OF_KINDOF(OFStream *))response didReadIntoBuffer: (void *)buffer length: (size_t)length + exception: (id)exception { + if (exception != nil) { + OFString *URL; + + [_progressBar stop]; + [_progressBar draw]; + [_progressBar release]; + _progressBar = nil; + + if (!_quiet) + [of_stdout writeString: @"\n Error!\n"]; + + URL = [_URLs objectAtIndex: _URLIndex - 1]; + [of_stderr writeLine: OF_LOCALIZED( + @"download_failed_exception", + @"%[prog]: Failed to download <%[url]>: %[exception]", + @"prog", [OFApplication programName], + @"url", URL, + @"exception", exception)]; + + _errorCode = 1; + [self performSelector: @selector(downloadNextURL) + afterDelay: 0]; + return false; + } + _received += length; [_output writeBuffer: buffer length: length]; @@ -683,36 +709,10 @@ } return true; } -- (void)stream: (OF_KINDOF(OFStream *))response - didFailWithException: (id)exception -{ - OFString *URL; - - [_progressBar stop]; - [_progressBar draw]; - [_progressBar release]; - _progressBar = nil; - - if (!_quiet) - [of_stdout writeString: @"\n Error!\n"]; - - URL = [_URLs objectAtIndex: _URLIndex - 1]; - [of_stderr writeLine: OF_LOCALIZED( - @"download_failed_exception", - @"%[prog]: Failed to download <%[url]>: %[exception]", - @"prog", [OFApplication programName], - @"url", URL, - @"exception", exception)]; - - _errorCode = 1; - [self performSelector: @selector(downloadNextURL) - afterDelay: 0]; -} - - (void)client: (OFHTTPClient *)client didReceiveHeaders: (OFDictionary OF_GENERIC(OFString *, OFString *) *)headers statusCode: (int)statusCode request: (OFHTTPRequest *)request context: (id)context