@@ -64,10 +64,71 @@ typedef size_t (^of_udp_socket_async_send_block_t)(OFUDPSocket *socket, const void *_Nonnull *_Nonnull buffer, size_t bytesSent, of_socket_address_t *_Nonnull receiver, id exception); #endif +/*! + * @protocol OFUDPSocketDelegate OFUDPSocket.h ObjFW/OFUDPSocket.h + * + * @brief A delegate for OFUDPSocket. + */ +@protocol OFUDPSocketDelegate +@optional +/*! + * @brief This method is called when a packet has been received. + * + * @param socket The UDP socket which received a packet + * @param buffer The buffer the packet has been written to + * @param length The length of the packet + * @param sender The address of the sender of the packet + * @return A bool whether the same block should be used for the next receive + */ +- (bool)socket: (OF_KINDOF(OFUDPSocket *))socket + didReceiveIntoBuffer: (void *)buffer + length: (size_t)length + sender: (of_socket_address_t)sender; + +/*! + * @brief This which is called when a packet has been sent. + * + * @param socket The UDP socket which sent a packet + * @param buffer A pointer to the buffer which was sent. This can be changed to + * point to a different buffer to be used on the next send. + * @param length The length of the buffer that has been sent + * @param receiver The receiver for the UDP packet. This may be set to a new + * receiver to which the next packet is sent. + * @return The length to repeat the send with or 0 if it should not repeat. + * The buffer and receiver may be changed, so that every time a new + * buffer, length and receiver can be specified while the callback + * stays the same. + */ +- (size_t)socket: (OF_KINDOF(OFUDPSocket *))socket + didSendBuffer: (const void *_Nonnull *_Nonnull)buffer + length: (size_t)length + receiver: (of_socket_address_t *_Nonnull)receiver; + +/*! + * @brief This method is called when an exception occurred during an + * asynchronous receive on the socket. + * + * @param socket The socket for which an exception occurred + * @param exception The exception which occurred for the socket + */ +- (void)socket: (OF_KINDOF(OFUDPSocket *))socket + didFailToReceiveWithException: (id)exception; + +/*! + * @brief This method is called when an exception occurred during an + * asynchronous send on the socket. + * + * @param socket The socket for which an exception occurred + * @param exception The exception which occurred for the socket + */ +- (void)socket: (OF_KINDOF(OFUDPSocket *))socket + didFailToSendWithException: (id)exception; +@end + /*! * @class OFUDPSocket OFUDPSocket.h ObjFW/OFUDPSocket.h * * @brief A class which provides methods to create and use UDP sockets. * @@ -91,19 +152,29 @@ of_socket_t _socket; #ifdef OF_WII uint16_t _port; #endif bool _blocking; + id _Nullable _delegate; } /*! * @brief Whether the socket is in blocking mode. * * By default, a socket is in blocking mode. */ @property (nonatomic, getter=isBlocking) bool blocking; +/*! + * @brief The delegate for asynchronous operations on the socket. + * + * @note The delegate is retained for as long as asynchronous operations are + * still outstanding. + */ +@property OF_NULLABLE_PROPERTY (assign, nonatomic) + id delegate; + /*! * @brief Returns a new, autoreleased OFUDPSocket. * * @return A new, autoreleased OFUDPSocket */ @@ -142,26 +213,13 @@ * * If the buffer is too small, the datagram is truncated. * * @param buffer The buffer to write the datagram to * @param length The length of the buffer - * @param target The target on which the selector should be called when the - * datagram has been received. If the method returns true, it - * will be called again with the same buffer and maximum length - * when more datagrams have been received. If you want the next - * method in the queue to handle the datagram received next, you - * need to return false from the method. - * @param selector The selector to call on the target. The signature must be - * `bool (OFUDPSocket *socket, void *buffer, size_t length, - * of_socket_address_t sender, id context, id exception)`. - * @param context A context object to pass along to the target */ - (void)asyncReceiveIntoBuffer: (void *)buffer - length: (size_t)length - target: (id)target - selector: (SEL)selector - context: (nullable id)context; + length: (size_t)length; /*! * @brief Asynchronously receives a datagram and stores it into the specified * buffer. * @@ -168,27 +226,14 @@ * If the buffer is too small, the datagram is truncated. * * @param buffer The buffer to write the datagram to * @param length The length of the buffer * @param runLoopMode The run loop mode in which to perform the async receive - * @param target The target on which the selector should be called when the - * datagram has been received. If the method returns true, it - * will be called again with the same buffer and maximum length - * when more datagrams have been received. If you want the next - * method in the queue to handle the datagram received next, you - * need to return false from the method. - * @param selector The selector to call on the target. The signature must be - * `bool (OFUDPSocket *socket, void *buffer, size_t length, - * of_socket_address_t sender, id context, id exception)`. - * @param context A context object to pass along to the target */ - (void)asyncReceiveIntoBuffer: (void *)buffer length: (size_t)length - runLoopMode: (of_run_loop_mode_t)runLoopMode - target: (id)target - selector: (SEL)selector - context: (nullable id)context; + runLoopMode: (of_run_loop_mode_t)runLoopMode; #ifdef OF_HAVE_BLOCKS /*! * @brief Asynchronously receives a datagram and stores it into the specified * buffer. @@ -247,56 +292,28 @@ * * @param buffer The buffer to send as a datagram * @param length The length of the buffer * @param receiver A pointer to an @ref of_socket_address_t to which the * datagram should be sent - * @param target The target on which the selector should be called when the - * packet has been sent. The method should return the length for - * the next send with the same callback or 0 if it should not - * repeat. The buffer and receiver may be changed, so that every - * time a new buffer, length and receiver can be specified while - * the callback stays the same. - * @param selector The selector to call on the target. The signature must be - * `size_t (OFUDPSocket *socket, const void **buffer, - * size_t bytesSent, of_socket_address_t *receiver, id context, - * id exception)`. - * @param context A context object to pass along to the target */ - (void)asyncSendBuffer: (const void *)buffer length: (size_t)length - receiver: (of_socket_address_t)receiver - target: (id)target - selector: (SEL)selector - context: (nullable id)context; + receiver: (of_socket_address_t)receiver; /*! * @brief Asynchronously sends the specified datagram to the specified address. * * @param buffer The buffer to send as a datagram * @param length The length of the buffer * @param receiver A pointer to an @ref of_socket_address_t to which the * datagram should be sent * @param runLoopMode The run loop mode in which to perform the async send - * @param target The target on which the selector should be called when the - * packet has been sent. The method should return the length for - * the next send with the same callback or 0 if it should not - * repeat. The buffer and receiver may be changed, so that every - * time a new buffer, length and receiver can be specified while - * the callback stays the same. - * @param selector The selector to call on the target. The signature must be - * `size_t (OFUDPSocket *socket, const void **buffer, - * size_t bytesSent, of_socket_address_t *receiver, id context, - * id exception)`. - * @param context A context object to pass along to the target */ - (void)asyncSendBuffer: (const void *)buffer length: (size_t)length receiver: (of_socket_address_t)receiver - runLoopMode: (of_run_loop_mode_t)runLoopMode - target: (id)target - selector: (SEL)selector - context: (nullable id)context; + runLoopMode: (of_run_loop_mode_t)runLoopMode; #ifdef OF_HAVE_BLOCKS /*! * @brief Asynchronously sends the specified datagram to the specified address. *