From 8fd96713c90050821eda1e2277e186acc51d6dc4 Mon Sep 17 00:00:00 2001 From: Tymoteusz Bloch Date: Wed, 30 Jun 2021 20:09:41 +0200 Subject: [PATCH] New feature: send/recv message implementation added to network stack --- .../cellular/framework/AT/AT_CellularStack.h | 15 ++ .../lwipstack/include/lwipstack/LWIPStack.h | 43 ++++++ .../lwipstack/include/lwipstack/lwipopts.h | 3 + connectivity/lwipstack/source/LWIPStack.cpp | 142 +++++++++++++++--- .../include/nanostack-interface/Nanostack.h | 15 ++ .../netsocket/InternetDatagramSocket.h | 55 ++++++- .../netsocket/include/netsocket/MsgHeader.h | 79 ++++++++++ .../include/netsocket/NetworkStack.h | 45 ++++++ .../netsocket/include/netsocket/Socket.h | 49 ++++++ .../netsocket/include/netsocket/TCPSocket.h | 8 + .../netsocket/include/netsocket/nsapi_types.h | 30 +++- .../source/InternetDatagramSocket.cpp | 20 ++- .../netsocket/source/NetworkStack.cpp | 30 ++++ connectivity/netsocket/source/TCPSocket.cpp | 22 +++ 14 files changed, 525 insertions(+), 31 deletions(-) create mode 100644 connectivity/netsocket/include/netsocket/MsgHeader.h diff --git a/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h b/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h index 11308f87cda9..59ce6638b73d 100644 --- a/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h +++ b/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h @@ -88,6 +88,21 @@ class AT_CellularStack : public NetworkStack { virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data); + // FIXME + nsapi_size_or_error_t socket_sendmsg(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override + { + return NSAPI_ERROR_UNSUPPORTED; + } + + nsapi_size_or_error_t socket_recvmsg(nsapi_socket_t handle, SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override + { + return NSAPI_ERROR_UNSUPPORTED; + } + protected: class CellularSocket { public: diff --git a/connectivity/lwipstack/include/lwipstack/LWIPStack.h b/connectivity/lwipstack/include/lwipstack/LWIPStack.h index 994a4a0af3bb..e8b3d9c498a7 100644 --- a/connectivity/lwipstack/include/lwipstack/LWIPStack.h +++ b/connectivity/lwipstack/include/lwipstack/LWIPStack.h @@ -449,6 +449,27 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { */ nsapi_size_or_error_t socket_send(nsapi_socket_t handle, const void *data, nsapi_size_t size) override; + + /** Send a packet with ancillary data over a UDP socket + * + * Sends data to the specified address. Returns the number of bytes + * sent from the buffer. + * + * This call is non-blocking. If sendto would block, + * NSAPI_ERROR_WOULD_BLOCK is returned immediately. + * + * @param handle Socket handle + * @param address The SocketAddress of the remote host + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @param control Ancillary data storage + * @param control_size Size of the Ancillary data in bytes + * @return Number of sent bytes on success, negative error + * code on failure + */ + nsapi_size_or_error_t socket_sendmsg(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t* control, nsapi_size_t control_size) override; /** Receive data over a TCP socket * @@ -493,6 +514,7 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { * This call is non-blocking. If recvfrom would block, * NSAPI_ERROR_WOULD_BLOCK is returned immediately. * + * It uses socket_recvmsg with zero ancillary data. * @param handle Socket handle * @param address Destination for the source address or NULL * @param buffer Destination buffer for data received from the host @@ -503,6 +525,27 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, nsapi_size_t size) override; + /** Receive a packet with ancillary data over a UDP socket + * + * Receives data and stores the source address in address if address + * is not NULL. Returns the number of bytes received into the buffer. + * + * This call is non-blocking. If recvfrom would block, + * NSAPI_ERROR_WOULD_BLOCK is returned immediately. + * + * @param handle Socket handle + * @param address Destination for the source address or NULL + * @param buffer Destination buffer for data received from the host + * @param size Size of the buffer in bytes + * @param control Ancillary data storage + * @param control_size Size of the Ancillary data in bytes + * @return Number of received bytes on success, negative error + * code on failure + */ + nsapi_size_or_error_t socket_recvmsg(nsapi_socket_t handle, SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t* control, nsapi_size_t control_size) override; + /** Register a callback on state change of the socket * * The specified callback will be called on state changes such as when diff --git a/connectivity/lwipstack/include/lwipstack/lwipopts.h b/connectivity/lwipstack/include/lwipstack/lwipopts.h index 0a0c2cf7a445..549cebfe6118 100644 --- a/connectivity/lwipstack/include/lwipstack/lwipopts.h +++ b/connectivity/lwipstack/include/lwipstack/lwipopts.h @@ -311,6 +311,9 @@ #endif +// FIXME: Add compile time configuration and define conditionaly +#define LWIP_NETBUF_RECVINFO 1 + // Make sure we default these to off, so // LWIP doesn't default to on #ifndef LWIP_ARP diff --git a/connectivity/lwipstack/source/LWIPStack.cpp b/connectivity/lwipstack/source/LWIPStack.cpp index db4adafb891c..627386105f01 100644 --- a/connectivity/lwipstack/source/LWIPStack.cpp +++ b/connectivity/lwipstack/source/LWIPStack.cpp @@ -15,10 +15,10 @@ * limitations under the License. */ #include "nsapi.h" +#include "netsocket/MsgHeader.h" #include "mbed_interface.h" #include "mbed_assert.h" #include "Semaphore.h" -#include #include #include @@ -37,6 +37,7 @@ #include "lwip/raw.h" #include "lwip/netif.h" #include "lwip/lwip_errno.h" +#include "lwip/ip_addr.h" #include "lwip-sys/arch/sys_arch.h" #include "LWIPStack.h" @@ -439,24 +440,109 @@ nsapi_size_or_error_t LWIP::socket_recv(nsapi_socket_t handle, void *data, nsapi } nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size) +{ + return socket_sendmsg(handle, address, data, size, NULL, 0); +} + +nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size) +{ + return socket_recvmsg(handle, address, data, size, NULL, 0); + +} + +nsapi_size_or_error_t LWIP::socket_recvmsg(nsapi_socket_t handle, SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) { struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; - ip_addr_t ip_addr; + struct netbuf *buf; + + err_t err = netconn_recv(s->conn, &buf); + if (err != ERR_OK) { + return err_remap(err); + } + + if (address) { + nsapi_addr_t addr; + convert_lwip_addr_to_mbed(&addr, netbuf_fromaddr(buf)); + address->set_addr(addr); + address->set_port(netbuf_fromport(buf)); + } + + if ((s->conn->flags & NETCONN_FLAG_PKTINFO) && control && control_size >= sizeof(nsapi_pktinfo_t)) { + nsapi_pktinfo_t *pkt_info = reinterpret_cast(control); + // Not optimal but sufficient. It should help the caller in not iterating over + // the control data structure + control->len = control_size; + control->level = NSAPI_SOCKET; + control->type = NSAPI_PKTINFO; + // retrieve the destination + convert_lwip_addr_to_mbed(&pkt_info->ipi_addr, netbuf_destaddr(buf)); + // retrieve the interface id + pkt_info->ipi_ifindex = buf->p->if_idx; + } + + u16_t recv = netbuf_copy(buf, data, (u16_t)size); + netbuf_delete(buf); + + return recv; +} + +nsapi_size_or_error_t LWIP::socket_sendmsg(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) +{ + struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; + ip_addr_t ip_addr = {}; + + // Used for backup the bound address if the packet must be sent from a specific address, + ip_addr_t bound_addr = {}; + ip_addr_t src_addr = {}; + + nsapi_pktinfo_t *pkt_info = nullptr; nsapi_addr_t addr = address.get_addr(); if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { return NSAPI_ERROR_PARAMETER; } - struct netif *netif_ = netif_get_by_index(s->conn->pcb.ip->netif_idx); + + // We try to extract the pktinfo from the header + + if (control) { + MsgHeaderIterator it(control, control_size); + while (it.has_next()) { + auto *hdr = it.next(); + if (hdr->level == NSAPI_SOCKET && hdr->type == NSAPI_PKTINFO) { + pkt_info = reinterpret_cast(hdr); + break; + } + } + } + + if (pkt_info) { + if (!convert_mbed_addr_to_lwip(&src_addr, &pkt_info->ipi_addr)) { + return NSAPI_ERROR_PARAMETER; + } + } + + struct netif *netif_ = nullptr; + + if (pkt_info) { + netif_ = netif_get_by_index(pkt_info->ipi_ifindex); + } else { + netif_ = netif_get_by_index(s->conn->pcb.ip->netif_idx); + } if (!netif_) { netif_ = &default_interface->netif; } + if (netif_) { if ((addr.version == NSAPI_IPv4 && !get_ipv4_addr(netif_)) || (addr.version == NSAPI_IPv6 && !get_ipv6_addr(netif_) && !get_ipv6_link_local_addr(netif_))) { return NSAPI_ERROR_PARAMETER; } } + struct netbuf *buf = netbuf_new(); err_t err = netbuf_ref(buf, data, (u16_t)size); @@ -465,36 +551,29 @@ nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAdd return err_remap(err); } - err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port()); - netbuf_delete(buf); - if (err != ERR_OK) { - return err_remap(err); + // handle src destination if required + if (pkt_info) { + // Backup the bound address + ip_addr_copy(bound_addr, s->conn->pcb.udp->local_ip); + // replace it with the source address + if (!ip_addr_isany(&src_addr)) { + ip_addr_copy(s->conn->pcb.udp->local_ip, src_addr); + } } - return size; -} + err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port()); -nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size) -{ - struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle; - struct netbuf *buf; + if (pkt_info) { + // restore bound address + ip_addr_copy(s->conn->pcb.udp->local_ip, bound_addr); + } - err_t err = netconn_recv(s->conn, &buf); + netbuf_delete(buf); if (err != ERR_OK) { return err_remap(err); } - if (address) { - nsapi_addr_t addr; - convert_lwip_addr_to_mbed(&addr, netbuf_fromaddr(buf)); - address->set_addr(addr); - address->set_port(netbuf_fromport(buf)); - } - - u16_t recv = netbuf_copy(buf, data, (u16_t)size); - netbuf_delete(buf); - - return recv; + return size; } int32_t LWIP::find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr) @@ -687,6 +766,19 @@ nsapi_error_t LWIP::setsockopt(nsapi_socket_t handle, int level, int optname, co } s->conn->pcb.ip->tos = (u8_t)(*(const int *)optval); return 0; + + case NSAPI_PKTINFO: + // FIXME: Turn NETCONN_FLAG_PKTINFO off by default + if (optlen != sizeof(int)) { + return NSAPI_ERROR_UNSUPPORTED; + } + if (*(const int *)optval) { + s->conn->flags |= NETCONN_FLAG_PKTINFO; + } else { + s->conn->flags &= ~NETCONN_FLAG_PKTINFO; + } + return 0; + default: return NSAPI_ERROR_UNSUPPORTED; } diff --git a/connectivity/nanostack/include/nanostack-interface/Nanostack.h b/connectivity/nanostack/include/nanostack-interface/Nanostack.h index 53894a1f10b8..305736efec86 100644 --- a/connectivity/nanostack/include/nanostack-interface/Nanostack.h +++ b/connectivity/nanostack/include/nanostack-interface/Nanostack.h @@ -302,6 +302,21 @@ class Nanostack : public OnboardNetworkStack, private mbed::NonCopyablelen < sizeof(*current)) { + return false; + } + + if ((reinterpret_cast(current) + current->len) >= (reinterpret_cast(start) + size)) { + return false; + } + + return true; + } + + nsapi_msghdr_t *next() + { + if (!has_next()) { + return nullptr; + } + + if (current == nullptr) { + current = start; + } else { + current = reinterpret_cast(reinterpret_cast(current) + current->len); + } + + return current; + } + +private: + nsapi_msghdr_t *start; + nsapi_msghdr_t *current; + nsapi_size_t size; +}; + + +#endif + +/** @}*/ diff --git a/connectivity/netsocket/include/netsocket/NetworkStack.h b/connectivity/netsocket/include/netsocket/NetworkStack.h index 2f6bb78cbc45..8118372095d1 100644 --- a/connectivity/netsocket/include/netsocket/NetworkStack.h +++ b/connectivity/netsocket/include/netsocket/NetworkStack.h @@ -395,6 +395,51 @@ class NetworkStack : public DNS { virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, nsapi_size_t size) = 0; + /** Send a packet with ancillary data over a UDP socket + * + * Sends data to the specified address. Returns the number of bytes + * sent from the buffer. + * + * This call is non-blocking. If sendto would block, + * NSAPI_ERROR_WOULD_BLOCK is returned immediately. + * + * @param handle Socket handle + * @param address The SocketAddress of the remote host + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @param control Storage for ancillary data + * @param control_size Size of ancillary data + * @return Number of sent bytes on success, negative error + * code on failure + */ + virtual nsapi_size_or_error_t socket_sendmsg(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) = 0; + + /** Receive a packet with ancillary data over a UDP socket + * + * Receives data and stores the source address in address if address + * is not NULL. Returns the number of bytes received into the buffer. + * + * Additional information related to the message can be retrieved with + * the control data. + * + * This call is non-blocking. If recvfrom would block, + * NSAPI_ERROR_WOULD_BLOCK is returned immediately. + * + * @param handle Socket handle + * @param address Destination for the source address or NULL + * @param buffer Destination buffer for data received from the host + * @param size Size of the buffer in bytes + * @param control Storage for ancillary data + * @param control_size Size of ancillary data + * @return Number of received bytes on success, negative error + * code on failure + */ + virtual nsapi_size_or_error_t socket_recvmsg(nsapi_socket_t handle, SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) = 0; + /** Register a callback on state change of the socket * * The specified callback will be called on state changes such as when diff --git a/connectivity/netsocket/include/netsocket/Socket.h b/connectivity/netsocket/include/netsocket/Socket.h index de493c7bd6e2..fc46976fc867 100644 --- a/connectivity/netsocket/include/netsocket/Socket.h +++ b/connectivity/netsocket/include/netsocket/Socket.h @@ -157,6 +157,55 @@ class Socket { virtual nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size) = 0; + /** Send a message on a socket. + * + * The sendmsg() function sends a message through a connection-mode or connectionless-mode socket. + * If the socket is a connectionless-mode socket, the message is sent to the address specified. + * If the socket is a connected-mode socket, address is ignored. + * + * Additional control information can be passed to the stack to realise specific operations. + * + * By default, sendto blocks until data is sent. If socket is set to + * non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned + * immediately. + * + * @param address Remote address + * @param data Buffer of data to send to the host + * @param size Size of the buffer in bytes + * @return Number of sent bytes on success, negative subclass-dependent error + * code on failure + */ + virtual nsapi_size_or_error_t sendmsg(const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) = 0; + + + /** Receive a data from a socket + * + * Receives a data and stores the source address in address if address + * is not NULL. Returns the number of bytes written into the buffer. + * + * If socket is connected, only packets coming from connected peer address + * are accepted. + * + * Additional information related to the message can be retrieved with the control data. + * + * @note recvfrom() is allowed write to address and data buffers even if error occurs. + * + * By default, recvfrom blocks until a datagram is received. If socket is set to + * non-blocking or times out with no data, NSAPI_ERROR_WOULD_BLOCK + * is returned. + * + * @param address Destination for the source address or NULL + * @param data Destination buffer for datagram received from the host + * @param size Size of the buffer in bytes + * @return Number of received bytes on success, negative subclass-dependent + * error code on failure + */ + virtual nsapi_size_or_error_t recvmsg(SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) = 0; + /** Bind a specific address to a socket. * * Binding a socket specifies the address and port on which to receive diff --git a/connectivity/netsocket/include/netsocket/TCPSocket.h b/connectivity/netsocket/include/netsocket/TCPSocket.h index 37897f231a05..90fded7c3610 100644 --- a/connectivity/netsocket/include/netsocket/TCPSocket.h +++ b/connectivity/netsocket/include/netsocket/TCPSocket.h @@ -145,6 +145,14 @@ class TCPSocket : public InternetSocket { nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size) override; + virtual nsapi_size_or_error_t sendmsg(const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override; + + virtual nsapi_size_or_error_t recvmsg(SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) override; + /** Accepts a connection on a socket. * * The server socket must be bound and set to listen for connections. diff --git a/connectivity/netsocket/include/netsocket/nsapi_types.h b/connectivity/netsocket/include/netsocket/nsapi_types.h index eef8f34cc57c..a7a88b747d2c 100644 --- a/connectivity/netsocket/include/netsocket/nsapi_types.h +++ b/connectivity/netsocket/include/netsocket/nsapi_types.h @@ -318,7 +318,8 @@ typedef enum nsapi_socket_option { NSAPI_LATENCY, /*!< Read estimated latency to destination */ NSAPI_STAGGER, /*!< Read estimated stagger value to destination */ NSAPI_IPTOS, /*!< Set IP type of service to set specific precedence */ - NSAPI_BROADCAST /*!< Set broadcast flag for UDP socket */ + NSAPI_BROADCAST, /*!< Set broadcast flag for UDP socket */ + NSAPI_PKTINFO /*!< Get additional information when using sendmsg/recvmsg */ } nsapi_socket_option_t; typedef enum nsapi_tlssocket_level { @@ -406,6 +407,22 @@ typedef struct nsapi_stagger_req { uint16_t stagger_rand; /* [OUT] Randomized stagger value in seconds */ } nsapi_stagger_req_t; +/** nsapi_msghdr + */ +typedef struct nsapi_msghdr { + nsapi_size_t len; /* Data byte count, including header */ + int level; /* Originating protocol */ + int type; /* Protocol-specific type */ +} nsapi_msghdr_t; + +/** nsapi_pktinfo structure + */ +typedef struct nsapi_pktinfo { + nsapi_msghdr_t hdr; /* Header identifying the message control structure */ + nsapi_addr_t ipi_addr; /* Address associated with the packet */ + int ipi_ifindex; /* Interface associated with the packet */ +} nsapi_pktinfo_t; + /** nsapi_stack_api structure * * Common api structure for network stack operations. A network stack @@ -644,6 +661,17 @@ typedef struct nsapi_stack_api { nsapi_size_or_error_t (*socket_recvfrom)(nsapi_stack_t *stack, nsapi_socket_t socket, nsapi_addr_t *addr, uint16_t *port, void *buffer, nsapi_size_t size); + // TODO: Documentation + nsapi_size_or_error_t (*socket_sendmsg)(nsapi_stack_t *stack, nsapi_socket_t socket, + nsapi_addr_t addr, uint16_t port, + const void *data, nsapi_size_t size, + const nsapi_msghdr_t *control, nsapi_size_t control_size); + + nsapi_size_or_error_t (*socket_recvmsg)(nsapi_stack_t *stack, nsapi_socket_t socket, + nsapi_addr_t *addr, uint16_t *port, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size); + /** Register a callback on state change of the socket * * The specified callback will be called on state changes such as when diff --git a/connectivity/netsocket/source/InternetDatagramSocket.cpp b/connectivity/netsocket/source/InternetDatagramSocket.cpp index 4c0010de0330..1d212efc2b32 100644 --- a/connectivity/netsocket/source/InternetDatagramSocket.cpp +++ b/connectivity/netsocket/source/InternetDatagramSocket.cpp @@ -27,7 +27,7 @@ nsapi_error_t InternetDatagramSocket::connect(const SocketAddress &address) return NSAPI_ERROR_OK; } -nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &address, const void *data, nsapi_size_t size) +nsapi_size_or_error_t InternetDatagramSocket::sendmsg(const SocketAddress &address, const void *data, nsapi_size_t size, nsapi_msghdr_t *control, nsapi_size_t control_size) { _lock.lock(); nsapi_size_or_error_t ret; @@ -44,7 +44,7 @@ nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &addres } core_util_atomic_flag_clear(&_pending); - nsapi_size_or_error_t sent = _stack->socket_sendto(_socket, address, data, size); + nsapi_size_or_error_t sent = _stack->socket_sendmsg(_socket, address, data, size, control, control_size); if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) { _socket_stats.stats_update_sent_bytes(this, sent); ret = sent; @@ -74,6 +74,12 @@ nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &addres return ret; } +nsapi_size_or_error_t InternetDatagramSocket::sendto(const SocketAddress &address, const void *data, nsapi_size_t size) +{ + + return sendmsg(address, data, size, NULL, 0); +} + nsapi_size_or_error_t InternetDatagramSocket::send(const void *data, nsapi_size_t size) { if (!_remote_peer) { @@ -82,7 +88,8 @@ nsapi_size_or_error_t InternetDatagramSocket::send(const void *data, nsapi_size_ return sendto(_remote_peer, data, size); } -nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size) + +nsapi_size_or_error_t InternetDatagramSocket::recvmsg(SocketAddress *address, void *buffer, nsapi_size_t size, nsapi_msghdr_t *control, nsapi_size_t control_size) { _lock.lock(); nsapi_size_or_error_t ret; @@ -104,7 +111,7 @@ nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, v } core_util_atomic_flag_clear(&_pending); - nsapi_size_or_error_t recv = _stack->socket_recvfrom(_socket, address, buffer, size); + nsapi_size_or_error_t recv = _stack->socket_recvmsg(_socket, address, buffer, size, control, control_size); // Filter incomming packets using connected peer address if (recv >= 0 && _remote_peer && _remote_peer != *address) { @@ -143,6 +150,11 @@ nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, v return ret; } +nsapi_size_or_error_t InternetDatagramSocket::recvfrom(SocketAddress *address, void *buffer, nsapi_size_t size) +{ + return recvmsg(address, buffer, size, NULL, 0); +} + nsapi_size_or_error_t InternetDatagramSocket::recv(void *buffer, nsapi_size_t size) { return recvfrom(NULL, buffer, size); diff --git a/connectivity/netsocket/source/NetworkStack.cpp b/connectivity/netsocket/source/NetworkStack.cpp index 99b17cff13a9..454f7175ba9d 100644 --- a/connectivity/netsocket/source/NetworkStack.cpp +++ b/connectivity/netsocket/source/NetworkStack.cpp @@ -399,6 +399,36 @@ class NetworkStackWrapper : public NetworkStack { return err; } + nsapi_size_or_error_t socket_sendmsg(nsapi_socket_t socket, const SocketAddress &address, const void *data, nsapi_size_t size, nsapi_msghdr_t *control, nsapi_size_t control_size) override + { + if (!_stack_api()->socket_sendmsg) { + return NSAPI_ERROR_UNSUPPORTED; + } + + return _stack_api()->socket_sendmsg(_stack(), socket, address.get_addr(), address.get_port(), data, size, control, control_size); + } + + nsapi_size_or_error_t socket_recvmsg(nsapi_socket_t socket, SocketAddress *address, void *data, nsapi_size_t size, nsapi_msghdr_t *control, nsapi_size_t control_size) override + { + if (!_stack_api()->socket_recvmsg) { + return NSAPI_ERROR_UNSUPPORTED; + } + + nsapi_addr_t addr = {NSAPI_IPv4, 0}; + uint16_t port = 0; + + nsapi_size_or_error_t err = _stack_api()->socket_recvmsg(_stack(), socket, &addr, &port, data, size, control, control_size); + + if (address) { + address->set_addr(addr); + address->set_port(port); + } + + return err; + } + + + void socket_attach(nsapi_socket_t socket, void (*callback)(void *), void *data) override { if (!_stack_api()->socket_attach) { diff --git a/connectivity/netsocket/source/TCPSocket.cpp b/connectivity/netsocket/source/TCPSocket.cpp index a85c8eb26cdf..f749aff97f8a 100644 --- a/connectivity/netsocket/source/TCPSocket.cpp +++ b/connectivity/netsocket/source/TCPSocket.cpp @@ -173,6 +173,17 @@ nsapi_size_or_error_t TCPSocket::sendto(const SocketAddress &address, const void return send(data, size); } +nsapi_size_or_error_t TCPSocket::sendmsg(const SocketAddress &address, + const void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) +{ + // FIXME: Implement + if (control) { + return NSAPI_ERROR_UNSUPPORTED; + } + return sendto(address, data, size); +} + nsapi_size_or_error_t TCPSocket::recv(void *data, nsapi_size_t size) { _lock.lock(); @@ -229,6 +240,17 @@ nsapi_size_or_error_t TCPSocket::recvfrom(SocketAddress *address, void *data, ns return recv(data, size); } +nsapi_size_or_error_t TCPSocket::recvmsg(SocketAddress *address, + void *data, nsapi_size_t size, + nsapi_msghdr_t *control, nsapi_size_t control_size) +{ + // FIXME: Implement + if (control) { + return NSAPI_ERROR_UNSUPPORTED; + } + return recvfrom(address, data, size); +} + nsapi_error_t TCPSocket::listen(int backlog) { _lock.lock();