1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2026-01-01 01:41:18 +01:00

net/sock_udp: Extend API for auxiliary data

This commit is contained in:
Marian Buschsieweke 2020-07-27 12:43:39 +02:00
parent ebcf1c0ab4
commit 893bfd13d0
No known key found for this signature in database
GPG Key ID: 61F64C6599B1539F
3 changed files with 211 additions and 21 deletions

View File

@ -69,8 +69,9 @@ int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep)
0)) ? -ENOTCONN : 0;
}
ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote)
ssize_t sock_udp_recv_aux(sock_udp_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux)
{
void *pkt = NULL;
void *ctx = NULL;
@ -79,8 +80,8 @@ ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
bool nobufs = false;
assert((sock != NULL) && (data != NULL) && (max_len > 0));
while ((res = sock_udp_recv_buf(sock, &pkt, &ctx, timeout,
remote)) > 0) {
while ((res = sock_udp_recv_buf_aux(sock, &pkt, &ctx, timeout,
remote, aux)) > 0) {
struct netbuf *buf = ctx;
if (buf->p->tot_len > (ssize_t)max_len) {
nobufs = true;
@ -95,9 +96,11 @@ ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
return (nobufs) ? -ENOBUFS : ((res < 0) ? res : ret);
}
ssize_t sock_udp_recv_buf(sock_udp_t *sock, void **data, void **ctx,
uint32_t timeout, sock_udp_ep_t *remote)
ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **ctx,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux)
{
(void)aux;
struct netbuf *buf;
int res;
@ -147,9 +150,10 @@ ssize_t sock_udp_recv_buf(sock_udp_t *sock, void **data, void **ctx,
return (ssize_t)buf->ptr->len;
}
ssize_t sock_udp_send(sock_udp_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote)
ssize_t sock_udp_send_aux(sock_udp_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux)
{
(void)aux;
assert((sock != NULL) || (remote != NULL));
assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */

View File

@ -299,6 +299,51 @@ typedef struct sock_udp sock_udp_t;
# pragma clang diagnostic pop
#endif
/**
* @brief Auxiliary data provided when receiving using an UDP sock object
*/
typedef struct {
#if defined(MODULE_SOCK_AUX_LOCAL) || defined(DOXYGEN)
/**
* @brief The local endpoint the datagram was received on
*
* @see SOCK_AUX_GET_LOCAL
*/
sock_udp_ep_t local;
#endif /* MODULE_SOCK_AUX_ENDPOINT */
#if defined(MODULE_SOCK_AUX_TIMESTAMP) || defined(DOXYGEN)
/**
* @brief System time the datagram was received
*
* @see SOCK_AUX_GET_TIMESTAMP
*/
uint64_t timestamp;
#endif /* MODULE_SOCK_AUX_TIMESTAP*/
sock_aux_flags_t flags; /**< Flags used request information */
} sock_udp_aux_rx_t;
/**
* @brief Auxiliary data provided when sending using an UDP sock object
*/
typedef struct {
#if defined(MODULE_SOCK_AUX_TIMESTAMP) || defined(DOXYGEN)
/**
* @brief System time the datagram was send
*
* Add @ref SOCK_AUX_GET_TIMESTAMP to the bitmask in
* @ref sock_udp_aux_tx_t::flags to request a transmission timestamp. This
* bit will be cleared by @ref sock_udp_send_aux if and only if the
* timestamp was provided. The module `sock_aux_timestamp` needs to be
* selected to use this. The timestamp refers to the transmission of start
* of frame delimiter or preamble of the frame carrying the datagram and is
* given in nanoseconds since epoch, unless otherwise documented by the
* underlying implementation.
*/
uint64_t timestamp;
#endif /* MODULE_SOCK_AUX_TIMESTAP*/
sock_aux_flags_t flags; /**< Flags used request information */
} sock_udp_aux_tx_t;
/**
* @brief Creates a new UDP sock object
*
@ -393,6 +438,8 @@ int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep);
* data is available).
* @param[out] remote Remote end point of the received data.
* May be `NULL`, if it is not required by the application.
* @param[out] aux Auxiliary data about the received datagram.
* May be `NULL`, if it is not required by the application.
*
* @note Function blocks if no packet is currently waiting.
*
@ -409,8 +456,95 @@ int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep);
* the remote of @p sock.
* @return -ETIMEDOUT, if @p timeout expired.
*/
ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote);
ssize_t sock_udp_recv_aux(sock_udp_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux);
/**
* @brief Receives a UDP message from a remote end point
*
* @pre `(sock != NULL) && (data != NULL) && (max_len > 0)`
*
* @param[in] sock A UDP sock object.
* @param[out] data Pointer where the received data should be stored.
* @param[in] max_len Maximum space available at @p data.
* @param[in] timeout Timeout for receive in microseconds.
* If 0 and no data is available, the function returns
* immediately.
* May be @ref SOCK_NO_TIMEOUT for no timeout (wait until
* data is available).
* @param[out] remote Remote end point of the received data.
* May be `NULL`, if it is not required by the application.
*
* @note Function blocks if no packet is currently waiting.
*
* @return The number of bytes received on success.
* @return 0, if no received data is available, but everything is in order.
* @return -EADDRNOTAVAIL, if local of @p sock is not given.
* @return -EAGAIN, if @p timeout is `0` and no data is available.
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
* initialized (or closed while sock_udp_recv() blocks).
* @return -ENOBUFS, if buffer space is not large enough to store received
* data.
* @return -ENOMEM, if no memory was available to receive @p data.
* @return -EPROTO, if source address of received packet did not equal
* the remote of @p sock.
* @return -ETIMEDOUT, if @p timeout expired.
*/
static inline ssize_t sock_udp_recv(sock_udp_t *sock,
void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote)
{
return sock_udp_recv_aux(sock, data, max_len, timeout, remote, NULL);
}
/**
* @brief Provides stack-internal buffer space containing a UDP message from
* a remote end point
*
* @pre `(sock != NULL) && (data != NULL) && (buf_ctx != NULL)`
*
* @param[in] sock A UDP sock object.
* @param[out] data Pointer to a stack-internal buffer space containing the
* received data.
* @param[in,out] buf_ctx Stack-internal buffer context. If it points to a
* `NULL` pointer, the stack returns a new buffer space
* for a new packet. If it does not point to a `NULL`
* pointer, an existing context is assumed to get a next
* segment in a buffer.
* @param[in] timeout Timeout for receive in microseconds.
* If 0 and no data is available, the function returns
* immediately.
* May be @ref SOCK_NO_TIMEOUT for no timeout (wait until
* data is available).
* @param[out] remote Remote end point of the received data.
* May be `NULL`, if it is not required by the application.
* @param[out] aux Auxiliary data about the received datagram.
* May be `NULL`, if it is not required by the application.
*
* @experimental This function is quite new, not implemented for all stacks
* yet, and may be subject to sudden API changes. Do not use in
* production if this is unacceptable.
*
* @note Function blocks if no packet is currently waiting.
*
* @return The number of bytes received on success. May not be the complete
* payload. Continue calling with the returned `buf_ctx` to get more
* buffers until result is 0 or an error.
* @return 0, if no received data is available, but everything is in order.
* If @p buf_ctx was provided, it was released.
* @return -EADDRNOTAVAIL, if local of @p sock is not given.
* @return -EAGAIN, if @p timeout is `0` and no data is available.
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
* initialized (or closed while sock_udp_recv() blocks).
* @return -ENOMEM, if no memory was available to receive @p data.
* @return -EPROTO, if source address of received packet did not equal
* the remote of @p sock.
* @return -ETIMEDOUT, if @p timeout expired.
*/
ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux);
/**
* @brief Provides stack-internal buffer space containing a UDP message from
@ -454,8 +588,51 @@ ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
* the remote of @p sock.
* @return -ETIMEDOUT, if @p timeout expired.
*/
ssize_t sock_udp_recv_buf(sock_udp_t *sock, void **data, void **buf_ctx,
uint32_t timeout, sock_udp_ep_t *remote);
static inline ssize_t sock_udp_recv_buf(sock_udp_t *sock,
void **data, void **buf_ctx,
uint32_t timeout,
sock_udp_ep_t *remote)
{
return sock_udp_recv_buf_aux(sock, data, buf_ctx, timeout, remote, NULL);
}
/**
* @brief Sends a UDP message to remote end point
*
* @pre `((sock != NULL || remote != NULL)) && (if (len != 0): (data != NULL))`
*
* @param[in] sock A UDP sock object. May be `NULL`.
* A sensible local end point should be selected by the
* implementation in that case.
* @param[in] data Pointer where the received data should be stored.
* May be `NULL` if `len == 0`.
* @param[in] len Maximum space available at @p data.
* @param[in] remote Remote end point for the sent data.
* May be `NULL`, if @p sock has a remote end point.
* sock_udp_ep_t::family may be AF_UNSPEC, if local
* end point of @p sock provides this information.
* sock_udp_ep_t::port may not be 0.
* @param[out] aux Auxiliary data about the transmission.
* May be `NULL`, if it is not required by the application.
*
* @return The number of bytes sent on success.
* @return -EADDRINUSE, if `sock` has no local end-point or was `NULL` and the
* pool of available ephemeral ports is depleted.
* @return -EAFNOSUPPORT, if `remote != NULL` and sock_udp_ep_t::family of
* @p remote is != AF_UNSPEC and not supported.
* @return -EHOSTUNREACH, if @p remote or remote end point of @p sock is not
* reachable.
* @return -EINVAL, if sock_udp_ep_t::addr of @p remote is an invalid address.
* @return -EINVAL, if sock_udp_ep_t::netif of @p remote is not a valid
* interface or contradicts the given local interface (i.e.
* neither the local end point of `sock` nor remote are assigned to
* `SOCK_ADDR_ANY_NETIF` but are nevertheless different.
* @return -EINVAL, if sock_udp_ep_t::port of @p remote is 0.
* @return -ENOMEM, if no memory was available to send @p data.
* @return -ENOTCONN, if `remote == NULL`, but @p sock has no remote end point.
*/
ssize_t sock_udp_send_aux(sock_udp_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux);
/**
* @brief Sends a UDP message to remote end point
@ -490,8 +667,12 @@ ssize_t sock_udp_recv_buf(sock_udp_t *sock, void **data, void **buf_ctx,
* @return -ENOMEM, if no memory was available to send @p data.
* @return -ENOTCONN, if `remote == NULL`, but @p sock has no remote end point.
*/
ssize_t sock_udp_send(sock_udp_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote);
static inline ssize_t sock_udp_send(sock_udp_t *sock,
const void *data, size_t len,
const sock_udp_ep_t *remote)
{
return sock_udp_send_aux(sock, data, len, remote, NULL);
}
#include "sock_types.h"

View File

@ -174,8 +174,9 @@ int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *remote)
return 0;
}
ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote)
ssize_t sock_udp_recv_aux(sock_udp_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux)
{
void *pkt = NULL, *ctx = NULL;
uint8_t *ptr = data;
@ -183,7 +184,8 @@ ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
bool nobufs = false;
assert((sock != NULL) && (data != NULL) && (max_len > 0));
while ((res = sock_udp_recv_buf(sock, &pkt, &ctx, timeout, remote)) > 0) {
while ((res = sock_udp_recv_buf_aux(sock, &pkt, &ctx, timeout, remote,
aux)) > 0) {
if (res > (ssize_t)max_len) {
nobufs = true;
continue;
@ -195,9 +197,11 @@ ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
return (nobufs) ? -ENOBUFS : ((res < 0) ? res : ret);
}
ssize_t sock_udp_recv_buf(sock_udp_t *sock, void **data, void **buf_ctx,
uint32_t timeout, sock_udp_ep_t *remote)
ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
uint32_t timeout, sock_udp_ep_t *remote,
sock_udp_aux_rx_t *aux)
{
(void)aux;
gnrc_pktsnip_t *pkt, *udp;
udp_hdr_t *hdr;
sock_ip_ep_t tmp;
@ -242,9 +246,10 @@ ssize_t sock_udp_recv_buf(sock_udp_t *sock, void **data, void **buf_ctx,
return res;
}
ssize_t sock_udp_send(sock_udp_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote)
ssize_t sock_udp_send_aux(sock_udp_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux)
{
(void)aux;
int res;
gnrc_pktsnip_t *payload, *pkt;
uint16_t src_port = 0, dst_port;