diff --git a/examples/udp_echo_server/Makefile b/examples/udp_echo_server/Makefile new file mode 100644 index 000000000000..b4484be9d18a --- /dev/null +++ b/examples/udp_echo_server/Makefile @@ -0,0 +1,54 @@ +# name of your application +APPLICATION = default + +# If no BOARD is found in the environment, use this default: +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# Uncomment these lines if you want to use platform support from external +# repositories: +#RIOTCPU ?= $(CURDIR)/../../RIOT/thirdparty_cpu +#RIOTBOARD ?= $(CURDIR)/../../RIOT/thirdparty_boards + +# Uncomment this to enable scheduler statistics for ps: +#CFLAGS += -DSCHEDSTATISTICS + +# If you want to use native with valgrind, you should recompile native +# with the target all-valgrind instead of all: +# make -B clean all-valgrind + +# name of your application +APPLICATION = udp_echo_server + +# If no BOARD is found in the environment, use this default: +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +BOARD_INSUFFICIENT_MEMORY := # TODO + +# Include packages that pull up and auto-init the link layer. +# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present +USEMODULE += gnrc_netdev_default +USEMODULE += auto_init_gnrc_netif +# Specify the mandatory networking modules for conn communication via UDP +USEMODULE += gnrc_ipv6_default +USEMODULE += gnrc_udp +USEMODULE += gnrc_conn_udp +# Add also the shell, some shell commands +USEMODULE += shell +USEMODULE += shell_commands +USEMODULE += ps + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +CFLAGS += -DDEVELHELP + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/udp_echo_server/README.md b/examples/udp_echo_server/README.md new file mode 100644 index 000000000000..2d44b2782f58 --- /dev/null +++ b/examples/udp_echo_server/README.md @@ -0,0 +1,79 @@ +examples/udp_echo_server +======================== +This application showcases a simple UDP echo server using RIOT's connectivity +API `conn`. + +It listens on port 61616 for incoming UDP packets and returns them to the +original sender. + +Usage +===== + +Setup +----- +Build, flash and start the application: +``` +export BOARD=your_board +make +make flash +make term +``` + +The `term` make target starts a terminal emulator for your board. It +connects to a default port so you can interact with the shell, usually +that is `/dev/ttyUSB0`. If your port is named differently, the +`PORT=/dev/yourport` variable can be used to override this. + + +Sending a packet to the server +------------------------------ + +The `ifconfig` command will help you to configure and review all available +network configuration. On an `samr21-xpro` it will print something like the +following. The global IPv6 address is available if you set-up a [border +router][6lbr]: + +``` +2016-06-08 17:29:57,780 - INFO # ifconfig +2016-06-08 17:29:57,785 - INFO # Iface 7 HWaddr: 76:0e Channel: 26 Page: 0 +NID: 0x23 +2016-06-08 17:29:57,791 - INFO # Long HWaddr: 5a:5a:5c:5c:87:92:76:0e +2016-06-08 17:29:57,796 - INFO # TX-Power: 0dBm State: IDLE max. Retrans.: 3 CSMA Retries: 4 +2016-06-08 17:29:57,802 - INFO # ACK_REQ CSMA MTU:1280 HL:64 6LO IPHC +2016-06-08 17:29:57,805 - INFO # Source address length: 8 +2016-06-08 17:29:57,816 - INFO # Link type: wireless +2016-06-08 17:29:57,819 - INFO # inet6 addr: ff02::1/128 scope: local [multicast] +2016-06-08 17:29:57,821 - INFO # inet6 addr: fe80::585a:5c5c:8792:760e/64 scope: local +2016-06-08 17:29:57,825 - INFO # inet6 addr: ff02::1:ff92:760e/128 scope: local [multicast] +2016-06-08 17:29:57,830 - INFO # inet6 addr: ff02::1a/128 scope: local [multicast] +2016-06-08 17:29:57,821 - INFO # inet6 addr: 2001:db8::585a:5c5c:8792:760e/64 scope: global +``` + +If you now send a UDP message to one of the IPv6 addresses given with port 61616, +the node will print out this information and return a UDP packet to the sender: + +``` +2016-06-08 17:34:22,417 - INFO # Message "Hello!" receive from [fd00:dead:beef::1]:TODO +``` + +To send a UDP message using e.g. [netcat](http://nc110.sourceforge.net/) +through a [border router][6lbr] or when using the `native` `BOARD`: + +```bash +echo "Hello\!" | nc -6 -u 2001:db8::585a:5c5c:8792:760e 61616 +``` + +Note however, that some versions of `netcat` do not have IPv6 support and might +yield error messages. Because of that, we recommend the BSD version of `netcat`. + +Alternatively you can send with e.g. the [`gnrc_networking` +example][gnrc_networking]: + +``` +udp send fe80::585a:5c5c:8792:760e 61616 "Hello!" +2016-06-08 17:46:09,116 - INFO # > udp send fe80::585a:5c5c:8792:760e 61616 "Hello!" +2016-06-08 17:46:09,124 - INFO # Success: send 6 byte to [fe80::585a:5c5c:8792:760e]:61616 +``` + + [6lbr] ../gnrc_border_router/README.md + [gnrc_networking] ../gnrc_networking/README.md diff --git a/examples/udp_echo_server/main.c b/examples/udp_echo_server/main.c new file mode 100644 index 000000000000..387f1b27b61f --- /dev/null +++ b/examples/udp_echo_server/main.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief Default application that shows a lot of functionality of RIOT + * + * @author Kaspar Schleiser + * @author Martine Lenders + * + * @} + */ + +#include +#include + +#include "net/af.h" +#include "net/conn/udp.h" +#include "msg.h" +#include "shell.h" +#include "shell_commands.h" +#include "thread.h" + +#define ECHO_SERVER_BUFSIZE (64) +#define ECHO_SERVER_PORT (61616) +#define ECHO_SERVER_PRIO (THREAD_PRIORITY_MAIN - 1) +#define ECHO_SERVER_STACK_SIZE (THREAD_STACKSIZE_MAIN) + +/* shell line buffer */ +static char line_buf[SHELL_DEFAULT_BUFSIZE]; +static char echo_server_buf[ECHO_SERVER_BUFSIZE]; +static char echo_server_stack[ECHO_SERVER_STACK_SIZE]; +static const conn_ep_udp_t server_address = { .addr = { .ipv6 = IPV6_ADDR_UNSPECIFIED }, + .family = AF_INET6, + .netif = CONN_EP_ANY_NETIF, + .port = ECHO_SERVER_PORT }; + +static void *echo_server(void *arg) +{ + conn_udp_t server; + + (void)arg; + /* create connectivity end-point for server */ + if (conn_udp_create(&server, &server_address, NULL) < 0) { + puts("Unable to start server"); + return NULL; + } + while (1) { + conn_ep_udp_t client_address; + int res; + + /* wait for packet */ + res = conn_udp_recvfrom(&server, echo_server_buf, + sizeof(echo_server_buf), 0, &client_address); + /* only print out and reply to valid results*/ + if (res >= 0) { + char addr_str[IPV6_ADDR_MAX_STR_LEN]; + + echo_server_buf[res] = '\0'; + /* convert source address to string */ + switch (client_address.family) { + case AF_INET6: + ipv6_addr_to_str(addr_str, + &client_address.addr.ipv6, + sizeof(addr_str)); + break; + default: + memcpy(addr_str, "???", sizeof("???")); + break; + } + /* output received message */ + printf("Message \"%s\" received from [%s]:%u\n", + echo_server_buf, addr_str, client_address.port); + /* send reply */ + conn_udp_sendto(&server, echo_server_buf, res, + &client_address); + } + } + return NULL; +} + +int main(void) +{ + /* start server thread */ + if (thread_create(echo_server_stack, sizeof(echo_server_stack), + ECHO_SERVER_PRIO, THREAD_CREATE_STACKTEST, echo_server, + NULL, "echo_server") <= KERNEL_PID_UNDEF) { + puts("Unable to start server thread"); + return 1; + } + + /* initialize shell with default commands */ + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + + return 0; +} diff --git a/sys/include/net/conn.h b/sys/include/net/conn.h index 2e140eb22517..fc39b2dd8438 100644 --- a/sys/include/net/conn.h +++ b/sys/include/net/conn.h @@ -7,7 +7,7 @@ */ /** - * @defgroup net_conn Application connection API + * @defgroup net_conn Application connectivity API * @ingroup net * @brief Provides a minimal common API for applications to connect to the * different network stacks. @@ -29,42 +29,44 @@ * | Network Stack | * +---------------+ * - * This module provides a minimal set of functions to establish a connection using - * different types of connections. Together, they serve as a common API - * that connects application- and network stack code. + * This module provides a minimal set of functions to establish connectivity or + * send and receives datagrams using different types of connectivity. Together, + * they serve as a common API that connects application- and network stack code. * - * Currently the following connection types are defined: + * Currently the following connectivity types are defined: * - * * @ref conn_ip_t (net/conn/ip.h): raw IP connections - * * @ref conn_tcp_t (net/conn/tcp.h): TCP connections - * * @ref conn_udp_t (net/conn/udp.h): UDP connections + * * @ref conn_ip_t (net/conn/ip.h): raw IP connectivity + * * @ref conn_tcp_t (net/conn/tcp.h): TCP connectivity + * * @ref conn_udp_t (net/conn/udp.h): UDP connectivity * - * Each network stack must implement at least one connection type. + * Each network stack must implement at least one connectivity type. * - * Note that there might be no relation between the different connection types. - * For simplicity and modularity this API doesn't put any restriction of the actual - * implementation of the type. For example, one implementation might choose - * to have all connection types have a common base class or use the raw IPv6 - * connection type to send e.g. UDP packets, while others will keep them + * Note that there might be no relation between the different connectivity + * types. + * For simplicity and modularity this API doesn't put any restriction of the + * actual implementation of the type. For example, one implementation might + * choose to have all connectivity types have a common base class or use the raw + * IPv6 connectivity type to send e.g. UDP packets, while others will keep them * completely separate from each other. * * How To Use * ========== * - * A RIOT application uses the functions provided by one or more of the connection types - * headers (for example @ref conn_udp_t), regardless of the network stack it uses. - * The network stack used under the bonnet is specified by including the appropriate - * module (for example USEMODULE += gnrc_conn_udp) + * A RIOT application uses the functions provided by one or more of the + * connectivity type headers (for example @ref conn_udp), regardless of the + * network stack it uses. + * The network stack used under the bonnet is specified by including the + * appropriate module (for example USEMODULE += gnrc_conn_udp) * * This allows for network stack agnostic code on the application layer. - * The application code to establish a connection is always the same, allowing - * the network stack underneath to be switched simply by changing the USEMODULE - * definition in the application's Makefile. + * The application code to establish connectivity is always the same, allowing + * the network stack underneath to be switched simply by changing the + * `USEMODULE` definitions in the application's Makefile. * * @{ * * @file - * @brief Application connection API definitions + * @brief Application connectivity API definitions * * @author Martine Lenders * @author Oliver Hahm @@ -73,27 +75,16 @@ #ifndef NET_CONN_H_ #define NET_CONN_H_ +#include + #include "net/conn/ip.h" #include "net/conn/tcp.h" #include "net/conn/udp.h" -#include "net/ipv6/addr.h" #ifdef __cplusplus extern "C" { #endif -/** - * @brief Find the best matching source address for a given prefix - * - * @param[in] dst Pointer to the IPv6 address to find a match for - * Must not be NULL - * - * @return NULL if no matching address on any interface could be found - * @return pointer to an IPv6 address configured on an interface with the best - * match to @p dst - */ -ipv6_addr_t *conn_find_best_source(const ipv6_addr_t *dst); - #ifdef __cplusplus } #endif diff --git a/sys/include/net/conn/addr.h b/sys/include/net/conn/addr.h new file mode 100644 index 000000000000..dd7421b53d54 --- /dev/null +++ b/sys/include/net/conn/addr.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup net_conn_addr Address abstractions + * @ingroup net_conn + * @brief Address abstractions for usage with @ref net_conn. + * @{ + * + * @file + * @brief Address abstraction definitions for @ref net_conn. + * + * @author Martine Lenders + */ +#ifndef CONN_ADDR_H_ +#define CONN_ADDR_H_ + +#include "net/ipv4/addr.h" +#include "net/ipv6/addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Type to abstract both IPv4 and IPv6 addresses + */ +typedef union { +#ifdef CONN_HAS_IPV6 + ipv6_addr_t ipv6; /**< IPv6 address mode */ +#endif + ipv4_addr_t ipv4; /**< IPv4 address mode */ +} conn_addr_ip_t; + +#ifdef __cplusplus +} +#endif + +#endif /* CONN_ADDR_H_ */ +/** @} */ diff --git a/sys/include/net/conn/ep.h b/sys/include/net/conn/ep.h new file mode 100644 index 000000000000..a5c7d98d943f --- /dev/null +++ b/sys/include/net/conn/ep.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup net_conn_ep End points + * @ingroup net_conn + * @brief Protocol specific end points for connectivity objects. + * @{ + * + * @file + * @brief Type definitions of protocol specific end points for connectivity + * objects. + * + * @author Martine Lenders + */ +#ifndef CONN_EP_H_ +#define CONN_EP_H_ + +#include + +#include "net/conn/addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Special @ref net_netif "netif" ID for "any interface". + */ +#define CONN_EP_ANY_NETIF (0) + +/** + * @brief An end point for a raw IPv4/IPv6 connectivity object. + */ +typedef struct { + conn_addr_ip_t addr; /**< IP address */ + int family; /**< family of conn_ep_ip_t::addr */ + + /** + * @brief network interface ID as defined in @ref net_netif + * + * Use @ref CONN_EP_ANY_NETIF for any interface. + * For reception this is the local interface the message came over, + * for transmission, this is the local interface the message should be send + * over + */ + uint16_t netif; +} conn_ep_ip_t; + +/** + * @brief An end point for a UDP connectivity object. + */ +typedef struct { + conn_addr_ip_t addr; /**< IP address */ + int family; /**< family of conn_ep_udp_t::addr */ + + /** + * @brief network interface ID as defined in @ref net_netif + * + * Use @ref CONN_EP_ANY_NETIF for any interface. + * For reception this is the local interface the message came over, + * for transmission, this is the local interface the message should be send + * over + */ + uint16_t netif; + uint16_t port; /**< port for the UDP end point */ +} conn_ep_udp_t; + +/** + * @brief An end point for a TCP connectivity object. + */ +typedef struct { + conn_addr_ip_t addr; /**< IP address */ + int family; /**< family of conn_ep_tcp_t::addr */ + + /** + * @brief network interface ID as defined in @ref net_netif + * + * Use @ref CONN_EP_ANY_NETIF for any interface. + * For reception this is the local interface the message came over, + * for transmission, this is the local interface the message should be send + * over + */ + uint16_t netif; + uint16_t port; /**< port for the TCP end point */ +} conn_ep_tcp_t; + +#ifdef __cplusplus +} +#endif + +#endif /* CONN_EP_H_ */ +/** @} */ diff --git a/sys/include/net/conn/ip.h b/sys/include/net/conn/ip.h index 4df3e8626b1e..154f1222c4d3 100644 --- a/sys/include/net/conn/ip.h +++ b/sys/include/net/conn/ip.h @@ -7,22 +7,25 @@ */ /** - * @defgroup net_conn_ip Raw IPv4/IPv6 connections + * @defgroup net_conn_ip Raw IPv4/IPv6 connectivity * @ingroup net_conn - * @brief Connection submodule for raw IPv4/IPv6 connections + * @brief Connectivity submodule for raw IPv4/IPv6 connectivity * @{ * * @file - * @brief Raw IPv4/IPv6 connection definitions + * @brief Raw IPv4/IPv6 connectivity definitions * * @author Martine Lenders */ #ifndef NET_CONN_IP_H_ #define NET_CONN_IP_H_ +#include #include #include +#include "net/conn/ep.h" + #ifdef MODULE_GNRC_CONN_IP #include "net/gnrc/conn.h" #endif @@ -36,93 +39,212 @@ extern "C" { #endif /** - * @brief Forward declaration of @ref conn_ip_t to allow for external definition. + * @brief Implementation-specific type of a raw IPv4/IPv6 connectivity object + * + * `struct conn_ip` needs to be defined by stack-specific a implementation. */ -struct conn_ip; +typedef struct conn_ip conn_ip_t; /** - * @brief Implementation-specific type of a raw IPv4/IPv6 connection object + * @brief Creates a new raw IPv4/IPv6 connectivity object + * + * @pre `(conn != NULL)` + * + * @param[out] conn Preallocated connectivity object. Must fill the size of + * the stack-specific connectivity descriptor. + * @param[in] local Local end point for the connectivity object. + * May be NULL to solicit implicit bind on + * @ref conn_ip_sendto() and @ref conn_ip_send(). + * conn_ep_ip_t::netif must either be + * @ref CONN_EP_ANY_NETIF or equal to conn_ep_ip_t::netif + * of @p remote if `remote != NULL`. + * @param[in] remote Remote end point for the connectivity object. + * May be `NULL` but then the `remote` parameter of + * @ref conn_ip_sendto() may not be `NULL` and + * @ref conn_ip_send() will always error with return value + * -ENOTCONN. conn_ep_ip_t::port may not be 0 if + * `remote != NULL`. + * conn_ep_ip_t::netif must either be + * @ref CONN_EP_ANY_NETIF or equal to conn_ep_ip_t::netif + * of @p local if `local != NULL`. + * @param[in] proto Protocol to use in the raw IPv4/IPv6 connectivity object + * (the `protocol` header field in IPv4 and the `next_header` + * field in IPv6). + * + * @return 0 on success. + * @return -EADDRINUSE, if `local != NULL` and the stack reports that @p local is + * already use elsewhere + * @return -EAFNOSUPPORT, if `local != NULL` or `remote != NULL` and + * conn_ep_ip_t::family of @p local or @p remote is not supported. + * @return -EINVAL, if `proto` is not supported or if conn_ep_ip_t::netif of + * @p local or @p remote is not a valid interface or contradict each + * other (i.e. `(local->netif != remote->netif) && + * ((local->netif != CONN_EP_ANY_NETIF) || + * (remote->netif != CONN_EP_ANY_NETIF))` if neither is `NULL`). + * @return -EPROTONOSUPPORT, if `local != NULL` or `remote != NULL` and + * proto is not supported by conn_ep_ip_t::family of @p local or @p + * remote. */ -typedef struct conn_ip conn_ip_t; +int conn_ip_create(conn_ip_t *conn, const conn_ep_ip_t *local, + const conn_ep_ip_t *remote, uint8_t proto); + +/** + * @brief Closes a raw IPv4/IPv6 connectivity + * + * @pre `(conn != NULL)` + * + * @param[in,out] conn A raw IPv4/IPv6 connectivity object. + */ +void conn_ip_close(conn_ip_t *conn); /** - * @brief Creates a new raw IPv4/IPv6 connection object + * @brief Gets the local end point of a raw IPv4/IPv6 connectivity + * + * @pre `(conn != NULL) && (ep != NULL)` * - * @param[out] conn Preallocated connection object. Must fill the size of the stack-specific - * connection desriptor. - * @param[in] addr The local IP address for @p conn. - * @param[in] addr_len Length of @p addr. Must be fitting for the @p family. - * @param[in] family The family of @p addr (see @ref net_af). - * @param[in] proto @ref net_protnum for the IPv6 packets to receive. + * @param[in] conn A raw IPv4/IPv6 connectivity object. + * @param[out] ep The local end point. * * @return 0 on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' bind() function specification. + * @return -EADDRNOTAVAIL, when @p conn has no end point bound to it. */ -int conn_ip_create(conn_ip_t *conn, const void *addr, size_t addr_len, int family, int proto); +int conn_ip_get_local(conn_ip_t *conn, conn_ep_ip_t *ep); /** - * @brief Closes a raw IPv4/IPv6 connection + * @brief Gets the remote end point of a UDP connectivity * - * @param[in,out] conn A raw IPv4/IPv6 connection object. + * @pre `(conn != NULL) && (ep != NULL)` + * + * @param[in] conn A UDP connectivity object. + * @param[out] ep The remote end point. + * + * @return 0 on success. + * @return -ENOTCONN, when @p conn has no remote end point bound to it. */ -void conn_ip_close(conn_ip_t *conn); +int conn_ip_get_remote(conn_ip_t *conn, conn_ep_ip_t *ep); /** - * @brief Gets the local address of a raw IPv4/IPv6 connection + * @brief Receives a message over IPv4/IPv6 from remote end point + * + * @pre `(conn != NULL) && (data != NULL) && (max_len > 0)` * - * @param[in] conn A raw IPv4/IPv6 connection object. - * @param[out] addr The local IP address. Must have space for any address of the connection's - * family. + * @param[in] conn A raw IPv4/IPv6 connectivity object. + * @param[out] data Pointer where the received data should be stored. + * @param[in] max_len Maximum space available at @p data. + * If received data exceeds @p max_len the data is + * truncated and the remaining data can be retrieved + * later on. + * @param[in] timeout Timeout for receive in microseconds. + * This value can be ignored (no timeout) if the + * @ref sys_xtimer module is not present and the stack does + * not support timeouts on its own. + * May be 0 for no timeout. + * @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 length of @p addr on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' getsockname() function - * specification. + * @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 conn is not given. + * @return -ENOBUFS, if buffer space is not large enough to store received + * data. + * @return -EPROTO, if source address of received packet did not equal + * the remote of @p conn. + * @return -ETIMEDOUT, if @p timeout expired. */ -int conn_ip_getlocaladdr(conn_ip_t *conn, void *addr); +int conn_ip_recvfrom(conn_ip_t *conn, void *data, size_t max_len, + uint32_t timeout, conn_ep_ip_t *remote); /** * @brief Receives a message over IPv4/IPv6 * - * @param[in] conn A raw IPv4/IPv6 connection object. + * @pre `(conn != NULL) && (data != NULL) && (max_len > 0)` + * + * @param[in] conn A raw IPv4/IPv6 connectivity object. * @param[out] data Pointer where the received data should be stored. * @param[in] max_len Maximum space available at @p data. - * @param[out] addr NULL pointer or the sender's IP address. Must have space for any address - * of the connection's family. - * @param[out] addr_len Length of @p addr. Can be NULL if @p addr is NULL. + * If received data exceeds @p max_len the data is + * truncated and the remaining data can be retrieved + * later on. + * @param[in] timeout Timeout for receive in microseconds. + * This value can be ignored (no timeout) if the + * @ref sys_xtimer module is not present and the stack does + * not support timeouts on its own. + * May be 0 for no timeout. * - * @note Function may block. + * @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 any other negative number in case of an error. For portability, implementations should - * draw inspiration of the errno values from the POSIX' recv(), recvfrom(), or recvmsg() - * function specification. + * @return -EADDRNOTAVAIL, if local of @p conn is not given. + * @return -ENOBUFS, if buffer space is not large enough to store received + * data. + * @return -EPROTO, if source address of received packet did not equal + * the remote of @p conn. + * @return -ETIMEDOUT, if @p timeout expired. + */ +static inline int conn_ip_recv(conn_ip_t *conn, void *data, size_t max_len, + uint32_t timeout) +{ + return conn_ip_recvfrom(conn, data, max_len, timeout, NULL); +} + +/** + * @brief Sends a message over IPv4/IPv6 to remote end point + * + * @pre `(if (len != 0): (data != NULL))` + * + * @param[in] conn A raw IPv4/IPv6 connectivity object. May be NULL. + * A sensible local end point should be selected by the + * stack 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 send data. + * May be `NULL`, if @p conn has a remote end point. + * conn_ep_ip_t::family may be AF_UNSPEC, if local + * end point of @p conn provides this information. + * + * @note Function blocks until packet is handed to the stack. + * + * @return The number of bytes send on success. + * @return -EAFNOSUPPORT, if `remote != NULL` and conn_ep_ip_t::family of + * @p remote is != AF_UNSPEC and not supported. + * @return -ENOMEM, if no memory was available to send @p data. + * @return -ENOTCONN, if `remote == NULL`, but @p conn has no remote end point. */ -int conn_ip_recvfrom(conn_ip_t *conn, void *data, size_t max_len, void *addr, size_t *addr_len); +int conn_ip_sendto(conn_ip_t *conn, const void *data, size_t len, + const conn_ep_ip_t *remote); + /** - * @brief Sends a message over IPv4/IPv6 + * @brief Sends a message over IPv4/IPv6 to remote end point * + * @pre `(conn != NULL) && (if (len != 0): (data != NULL))` + * + * @param[in] conn A raw IPv4/IPv6 connectivity object. May be NULL. + * A sensible local end point should be selected by the + * stack 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] src The source address. May be NULL for all any interface address. - * @param[in] src_len Length of @p src. - * @param[in] dst The receiver's network address. - * @param[in] dst_len Length of @p dst. - * @param[in] family The family of @p src and @p dst (see @ref net_af). - * @param[in] proto @ref net_protnum for the IPv6 packets to set. * - * @note Function may block. + * @note Function blocks until packet is handed to the stack. * * @return The number of bytes send on success. - * @return any other negative number in case of an error. For portability, implementations should - * draw inspiration of the errno values from the POSIX' send(), sendfrom(), or sendmsg() - * function specification. + * @return -EINVAL, if conn_ep_ip_t::netif of @p remote is not a valid + * interface or contradicts the given local interface (i.e. + * neither the local endpoint of `conn` nor remote are assigned to + * `CONN_EP_ANY_NETIF` but are nevertheless different. + * @return -ENOMEM, if no memory was available to send @p data. + * @return -ENOTCONN, if @p conn has no remote end point. */ -int conn_ip_sendto(const void *data, size_t len, const void *src, size_t src_len, - void *dst, size_t dst_len, int family, int proto); +static inline int conn_ip_send(conn_ip_t *conn, const void *data, size_t len) +{ + assert(conn != NULL); + return conn_ip_sendto(conn, data, len, NULL); +} #ifdef __cplusplus } diff --git a/sys/include/net/conn/tcp.h b/sys/include/net/conn/tcp.h index aa02fa7e048f..7a5d50f58bfc 100644 --- a/sys/include/net/conn/tcp.h +++ b/sys/include/net/conn/tcp.h @@ -7,13 +7,13 @@ */ /** - * @defgroup net_conn_tcp TCP connections + * @defgroup net_conn_tcp TCP connectivity * @ingroup net_conn - * @brief Connection submodule for TCP connections + * @brief Connectivity submodule for TCP connectivity * @{ * * @file - * @brief TCP connection definitions + * @brief TCP connectivity definitions * * @author Martine Lenders */ @@ -23,6 +23,8 @@ #include #include +#include "net/conn/ep.h" + #ifdef MODULE_GNRC_CONN_TCP #include "net/gnrc/conn.h" #endif @@ -32,140 +34,158 @@ extern "C" { #endif /** - * @brief Forward declaration of @ref conn_tcp_t to allow for external definition. - */ -struct conn_tcp; - -/** - * @brief Implementation-specific type of a TCP connection object + * @brief Implementation-specific type of a TCP connectivity object + * + * `struct conn_tcp` needs to be defined by stack-specific implementation. */ typedef struct conn_tcp conn_tcp_t; /** - * @brief Creates a new TCP connection object - * - * @param[out] conn Preallocated connection object. Must fill the size of the stack-specific - * connection desriptor. - * @param[in] addr The local network layer address for @p conn. - * @param[in] addr_len The length of @p addr. Must be fitting for the @p family. - * @param[in] family The family of @p addr (see @ref net_af). - * @param[in] port The local TCP port for @p conn. + * @brief Creates a new TCP connectivity object + * + * @pre `(conn != NULL)` + * @pre `(local == NULL) || (local->port != 0)` + * + * @param[out] conn Preallocated connectivity object. Must fill the size of + * the stack-specific connectivity descriptor. + * @param[in] local Local end point for the connectivity object. + * May be NULL to solicit implicit bind when @p remote is + * not NULL. + * conn_ep_tcp_t::netif must either be + * @ref CONN_EP_ANY_NETIF or equal to conn_ep_tcp_t::netif + * of @p remote if `remote != NULL`. + * @param[in] remote Remote end point for the connectivity object. + * May be NULL. In this case the connectivity object is a + * listening connectivity object. Call + * @ref conn_tcp_accept() to wait for incoming connection + * requests. + * conn_ep_tcp_t::netif must either be + * @ref CONN_EP_ANY_NETIF or equal to conn_ep_tcp_t::netif + * of @p local if `local != NULL`. * * @return 0 on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' bind() function specification. + * @return -EADDRINUSE, if `local != NULL` and the stack reports that @p local + * is already use elsewhere + * @return -EAFNOSUPPORT, if `local != NULL` or `remote != NULL` and + * conn_ep_tcp_t::family of @p local or @p remote is not supported. + * @return -ECONNREFUSED, if `remote != NULL`, but no-one is listening on this + * address. + * @return -EINVAL, if conn_ep_tcp_t::netif of @p local or @p remote is not a + * valid interface or contradict each other (i.e. + * `(local->netif != remote->netif) && + * ((local->netif != CONN_EP_ANY_NETIF) || + * (remote->netif != CONN_EP_ANY_NETIF))` if neither is `NULL`). + * @return -ENETUNREACH, if `remote != NULL`, but network is not reachable. + * @return -ENOMEM, if system was not able to allocate sufficient memory to + * establish connection. + * @return -EPERM, if connections to @p remote are not permitted on the system + * (e.g. by firewall rules). + * @return -ETIMEDOUT, if `remote != NULL`, but the connection attempt timed + * out. */ -int conn_tcp_create(conn_tcp_t *conn, const void *addr, size_t addr_len, int family, - uint16_t port); +int conn_tcp_create(conn_tcp_t *conn, const conn_ep_tcp_t *local, + const conn_ep_tcp_t *remote); /** * @brief Closes a TCP connection * - * @param[in,out] conn A TCP connection object. - */ -void conn_tcp_close(conn_tcp_t *conn); - -/** - * @brief Gets the local address of a TCP connection - * - * @param[in] conn A TCP connection object. - * @param[out] addr The local network layer address. Must have space for any address of - * the connection's family. - * @param[out] port The local TCP port. + * @pre `(conn != NULL)` * - * @return length of @p addr on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' getsockname() function - * specification. + * @param[in,out] conn A TCP connectivity object. */ -int conn_tcp_getlocaladdr(conn_tcp_t *conn, void *addr, uint16_t *port); +void conn_tcp_close(conn_tcp_t *conn); /** - * @brief Gets the address of the connected peer of a TCP connection - * - * @param[in] conn A TCP connection object. - * @param[out] addr The network layer address of the connected peer. Must have space for any - * address of the connection's family. - * @param[out] port The TCP port of the connected peer. + * @brief Gets the local end point of a TCP connectivity * - * @return length of @p addr on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' getpeername() function - * specification. - */ -int conn_tcp_getpeeraddr(conn_tcp_t *conn, void *addr, uint16_t *port); - -/** - * @brief Connects to a remote TCP peer + * @pre `(conn != NULL) && (ep != NULL)` * - * @param[in] conn A TCP connection object. - * @param[in] addr The remote network layer address for @p conn. - * @param[in] addr_len Length of @p addr. - * @param[in] port The remote TCP port for @p conn. + * @param[in] conn A TCP connectivity object. + * @param[out] ep The local end point. * * @return 0 on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' connect() function specification. + * @return -EADDRNOTAVAIL, when @p conn has no local end point. */ -int conn_tcp_connect(conn_tcp_t *conn, const void *addr, size_t addr_len, uint16_t port); +int conn_tcp_get_local(conn_tcp_t *conn, conn_ep_tcp_t *ep); /** - * @brief Marks connection to listen for a connection request by a remote TCP peer + * @brief Gets the remote end point of a TCP connectivity + * + * @pre `(conn != NULL) && (ep != NULL)` * - * @param[in] conn A TCP connection object. - * @param[in] queue_len Maximum length of the queue for connection requests. - * An implementation may choose to silently adapt this value to its needs - * (setting it to a minimum or maximum value). Any negative number must be - * set at least to 0. + * @param[in] conn A TCP connectivity object. + * @param[out] ep The remote end point. * * @return 0 on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' listen() function specification. + * @return -ENOTCONN, when @p conn is not connected to a remote end point. */ -int conn_tcp_listen(conn_tcp_t *conn, int queue_len); +int conn_tcp_get_remote(conn_tcp_t *conn, conn_ep_tcp_t *ep); /** * @brief Receives and handles TCP connection requests from other peers * - * @param[in] conn A TCP connection object. - * @param[out] out_conn A new TCP connection object for the established connection. + * @pre `(conn != NULL) && (out_conn != NULL)` + * + * @param[in] conn A TCP connectivity object. + * @param[out] out_conn A new TCP connectivity object for the established + * connectivity. * * @return 0 on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' accept() function specification. + * @return -EINVAL, if @p conn is not listening (`remote != NULL` on + * `conn_tcp_create()`). + * @return -ENOMEM, if system was not able to allocate sufficient memory to + * establish connection. + * @return -EPERM, if connections on local endpoint of @p conn are not + * permitted on this system (e.g. by firewall rules). + * @return -ETIMEDOUT, if the operation timed out stack-internally. */ int conn_tcp_accept(conn_tcp_t *conn, conn_tcp_t *out_conn); /** * @brief Receives a TCP message * - * @param[in] conn A TCP connection object. + * @pre `(conn != NULL) && (data != NULL) && (max_len > 0)` + * + * @param[in] conn A TCP connectivity object. * @param[out] data Pointer where the received data should be stored. * @param[in] max_len Maximum space available at @p data. + * If received data exceeds @p max_len the data is + * truncated and the remaining data can be retrieved + * later on. + * @param[in] timeout Timeout for receive in microseconds. + * This value can be ignored (no timeout) if the + * @ref sys_xtimer module is not present and the stack does + * not support timeouts on its own. + * May be 0 for no timeout. * * @note Function may block. * * @return The number of bytes received on success. * @return 0, if no received data is available, but everything is in order. - * @return any other negative number in case of an error. For portability, implementations should - * draw inspiration of the errno values from the POSIX' recv(), recvfrom(), or recvmsg() - * function specification. + * @return -EADDRNOTAVAIL, if local of @p conn is not given. + * @return -ECONNREFUSED, if remote end point of @p conn refused to allow the + * connection. + * @return -ENOTCONN, when @p conn is not connected to a remote end point. + * @return -ETIMEDOUT, if @p timeout expired. */ -int conn_tcp_recv(conn_tcp_t *conn, void *data, size_t max_len); +int conn_tcp_recv(conn_tcp_t *conn, void *data, size_t max_len, + uint32_t timeout); /** * @brief Sends a TCP message * - * @param[in] conn A TCP connection object. + * @pre `(conn != NULL) && (data != NULL) && (max > 0)` + * + * @param[in] conn A TCP connectivity object. * @param[in] data Pointer where the received data should be stored. * @param[in] len Maximum space available at @p data. * * @note Function may block. * * @return The number of bytes send on success. - * @return any other negative number in case of an error. For portability, implementations should - * draw inspiration of the errno values from the POSIX' send(), sendfrom(), or sendmsg() - * function specification. + * @return -ECONNRESET, if connection was reset by remote end point. + * @return -ENOMEM, if no memory was available to send @p data. + * @return -ENOTCONN, if @p conn is not connected to a remote end point. */ int conn_tcp_send(conn_tcp_t *conn, const void *data, size_t len); diff --git a/sys/include/net/conn/udp.h b/sys/include/net/conn/udp.h index b59ac07ce49d..c068431951e4 100644 --- a/sys/include/net/conn/udp.h +++ b/sys/include/net/conn/udp.h @@ -7,22 +7,25 @@ */ /** - * @defgroup net_conn_udp UDP connections + * @defgroup net_conn_udp UDP connectivity * @ingroup net_conn - * @brief Connection submodule for UDP connections + * @brief Connectivity submodule for UDP connectivity * @{ * * @file - * @brief UDP connection definitions + * @brief UDP connectivity definitions * * @author Martine Lenders */ #ifndef NET_CONN_UDP_H_ #define NET_CONN_UDP_H_ +#include #include #include +#include "net/conn/ep.h" + #ifdef MODULE_GNRC_CONN_UDP #include "net/gnrc/conn.h" #endif @@ -40,107 +43,214 @@ extern "C" { #endif /** - * @brief Forward declaration of @ref conn_udp_t to allow for external definition. + * @brief Implementation-specific type of a UDP connectivity object + * + * `struct conn_udp` needs to be defined by stack-specific implementation. */ -struct conn_udp; +typedef struct conn_udp conn_udp_t; /** - * @brief Implementation-specific type of a UDP connection object + * @brief Creates a new UDP connectivity object + * + * @pre `(conn != NULL)` + * @pre `(local == NULL) || (local->port != 0)` + * @pre `(remote == NULL) || (remote->port != 0)` + * + * @param[out] conn Preallocated connectivity object. Must fill the size of the + * stack-specific connectivity desriptor. + * @param[in] local Local end point for the connectivity object. + * May be `NULL` to solicit implicit bind on + * @ref conn_udp_sendto() and @ref conn_udp_send(). + * conn_ep_udp_t::port may not be 0 if `local != NULL`. + * conn_ep_udp_t::netif must either be + * @ref CONN_EP_ANY_NETIF or equal to conn_ep_udp_t::netif + * of @p remote if `remote != NULL`. + * @param[in] remote Remote end point for the connectivity object. + * May be `NULL` but then the `remote` parameter of + * @ref conn_udp_sendto() may not be `NULL` and + * @ref conn_udp_send() will always error with return value + * -ENOTCONN. conn_ep_udp_t::port may not be 0 if + * `remote != NULL`. + * conn_ep_udp_t::netif must either be + * @ref CONN_EP_ANY_NETIF or equal to conn_ep_udp_t::netif + * of @p local if `local != NULL`. + * + * @return 0 on success. + * @return -EADDRINUSE, if `local != NULL` and the stack reports that @p local is + * already use elsewhere + * @return -EAFNOSUPPORT, if `local != NULL` or `remote != NULL` and + * conn_ep_udp_t::family of @p local or @p remote is not supported. + * @return -EINVAL, if conn_ep_udp_t::netif of @p local or @p remote is not a + * valid interface or contradict each other (i.e. + * `(local->netif != remote->netif) && + * ((local->netif != CONN_EP_ANY_NETIF) || + * (remote->netif != CONN_EP_ANY_NETIF))` if neither is `NULL`). + * ` */ -typedef struct conn_udp conn_udp_t; +int conn_udp_create(conn_udp_t *conn, const conn_ep_udp_t *local, + const conn_ep_udp_t *remote); /** - * @brief Creates a new UDP connection object + * @brief Closes a UDP connectivity * - * @param[out] conn Preallocated connection object. Must fill the size of the stack-specific - * connection desriptor. - * @param[in] addr The local network layer address for @p conn. - * @param[in] addr_len The length of @p addr. Must be fitting for the @p family. - * @param[in] family The family of @p addr (see @ref net_af). - * @param[in] port The local UDP port for @p conn. + * @pre `(conn != NULL)` * - * @todo With @ref net_gnrc @ref conn_udp_recvfrom needs to be called from the - * same thread as for this function. This is undesired behavior and - * will be fixed in upcoming versions of RIOT. + * @param[in,out] conn A UDP connectivity object. + */ +void conn_udp_close(conn_udp_t *conn); + +/** + * @brief Gets the local end point of a UDP connectivity + * + * @pre `(conn != NULL) && (ep != NULL)` + * + * @param[in] conn A UDP connectivity object. + * @param[out] ep The local end point. * * @return 0 on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' bind() function specification. + * @return -EADDRNOTAVAIL, when @p conn has no local end point. */ -int conn_udp_create(conn_udp_t *conn, const void *addr, size_t addr_len, int family, - uint16_t port); +int conn_udp_get_local(conn_udp_t *conn, conn_ep_udp_t *ep); /** - * @brief Closes a UDP connection + * @brief Gets the remote end point of a UDP connectivity + * + * @pre `(conn != NULL) && (ep != NULL)` * - * @param[in,out] conn A UDP connection object. + * @param[in] conn A UDP connectivity object. + * @param[out] ep The remote end point. + * + * @return 0 on success. + * @return -ENOTCONN, when @p conn has no remote end point bound to it. */ -void conn_udp_close(conn_udp_t *conn); +int conn_udp_get_remote(conn_udp_t *conn, conn_ep_udp_t *ep); /** - * @brief Gets the local address of a UDP connection + * @brief Receives a UDP message from a remote end point * - * @param[in] conn A UDP connection object. - * @param[out] addr The local network layer address. Must have space for any address of - * the connection's family. - * @param[out] port The local UDP port. + * @pre `(conn != NULL) && (data != NULL) && (max_len > 0)` * - * @return length of @p addr on success. - * @return any other negative number in case of an error. For portability implementations should - * draw inspiration of the errno values from the POSIX' getsockname() function - * specification. + * @param[in] conn A raw IPv4/IPv6 connectivity object. + * @param[out] data Pointer where the received data should be stored. + * @param[in] max_len Maximum space available at @p data. + * If received data exceeds @p max_len the data is + * truncated and the remaining data can be retrieved + * later on. + * @param[in] timeout Timeout for receive in microseconds. + * This value can be ignored (no timeout) if the + * @ref sys_xtimer module is not present and the stack does + * not support timeouts on its own. + * May be 0 for no timeout. + * Must be 0 if @ref sys_xtimer module is not present. + * @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 conn is not given. + * @return -ENOBUFS, if buffer space is not large enough to store received + * data. + * @return -EPROTO, if source address of received packet did not equal + * the remote of @p conn. + * @return -ETIMEDOUT, if @p timeout expired. */ -int conn_udp_getlocaladdr(conn_udp_t *conn, void *addr, uint16_t *port); +int conn_udp_recvfrom(conn_udp_t *conn, void *data, size_t max_len, + uint32_t timeout, conn_ep_udp_t *remote); /** * @brief Receives a UDP message * - * @param[in] conn A UDP connection object. + * @pre `(conn != NULL) && (data != NULL) && (max_len > 0)` + * + * @param[in] conn A raw IPv4/IPv6 connectivity object. May be `NULL`. + * A sensible local end point should be selected by the + * stack in that case. * @param[out] data Pointer where the received data should be stored. * @param[in] max_len Maximum space available at @p data. - * @param[out] addr NULL pointer or the sender's network layer address. Must have space - * for any address of the connection's family. - * @param[out] addr_len Length of @p addr. Can be NULL if @p addr is NULL. - * @param[out] port NULL pointer or the sender's UDP port. - * - * @note Function may block. + * If received data exceeds @p max_len the data is + * truncated and the remaining data can be retrieved + * later on. + * @param[in] timeout Timeout for receive in microseconds. + * This value can be ignored (no timeout) if the + * @ref sys_xtimer module is not present and the stack does + * not support timeouts on its own. + * May be 0 for no timeout. * - * @todo With @ref net_gnrc this function needs to be called from the same - * thread as @ref conn_udp_create. This is undesired behavior and will - * be fixed in upcoming versions of RIOT. + * @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 any other negative number in case of an error. For portability, implementations should - * draw inspiration of the errno values from the POSIX' recv(), recvfrom(), or recvmsg() - * function specification. + * @return -EADDRNOTAVAIL, if local of @p conn is not given. + * @return -ENOBUFS, if buffer space is not large enough to store received + * data. + * @return -EPROTO, if source address of received packet did not equal + * the remote of @p conn. + * @return -ETIMEDOUT, if @p timeout expired. + */ +static inline int conn_udp_recv(conn_udp_t *conn, void *data, size_t max_len, + uint32_t timeout) +{ + return conn_udp_recvfrom(conn, data, max_len, timeout, NULL); +} + +/** + * @brief Sends a UDP message to remote end point + * + * @pre `(if (len != 0): (data != NULL))` + * + * @param[in] conn A raw IPv4/IPv6 connectivity object. May be `NULL`. + * A sensible local end point should be selected by the + * stack 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 send data. + * May be `NULL`, if @p conn has a remote end point. + * conn_ep_udp_t::family may be AF_UNSPEC, if local + * end point of @p conn provides this information. + * conn_ep_udp_t::port may not be 0. + * + * @note Function blocks until packet is handed to the stack. + * + * @return The number of bytes sent on success. + * @return -EAFNOSUPPORT, if `remote != NULL` and conn_ep_udp_t::family of + * @p remote is != AF_UNSPEC and not supported. + * @return -EINVAL, if conn_ep_udp_t::netif of @p remote is not a valid + * interface or contradicts the given local interface (i.e. + * neither the local endpoint of `conn` nor remote are assigned to + * `CONN_EP_ANY_NETIF` but are nevertheless different. + * @return -EINVAL, if conn_ep_udp_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 conn has no remote end point. */ -int conn_udp_recvfrom(conn_udp_t *conn, void *data, size_t max_len, void *addr, size_t *addr_len, - uint16_t *port); +int conn_udp_sendto(conn_udp_t *conn, const void *data, size_t len, + const conn_ep_udp_t *remote); /** * @brief Sends a UDP message * - * @param[in] data Pointer to the data to send. - * @param[in] len Length of the @p data to send. - * @param[in] src The source address. May be NULL for any interface address. - * @param[in] src_len Length of @p src. May be 0 if @p src is NULL - * @param[in] dst The receiver's network address. - * @param[in] dst_len Length of @p dst. - * @param[in] family The family of @p src and @p dst (see @ref net_af). - * @param[in] sport The source UDP port. - * @param[in] dport The receiver's UDP port. + * @pre `(conn != NULL) && (if (len != 0): (data != NULL))` * - * @note Function may block. + * @param[in] conn A raw IPv4/IPv6 connectivity object. May be `NULL`. + * A sensible local end point should be selected by the + * stack 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. + * + * @note Function blocks until packet is handed to the stack. * * @return The number of bytes sent on success. - * @return any other negative number in case of an error. For portability, implementations should - * draw inspiration of the errno values from the POSIX' send(), sendfrom(), or sendmsg() - * function specification. + * @return -ENOMEM, if no memory was available to send @p data. + * @return -ENOTCONN, if @p conn has no remote end point. */ -int conn_udp_sendto(const void *data, size_t len, const void *src, size_t src_len, - const void *dst, size_t dst_len, int family, uint16_t sport, - uint16_t dport); +static inline int conn_udp_send(conn_udp_t *conn, const void *data, size_t len) +{ + assert(conn != NULL); + return conn_udp_sendto(conn, data, len, NULL); +} #ifdef __cplusplus }