@@ -19,27 +19,59 @@ #import "socket.h" /*! @file */ +@class OFUDPSocket; +@class OFException; + /*! * @brief A struct which represents a host / port pair for a UDP socket. */ typedef struct { struct sockaddr_storage address; socklen_t length; } of_udp_socket_address_t; +/*! + * @brief A block which is called when the host / port pair for the UDP socket + * has been resolved. + * + * @param host The host that has been resolved + * @param port The port of the host / port pair + * @param address The address of the resolved host / port pair + * @param exception An exception which occurred while resolving or nil on + * success + */ +typedef void (^of_udp_socket_async_resolve_block_t)(OFString *host, + uint16_t port, of_udp_socket_address_t address, OFException *exception); + +/*! + * @brief A block which is called when a packet has been received. + * + * @param socket The UDP 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 which occurred while receiving or nil on + * success + * @return A bool whether the same block should be used for the next receive + */ +typedef bool (^of_udp_socket_async_receive_block_t)(OFUDPSocket *socket, + void *buffer, size_t length, of_udp_socket_address_t sender, + OFException *exception); + /*! * @brief A class which provides functions to create and use UDP sockets. * - * Addresses are of type @ref of_udp_socket_address_t. You can use - * @ref resolveAddressForHost:port:address: to create an address for a host / - * port pair and @ref hostForAddress:port: to get the host / port pair for an - * address. If you want to compare two addresses, you can use + * Addresses are of type @ref of_udp_socket_address_t. You can use @ref + * getHost:andPort:forAddress: to create an address for a host / port pair and + * @ref getHost:andPort:forAddress: to get the host / port pair for an address. + * If you want to compare two addresses, you can use * @ref of_udp_socket_address_equal and you can use - * @ref of_udp_socket_address_hash to get a hash to use in e.g. @ref OFMapTable. + * @ref of_udp_socket_address_hash to get a hash to use in e.g. + * @ref OFMapTable. */ @interface OFUDPSocket: OFObject { int _socket; @@ -51,21 +83,54 @@ * @return A new, autoreleased OFUDPSocket */ + (instancetype)socket; /*! - * @brief Resolves the specified host and creates a host / port pair together - * with the specified port. + * @brief Resolves the specified host and creates a an address for the host / + * port pair. * * @param host The host to resolve - * @param port The port for the resulting host / port pair + * @param port The port for the resulting address * @param address A pointer to the address that should be filled with the * host / port pair */ + (void)resolveAddressForHost: (OFString*)host port: (uint16_t)port address: (of_udp_socket_address_t*)address; + +#ifdef OF_HAVE_THREADS +/*! + * @brief Asynchronously resolves the specified host and creates an address for + * the host / port pair. + * + * @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 + * @param port The port for the resulting address + * @param block THe block to execute once the host has been resolved + */ ++ (void)asyncResolveAddressForHost: (OFString*)host + port: (uint16_t)port + block: (of_udp_socket_async_resolve_block_t)block; +# endif +#endif /*! * @brief Gets the host and port for the specified address. * * @param host A pointer to an OFString*. If it is not NULL, it will be set to @@ -103,10 +168,54 @@ */ - (size_t)receiveIntoBuffer: (void*)buffer length: (size_t)length sender: (of_udp_socket_address_t*)sender; +/*! + * @brief Asynchronously receives a datagram and stores it into the specified + * buffer. + * + * If the buffer is too small, the datagram is truncated. + * + * @param buffer The buffer to write the datagram to + * @param length The length of the buffer + * @param target The target on which the selector should be called when the + * datagram has been received. If the method returns true, it + * will be called again with the same buffer and maximum length + * when more datagrams have been received. If you want the next + * method in the queue to handle the datagram received next, you + * need to return false from the method. + * @param selector The selector to call on the target. The signature must be + * `bool (OFUDPSocket *socket, void *buffer, size_t length, + * of_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. + * + * @param buffer The buffer to write the datagram to + * @param length The length of the buffer + * @param block The block to call when the datagram has been received. If the + * block 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. + */ +- (void)asyncReceiveIntoBuffer: (void*)buffer + length: (size_t)length + block: (of_udp_socket_async_receive_block_t)block; +#endif + /*! * @brief Sends the specified datagram to the specified address. * * @param buffer The buffer to send as a datagram * @param length The length of the buffer @@ -115,10 +224,15 @@ */ - (void)sendBuffer: (const void*)buffer length: (size_t)length receiver: (of_udp_socket_address_t*)receiver; +/*! + * @brief Cancels all pending asyncronous requests on the socket. + */ +- (void)cancelAsyncRequests; + /*! * @brief Closes the socket so that it can neither receive nor send any more * datagrams. */ - (void)close;