mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #15040 from mat-kalinowski/sendrecv_message
New feature: send/recv message implementation added to network stackpull/15061/head
commit
f89655f2da
|
@ -88,6 +88,21 @@ protected: // NetworkStack
|
|||
|
||||
virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data);
|
||||
|
||||
|
||||
nsapi_size_or_error_t socket_sendto_control(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_recvfrom_control(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:
|
||||
|
|
|
@ -163,6 +163,9 @@ public:
|
|||
static void netif_status_irq(struct netif *netif);
|
||||
static Interface *our_if_from_netif(struct netif *netif);
|
||||
static void delete_interface(OnboardNetworkStack::Interface **interface_out);
|
||||
NetworkInterface *network_if_from_netif_id(int id);
|
||||
int netif_id_from_network_if(NetworkInterface *userInterface);
|
||||
|
||||
|
||||
#if LWIP_ETHERNET
|
||||
static err_t emac_low_level_output(struct netif *netif, struct pbuf *p);
|
||||
|
@ -222,6 +225,8 @@ public:
|
|||
void *hw; /**< alternative implementation pointer - used for PPP */
|
||||
};
|
||||
|
||||
NetworkInterface *user_network_interface;
|
||||
|
||||
mbed_rtos_storage_semaphore_t remove_interface_sem;
|
||||
osSemaphoreId_t remove_interface;
|
||||
mbed_rtos_storage_semaphore_t linked_sem;
|
||||
|
@ -265,7 +270,7 @@ public:
|
|||
* @param[out] interface_out pointer to stack interface object controlling the EMAC
|
||||
* @return NSAPI_ERROR_OK on success, or error code
|
||||
*/
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out) override;
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface = NULL) override;
|
||||
|
||||
/** Register a network interface with the IP stack
|
||||
*
|
||||
|
@ -450,6 +455,27 @@ protected:
|
|||
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_sendto_control(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
|
||||
*
|
||||
* The socket must be connected to a remote host. Returns the number of
|
||||
|
@ -493,6 +519,7 @@ protected:
|
|||
* This call is non-blocking. If recvfrom would block,
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned immediately.
|
||||
*
|
||||
* It uses socket_recvfrom_control 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 +530,27 @@ protected:
|
|||
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_recvfrom_control(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
|
||||
|
|
|
@ -311,6 +311,8 @@
|
|||
|
||||
#endif
|
||||
|
||||
#define LWIP_NETBUF_RECVINFO MBED_CONF_LWIP_NETBUF_RECVINFO_ENABLED
|
||||
|
||||
// Make sure we default these to off, so
|
||||
// LWIP doesn't default to on
|
||||
#ifndef LWIP_ARP
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#define LWIP_NETCONN !NO_SYS
|
||||
#define LWIP_SOCKET !NO_SYS
|
||||
#define LWIP_NETCONN_FULLDUPLEX LWIP_SOCKET
|
||||
#define LWIP_NETBUF_RECVINFO 1
|
||||
#define LWIP_NETBUF_RECVINFO MBED_CONF_NETBUF_RECVINFO_ENABLED
|
||||
#define LWIP_HAVE_LOOPIF 1
|
||||
#define TCPIP_THREAD_TEST
|
||||
|
||||
|
|
|
@ -42,6 +42,28 @@
|
|||
|
||||
LWIP::Interface *LWIP::Interface::list;
|
||||
|
||||
NetworkInterface *LWIP::Interface::network_if_from_netif_id(int id)
|
||||
{
|
||||
for (Interface *interface = list; interface; interface = interface->next) {
|
||||
if (id == netif_get_index(&interface->netif)) {
|
||||
return interface->user_network_interface;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int LWIP::Interface::netif_id_from_network_if(NetworkInterface *userInterface)
|
||||
{
|
||||
if (userInterface != NULL) {
|
||||
for (Interface *interface = list; interface; interface = interface->next) {
|
||||
if (userInterface == interface->user_network_interface) {
|
||||
return netif_get_index(&interface->netif);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWIP::Interface *LWIP::Interface::our_if_from_netif(struct netif *netif)
|
||||
{
|
||||
for (Interface *interface = list; interface; interface = interface->next) {
|
||||
|
@ -408,7 +430,7 @@ LWIP::Interface::Interface() :
|
|||
list = this;
|
||||
}
|
||||
|
||||
nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)
|
||||
nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface)
|
||||
{
|
||||
#if LWIP_ETHERNET
|
||||
Interface *interface = new (std::nothrow) Interface();
|
||||
|
@ -431,7 +453,7 @@ nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardN
|
|||
#endif
|
||||
|
||||
interface->netif.hwaddr_len = 6;
|
||||
|
||||
interface->user_network_interface = user_network_interface;
|
||||
if (!netif_add(&interface->netif,
|
||||
#if LWIP_IPV4
|
||||
0, 0, 0,
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -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"
|
||||
|
@ -271,7 +272,9 @@ nsapi_error_t LWIP::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
|
|||
arena_dealloc(s);
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
s->conn->flags &= ~NETCONN_FLAG_PKTINFO;
|
||||
#endif
|
||||
netconn_set_nonblocking(s->conn, true);
|
||||
*(struct mbed_lwip_socket **)handle = s;
|
||||
return 0;
|
||||
|
@ -440,41 +443,18 @@ 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)
|
||||
{
|
||||
struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
|
||||
ip_addr_t ip_addr;
|
||||
|
||||
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);
|
||||
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);
|
||||
if (err != ERR_OK) {
|
||||
netbuf_free(buf);
|
||||
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);
|
||||
}
|
||||
|
||||
return size;
|
||||
return socket_sendto_control(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_recvfrom_control(handle, address, data, size, NULL, 0);
|
||||
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t LWIP::socket_recvfrom_control(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;
|
||||
struct netbuf *buf;
|
||||
|
@ -490,13 +470,116 @@ nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress
|
|||
address->set_addr(addr);
|
||||
address->set_port(netbuf_fromport(buf));
|
||||
}
|
||||
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
if ((s->conn->flags & NETCONN_FLAG_PKTINFO) && control && control_size >= sizeof(nsapi_pktinfo_t)) {
|
||||
nsapi_pktinfo_t *pkt_info = reinterpret_cast<nsapi_pktinfo *>(control);
|
||||
memset(control, 0, control_size);
|
||||
// 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->network_interface = default_interface->network_if_from_netif_id(buf->p->if_idx);
|
||||
}
|
||||
#endif
|
||||
u16_t recv = netbuf_copy(buf, data, (u16_t)size);
|
||||
netbuf_delete(buf);
|
||||
|
||||
return recv;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t LWIP::socket_sendto_control(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;
|
||||
}
|
||||
|
||||
// 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<nsapi_pktinfo_t *>(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) {
|
||||
int index = default_interface->netif_id_from_network_if((NetworkInterface *)pkt_info->network_interface);
|
||||
netif_ = netif_get_by_index(index);
|
||||
} 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);
|
||||
if (err != ERR_OK) {
|
||||
netbuf_free(buf);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port());
|
||||
|
||||
if (pkt_info) {
|
||||
// restore bound address
|
||||
ip_addr_copy(s->conn->pcb.udp->local_ip, bound_addr);
|
||||
}
|
||||
|
||||
netbuf_delete(buf);
|
||||
if (err != ERR_OK) {
|
||||
return err_remap(err);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t LWIP::find_multicast_member(const struct mbed_lwip_socket *s, const nsapi_ip_mreq_t *imr)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
@ -687,6 +770,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:
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
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;
|
||||
#endif
|
||||
default:
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
|
|
@ -40,11 +40,11 @@ public:
|
|||
class PPPInterface;
|
||||
|
||||
/* Implement OnboardNetworkStack method */
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out) override;
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, const uint8_t *mac_addr) override;
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface = NULL) override;
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, const uint8_t *mac_addr, NetworkInterface *user_network_interface = NULL) override;
|
||||
|
||||
/* Local variant with stronger typing and manual address specification */
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr = NULL);
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr = NULL, NetworkInterface *user_network_interface = NULL);
|
||||
|
||||
nsapi_error_t add_ppp_interface(PPP &ppp, bool default_if, OnboardNetworkStack::Interface **interface_out) override;
|
||||
|
||||
|
@ -302,6 +302,20 @@ protected:
|
|||
*/
|
||||
nsapi_error_t getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen) override;
|
||||
|
||||
nsapi_size_or_error_t socket_sendto_control(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_recvfrom_control(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;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** Call in callback
|
||||
|
|
|
@ -191,7 +191,7 @@ void EMACPhy::set_mac_address(uint8_t *mac)
|
|||
memcpy(mac_addr, mac, sizeof mac_addr);
|
||||
}
|
||||
|
||||
nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr)
|
||||
nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr, NetworkInterface *user_network_interface)
|
||||
{
|
||||
if (single_phy) {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
|
@ -224,7 +224,7 @@ nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, Nan
|
|||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, const uint8_t *mac_addr)
|
||||
nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, const uint8_t *mac_addr, NetworkInterface *user_network_interface)
|
||||
{
|
||||
Nanostack::EthernetInterface *interface;
|
||||
nsapi_error_t err = add_ethernet_interface(emac, default_if, &interface, mac_addr);
|
||||
|
@ -232,7 +232,7 @@ nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, Onb
|
|||
return err;
|
||||
}
|
||||
|
||||
nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)
|
||||
nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface)
|
||||
{
|
||||
Nanostack::EthernetInterface *interface;
|
||||
nsapi_error_t err = add_ethernet_interface(emac, default_if, &interface);
|
||||
|
|
|
@ -133,6 +133,14 @@ public:
|
|||
nsapi_size_or_error_t recvfrom(SocketAddress *address,
|
||||
void *data, nsapi_size_t size) override;
|
||||
/// NOT APPLICABLE
|
||||
nsapi_size_or_error_t sendto_control(const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
|
||||
/// NOT APPLICABLE
|
||||
nsapi_size_or_error_t recvfrom_control(SocketAddress *address,
|
||||
void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
|
||||
/// NOT APPLICABLE
|
||||
nsapi_error_t bind(const SocketAddress &address) override;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
* nonblocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
|
||||
* immediately.
|
||||
*
|
||||
* It uses sendto_control with zero ancillary data
|
||||
* @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.
|
||||
|
@ -60,7 +61,7 @@ public:
|
|||
* are accepted.
|
||||
*
|
||||
* @note recvfrom() is allowed write to address and data buffers even if error occurs.
|
||||
*
|
||||
* It uses recvfrom_control with zero ancillary data
|
||||
* @param address Destination for the source address or NULL.
|
||||
* @param data Destination buffer for RAW data to be received from the host.
|
||||
* @param size Size of the buffer in bytes.
|
||||
|
@ -74,6 +75,58 @@ public:
|
|||
nsapi_size_or_error_t recvfrom(SocketAddress *address,
|
||||
void *data, nsapi_size_t size) override;
|
||||
|
||||
/** Send datagram and ancillary data to the specified address.
|
||||
*
|
||||
* By default, sendto blocks until data is sent. If socket is set to
|
||||
* nonblocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
|
||||
* immediately.
|
||||
*
|
||||
* It uses sendto_control with zero ancillary data
|
||||
* @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 Size of the buffer in bytes.
|
||||
* @param control_size Size of the buffer in bytes.
|
||||
* @retval NSAPI_ERROR_NO_SOCKET in case socket was not created correctly.
|
||||
* @retval NSAPI_ERROR_WOULD_BLOCK in case non-blocking mode is enabled
|
||||
* and send cannot be performed immediately.
|
||||
* @retval int Other negative error codes for stack-related failures.
|
||||
* See \ref NetworkStack::socket_send.
|
||||
*/
|
||||
nsapi_size_or_error_t sendto_control(const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
|
||||
|
||||
|
||||
/** Receive a datagram with ancillary data and store the source address in address if it's not NULL.
|
||||
*
|
||||
* By default, recvfrom blocks until a datagram is received. If socket is set to
|
||||
* nonblocking or times out with no datagram, NSAPI_ERROR_WOULD_BLOCK
|
||||
* is returned.
|
||||
* Ancillary data is stored in msghdr struct
|
||||
* @note If the datagram is larger than the buffer, the excess data is silently discarded.
|
||||
*
|
||||
* @note If socket is connected, only packets coming from connected peer address
|
||||
* are accepted.
|
||||
*
|
||||
* @note recvfrom_control() is allowed write to address and data buffers even if error occurs.
|
||||
*
|
||||
* @param address Destination for the source address or NULL.
|
||||
* @param data Destination buffer for RAW data to be received from the host.
|
||||
* @param size Size of the buffer in bytes.
|
||||
* @param control Size of the buffer in bytes.
|
||||
* @param control_size Size of the buffer in bytes.
|
||||
* @retval int Number of received bytes on success.
|
||||
* @retval NSAPI_ERROR_NO_SOCKET in case socket was not created correctly.
|
||||
* @retval NSAPI_ERROR_WOULD_BLOCK in case non-blocking mode is enabled
|
||||
* and send cannot be performed immediately.
|
||||
* @retval int Other negative error codes for stack-related failures.
|
||||
* See \ref NetworkStack::socket_recv.
|
||||
*/
|
||||
nsapi_size_or_error_t recvfrom_control(SocketAddress *address,
|
||||
void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
|
||||
|
||||
/** Set the remote address for next send() call and filtering
|
||||
* of incoming packets. To reset the address, zero initialized
|
||||
* SocketAddress must be in the address parameter.
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright (c) 2021 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MSG_HEADER_H
|
||||
#define MSG_HEADER_H
|
||||
|
||||
#include "netsocket/nsapi_types.h"
|
||||
|
||||
/**
|
||||
* Allows iteration through the list of message headers received in the control parameter of the
|
||||
* socket_sendto_control / socket_recvfrom_control methods.
|
||||
*
|
||||
* @par Members types
|
||||
*
|
||||
* MsgHeaderIterator works on the list which members are of type nsapi_msghdr_t or other types
|
||||
* extending this struct. For example nsapi_pktinfo:
|
||||
*
|
||||
* @code
|
||||
typedef struct nsapi_pktinfo {
|
||||
nsapi_msghdr_t hdr;
|
||||
nsapi_addr_t ipi_addr;
|
||||
int ipi_ifindex;
|
||||
void *network_interface;
|
||||
} nsapi_pktinfo_t;
|
||||
* @endcode
|
||||
*
|
||||
* There are two requirements for such structures to work well with MsgHeaderIterator.
|
||||
* - First element needs to be of type nsapi_msghdr_t.
|
||||
* - Value of the field len of the nsapi_msghdr_t needs to bet set to the size of the whole extending type.
|
||||
* For example:
|
||||
*
|
||||
* @code
|
||||
nsapi_pktinfo_t pkt_info;
|
||||
pkt_info.hdr.len = sizeof(nsapi_pktinfo_t);
|
||||
* @endcode
|
||||
*
|
||||
* This value is used in the MsgHeaderIterator to calculate proper addresses of the list elements.
|
||||
*
|
||||
* @par Example
|
||||
*
|
||||
* Code presenting minimal usage example.
|
||||
*
|
||||
* @code
|
||||
struct default_buffer_t {
|
||||
default_buffer_t()
|
||||
{
|
||||
el1.hdr.len = sizeof(nsapi_pktinfo_t);
|
||||
el2.len = sizeof(nsapi_msghdr_t);
|
||||
el3.len = sizeof(nsapi_msghdr_t);
|
||||
el4.hdr.len = sizeof(nsapi_pktinfo_t);
|
||||
}
|
||||
nsapi_pktinfo_t el1;
|
||||
nsapi_msghdr_t el2;
|
||||
nsapi_msghdr_t el3;
|
||||
nsapi_pktinfo_t el4;
|
||||
};
|
||||
|
||||
default_buffer buff;
|
||||
nsapi_msghdr_t *hdr_p = reinterpret_cast<nsapi_msghdr_t *>(&buff);
|
||||
|
||||
MsgHeaderIterator it(hdr_p, sizeof(buff));
|
||||
|
||||
it.has_next() // returns true
|
||||
auto p1 = it.next() // returns pointer to el1
|
||||
auto p2 = it.next() // returns pointer to el2
|
||||
auto p3 = it.next() // returns pointer to el3
|
||||
auto p4 = it.next() // returns pointer to el4
|
||||
|
||||
it.has_next() // returns false
|
||||
auto p5 = it.next() // returns nullptr
|
||||
* @endcode
|
||||
*
|
||||
* @note More usage examples are implemented in the MsgHeaderIterator unit test
|
||||
* in netsocket/tests/UNITTESTS/NetworkStack/test_MsgHeaderIterator.cpp
|
||||
*/
|
||||
|
||||
struct MsgHeaderIterator {
|
||||
/** Create a MsgHeaderIterator over given nsapi_msghdr_t list.
|
||||
*
|
||||
* @param hdr Pointer to the first list element.
|
||||
* @param size Size of the whole list.
|
||||
*/
|
||||
MsgHeaderIterator(nsapi_msghdr_t *hdr, nsapi_size_t size) :
|
||||
start(hdr),
|
||||
current(nullptr),
|
||||
size(size)
|
||||
{}
|
||||
|
||||
/** Checks if the next address of the iterator is a valid list member.
|
||||
*
|
||||
* @retval True if the next address is a valid member.
|
||||
* @retval False otherwise.
|
||||
*/
|
||||
bool has_next()
|
||||
{
|
||||
if (current == nullptr) {
|
||||
if (start != nullptr && start->len <= size && start->len >= sizeof(*start)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (current->len < sizeof(*current)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (get_next_aligned_addr() >= (reinterpret_cast<uint8_t *>(start) + size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Returns next element of the list.
|
||||
*
|
||||
* @retval nullptr if the list doesn't contain next element.
|
||||
* @retval Pointer to the next element otherwise.
|
||||
*/
|
||||
nsapi_msghdr_t *next()
|
||||
{
|
||||
if (!has_next()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (current == nullptr) {
|
||||
current = start;
|
||||
} else {
|
||||
current = reinterpret_cast<nsapi_msghdr *>(get_next_aligned_addr());
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
private:
|
||||
// Get address of the next member aligned to the size of msghdr_t.
|
||||
void *get_next_aligned_addr()
|
||||
{
|
||||
size_t remaining_size = size - (reinterpret_cast<uintptr_t>(current) - reinterpret_cast<uintptr_t>(start));
|
||||
void *next = reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(current) + current->len);
|
||||
|
||||
next = std::align(
|
||||
alignof(nsapi_msghdr_t),
|
||||
sizeof(nsapi_msghdr_t),
|
||||
next,
|
||||
remaining_size
|
||||
);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
nsapi_msghdr_t *start;
|
||||
nsapi_msghdr_t *current;
|
||||
nsapi_size_t size;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -395,6 +395,65 @@ protected:
|
|||
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_sendto_control(nsapi_socket_t handle, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
if (control != NULL) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return socket_sendto(handle, address, data, size);
|
||||
}
|
||||
|
||||
/** 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_recvfrom_control(nsapi_socket_t handle, SocketAddress *address,
|
||||
void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
if (control != NULL) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return socket_recvfrom(handle, address, data, size);
|
||||
}
|
||||
|
||||
/** Register a callback on state change of the socket
|
||||
*
|
||||
* The specified callback will be called on state changes such as when
|
||||
|
|
|
@ -160,9 +160,10 @@ public:
|
|||
* @param[out] interface_out pointer to stack interface object controlling the EMAC
|
||||
* @return NSAPI_ERROR_OK on success, or error code
|
||||
*/
|
||||
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out) = 0;
|
||||
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, NetworkInterface *user_network_interface = NULL) = 0;
|
||||
|
||||
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, const uint8_t *mac_addr, NetworkInterface *user_network_interface = NULL)
|
||||
|
||||
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, const uint8_t *mac_addr)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
|
|
@ -157,6 +157,55 @@ public:
|
|||
virtual nsapi_size_or_error_t recvfrom(SocketAddress *address,
|
||||
void *data, nsapi_size_t size) = 0;
|
||||
|
||||
/** Send a message on a socket.
|
||||
*
|
||||
* The sendto_control() 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 for 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 sendto_control(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_control() 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 recvfrom_control(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
|
||||
|
|
|
@ -145,6 +145,53 @@ public:
|
|||
nsapi_size_or_error_t recvfrom(SocketAddress *address,
|
||||
void *data, nsapi_size_t size) override;
|
||||
|
||||
/** Send data on a packet with ancillary datasocket.
|
||||
*
|
||||
* TCP socket is connection oriented protocol, so address is ignored.
|
||||
*
|
||||
* By default, sendto_control 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
|
||||
* @retval int Number of sent bytes on success
|
||||
* @retval NSAPI_ERROR_NO_SOCKET in case socket was not created correctly
|
||||
* @retval NSAPI_ERROR_WOULD_BLOCK in case non-blocking mode is enabled
|
||||
* and send cannot be performed immediately
|
||||
* @retval int Other negative error codes for stack-related failures.
|
||||
* See @ref NetworkStack::socket_send.
|
||||
*/
|
||||
nsapi_size_or_error_t sendto_control(const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
|
||||
|
||||
/** Receive a packet with ancillary 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.
|
||||
*
|
||||
* By default, recvfrom_control blocks until a data is received. If socket is set to
|
||||
* non-blocking or times out with no datagram, 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
|
||||
* @control Pointer to the control buffer
|
||||
* @control_size Size of the control buffer in bytes
|
||||
* @retval int Number of received bytes on success
|
||||
* @retval NSAPI_ERROR_NO_SOCKET in case socket was not created correctly
|
||||
* @retval NSAPI_ERROR_WOULD_BLOCK in case non-blocking mode is enabled
|
||||
* and send cannot be performed immediately
|
||||
* @retval int Other negative error codes for stack-related failures.
|
||||
* See @ref NetworkStack::socket_recv.
|
||||
*/
|
||||
nsapi_size_or_error_t recvfrom_control(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.
|
||||
|
|
|
@ -185,6 +185,14 @@ public:
|
|||
nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size) override;
|
||||
nsapi_size_or_error_t recvfrom(SocketAddress *address,
|
||||
void *data, nsapi_size_t size) override;
|
||||
|
||||
nsapi_size_or_error_t sendto_control(const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
|
||||
nsapi_size_or_error_t recvfrom_control(SocketAddress *address,
|
||||
void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
|
||||
|
||||
nsapi_error_t bind(const SocketAddress &address) override;
|
||||
void set_blocking(bool blocking) override;
|
||||
void set_timeout(int timeout) override;
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#define NSAPI_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "mbed_toolchain.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -318,7 +320,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 sendto_control/recvfrom_control */
|
||||
} nsapi_socket_option_t;
|
||||
|
||||
typedef enum nsapi_tlssocket_level {
|
||||
|
@ -406,6 +409,26 @@ 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 {
|
||||
/* In C alignment can't be specified in the type declaration.
|
||||
* Specifying it in the first member definition will affect whole structure.
|
||||
*/
|
||||
MBED_ALIGN(max_align_t) 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 */
|
||||
void *network_interface; /* Network interface pointer*/
|
||||
} nsapi_pktinfo_t;
|
||||
|
||||
/** nsapi_stack_api structure
|
||||
*
|
||||
* Common api structure for network stack operations. A network stack
|
||||
|
@ -644,6 +667,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_sendto_control)(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_recvfrom_control)(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
|
||||
|
|
|
@ -244,12 +244,26 @@ nsapi_size_or_error_t CellularNonIPSocket::sendto(const SocketAddress &address,
|
|||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
nsapi_size_or_error_t CellularNonIPSocket::sendto_control(const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t CellularNonIPSocket::recvfrom(SocketAddress *address,
|
||||
void *data, nsapi_size_t size)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t CellularNonIPSocket::recvfrom_control(SocketAddress *address,
|
||||
void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t CellularNonIPSocket::setsockopt(int level, int optname, const void *optval, unsigned optlen)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
|
|
|
@ -55,14 +55,14 @@ nsapi_error_t EMACInterface::connect()
|
|||
nsapi_error_t err = NSAPI_ERROR_UNSUPPORTED;
|
||||
|
||||
if (_hw_mac_addr_set) {
|
||||
err = _stack.add_ethernet_interface(_emac, true, &_interface, _hw_mac_addr);
|
||||
err = _stack.add_ethernet_interface(_emac, true, &_interface, _hw_mac_addr, this);
|
||||
if (err == NSAPI_ERROR_UNSUPPORTED) {
|
||||
tr_error("Failed to set user MAC address");
|
||||
}
|
||||
}
|
||||
|
||||
if (err == NSAPI_ERROR_UNSUPPORTED) {
|
||||
err = _stack.add_ethernet_interface(_emac, true, &_interface);
|
||||
err = _stack.add_ethernet_interface(_emac, true, &_interface, this);
|
||||
}
|
||||
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
|
|
|
@ -27,7 +27,9 @@ 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::sendto_control(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 +46,8 @@ 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_sendto_control(_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 +77,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 sendto_control(address, data, size, NULL, 0);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t InternetDatagramSocket::send(const void *data, nsapi_size_t size)
|
||||
{
|
||||
if (!_remote_peer) {
|
||||
|
@ -82,7 +91,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::recvfrom_control(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 +114,8 @@ 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_recvfrom_control(_socket, address, buffer, size, control,
|
||||
control_size);
|
||||
|
||||
// Filter incomming packets using connected peer address
|
||||
if (recv >= 0 && _remote_peer && _remote_peer != *address) {
|
||||
|
@ -143,6 +154,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 recvfrom_control(address, buffer, size, NULL, 0);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t InternetDatagramSocket::recv(void *buffer, nsapi_size_t size)
|
||||
{
|
||||
return recvfrom(NULL, buffer, size);
|
||||
|
|
|
@ -399,6 +399,50 @@ protected:
|
|||
return err;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t socket_sendto_control(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 (control != NULL) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (!_stack_api()->socket_sendto_control) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return _stack_api()->socket_sendto_control(_stack(), socket, address.get_addr(), address.get_port(), data,
|
||||
size, control, control_size);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t socket_recvfrom_control(nsapi_socket_t socket, SocketAddress *address, void *data,
|
||||
nsapi_size_t size, nsapi_msghdr_t *control,
|
||||
nsapi_size_t control_size) override
|
||||
{
|
||||
if (control != NULL) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (!_stack_api()->socket_recvfrom_control) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_addr_t addr = {NSAPI_IPv4, 0};
|
||||
uint16_t port = 0;
|
||||
|
||||
nsapi_size_or_error_t err = _stack_api()->socket_recvfrom_control(_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) {
|
||||
|
|
|
@ -173,6 +173,15 @@ nsapi_size_or_error_t TCPSocket::sendto(const SocketAddress &address, const void
|
|||
return send(data, size);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t TCPSocket::sendto_control(const SocketAddress &address, const void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
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 +238,15 @@ nsapi_size_or_error_t TCPSocket::recvfrom(SocketAddress *address, void *data, ns
|
|||
return recv(data, size);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t TCPSocket::recvfrom_control(SocketAddress *address, void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
if (control) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return recvfrom(address, data, size);
|
||||
}
|
||||
|
||||
nsapi_error_t TCPSocket::listen(int backlog)
|
||||
{
|
||||
_lock.lock();
|
||||
|
|
|
@ -385,6 +385,13 @@ nsapi_size_or_error_t TLSSocketWrapper::sendto(const SocketAddress &, const void
|
|||
return send(data, size);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t TLSSocketWrapper::sendto_control(const SocketAddress &address, const void *data,
|
||||
nsapi_size_t size, nsapi_msghdr_t *control,
|
||||
nsapi_size_t control_size)
|
||||
{
|
||||
return sendto(address, data, size);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t TLSSocketWrapper::recv(void *data, nsapi_size_t size)
|
||||
{
|
||||
int ret;
|
||||
|
@ -445,6 +452,12 @@ nsapi_size_or_error_t TLSSocketWrapper::recvfrom(SocketAddress *address, void *d
|
|||
return recv(data, size);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t TLSSocketWrapper::recvfrom_control(SocketAddress *address, void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
return recvfrom(address, data, size);
|
||||
}
|
||||
|
||||
void TLSSocketWrapper::print_mbedtls_error(MBED_UNUSED const char *name, MBED_UNUSED int err)
|
||||
{
|
||||
// Avoid pulling in mbedtls_strerror when trace is not enabled
|
||||
|
|
|
@ -115,7 +115,7 @@ void EmacTestNetworkStack::socket_attach(nsapi_socket_t handle, void (*callback)
|
|||
|
||||
}
|
||||
|
||||
nsapi_error_t EmacTestNetworkStack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)
|
||||
nsapi_error_t EmacTestNetworkStack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface)
|
||||
{
|
||||
// Test network stack supports only one interface
|
||||
TEST_ASSERT_MESSAGE(!m_interface, "Only one interface supported!");
|
||||
|
|
|
@ -148,7 +148,7 @@ public:
|
|||
* @param[out] interface_out pointer to stack interface object controlling the EMAC
|
||||
* @return NSAPI_ERROR_OK on success, or error code
|
||||
*/
|
||||
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out);
|
||||
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface);
|
||||
|
||||
/** Translates a hostname to an IP address with specific version
|
||||
*
|
||||
|
|
|
@ -136,6 +136,12 @@ protected:
|
|||
{
|
||||
return return_value;
|
||||
};
|
||||
virtual nsapi_size_or_error_t socket_sendto_control(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 return_value;
|
||||
};
|
||||
virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size)
|
||||
{
|
||||
|
@ -149,6 +155,16 @@ protected:
|
|||
}
|
||||
return return_value;
|
||||
};
|
||||
virtual nsapi_size_or_error_t socket_recvfrom_control(nsapi_socket_t handle, SocketAddress *address,
|
||||
void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size) override
|
||||
{
|
||||
if (control != NULL) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return socket_recvfrom(handle, address, data, size);
|
||||
};
|
||||
virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) {};
|
||||
|
||||
private:
|
||||
|
|
|
@ -47,9 +47,18 @@ public:
|
|||
MOCK_METHOD5(setsockopt, nsapi_error_t(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen));
|
||||
MOCK_METHOD5(getsockopt, nsapi_error_t(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned *optlen));
|
||||
// MOCK_METHOD3(socket_attach, void(nsapi_socket_t handle, void (*callback)(void *), void *data));
|
||||
MOCK_METHOD3(add_ethernet_interface, nsapi_error_t(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out));
|
||||
MOCK_METHOD3(add_ppp_interface, nsapi_error_t(PPP &ppp, bool default_if, OnboardNetworkStack::Interface **interface_out));
|
||||
MOCK_METHOD1(set_default_interface, void (OnboardNetworkStack::Interface *interface));
|
||||
MOCK_METHOD4(add_ethernet_interface_mock, nsapi_error_t(EMAC &emac, bool default_if,
|
||||
OnboardNetworkStack::Interface **interface_out,
|
||||
NetworkInterface *user_network_interface));
|
||||
|
||||
// Wrapper written to handle function with the default argument in the gmock.
|
||||
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, NetworkInterface *user_network_interface = NULL)
|
||||
{
|
||||
return add_ethernet_interface_mock(emac, default_if, interface_out, user_network_interface);
|
||||
}
|
||||
|
||||
void *socket_cb;
|
||||
// No need to mock socket_attach really.
|
||||
void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data)
|
||||
|
@ -57,7 +66,6 @@ public:
|
|||
socket_cb = data;
|
||||
};
|
||||
|
||||
|
||||
static OnboardNetworkStackMock &get_instance()
|
||||
{
|
||||
static OnboardNetworkStackMock stackMock1;
|
||||
|
|
|
@ -68,7 +68,7 @@ protected:
|
|||
/* Enclose the heavily-used connection procedure to improve code redability */
|
||||
void doConnect(bool dhcp = true, bool blocking = true)
|
||||
{
|
||||
EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _))
|
||||
EXPECT_CALL(*stackMock, add_ethernet_interface_mock(testing::Ref(*emacMock), true, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_OK)));
|
||||
EXPECT_CALL(*netStackIface, attach(_))
|
||||
|
@ -113,7 +113,7 @@ TEST_F(TestEthernetInterface, connect)
|
|||
|
||||
TEST_F(TestEthernetInterface, connect_failure)
|
||||
{
|
||||
EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _))
|
||||
EXPECT_CALL(*stackMock, add_ethernet_interface_mock(testing::Ref(*emacMock), true, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_NO_MEMORY)));
|
||||
EXPECT_EQ(NSAPI_ERROR_NO_MEMORY, iface->connect());
|
||||
|
@ -158,7 +158,7 @@ TEST_F(TestEthernetInterface, set_network)
|
|||
EXPECT_EQ(NSAPI_ERROR_OK, iface->set_network(ipAddress, netmask, gateway));
|
||||
|
||||
// Now the bringup should have different arguments. We can't use doConnect method.
|
||||
EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _))
|
||||
EXPECT_CALL(*stackMock, add_ethernet_interface_mock(testing::Ref(*emacMock), true, _, _))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_OK)));
|
||||
EXPECT_CALL(*netStackIface, attach(_))
|
||||
|
|
|
@ -56,6 +56,16 @@ public:
|
|||
{
|
||||
return return_value;
|
||||
}
|
||||
virtual nsapi_size_or_error_t sendto_control(const SocketAddress &address, const void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
return return_value;
|
||||
}
|
||||
virtual nsapi_size_or_error_t recvfrom_control(SocketAddress *address, void *data, nsapi_size_t size,
|
||||
nsapi_msghdr_t *control, nsapi_size_t control_size)
|
||||
{
|
||||
return return_value;
|
||||
}
|
||||
virtual Socket *accept(nsapi_error_t *error = NULL)
|
||||
{
|
||||
return NULL;
|
||||
|
|
|
@ -22,6 +22,7 @@ target_sources(${TEST_NAME}
|
|||
${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c
|
||||
${mbed-os_SOURCE_DIR}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c
|
||||
test_NetworkStack.cpp
|
||||
test_MsgHeaderIterator.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${TEST_NAME}
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Arm Limited and affiliates
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "netsocket/MsgHeader.h"
|
||||
#include "netsocket/nsapi_types.h"
|
||||
|
||||
struct custom_type_t {
|
||||
nsapi_msghdr_t hdr;
|
||||
uint64_t custom_field1;
|
||||
uint64_t custom_field2;
|
||||
uint64_t custom_field3;
|
||||
uint64_t custom_field4;
|
||||
};
|
||||
|
||||
struct pktinfo_buffer_t {
|
||||
pktinfo_buffer_t()
|
||||
{
|
||||
pkt_info_1.hdr.len = sizeof(nsapi_pktinfo_t);
|
||||
pkt_info_2.hdr.len = sizeof(nsapi_pktinfo_t);
|
||||
}
|
||||
nsapi_pktinfo_t pkt_info_1;
|
||||
nsapi_pktinfo_t pkt_info_2;
|
||||
};
|
||||
|
||||
struct custom_buffer_t {
|
||||
custom_buffer_t()
|
||||
{
|
||||
pkt_info.hdr.len = sizeof(nsapi_pktinfo_t);
|
||||
msg_hdr.len = sizeof(nsapi_msghdr_t);
|
||||
custom.hdr.len = sizeof(custom_type_t);
|
||||
}
|
||||
nsapi_pktinfo_t pkt_info;
|
||||
nsapi_msghdr_t msg_hdr;
|
||||
custom_type_t custom;
|
||||
};
|
||||
|
||||
class TestMsgHeaderIterator : public testing::Test {
|
||||
protected:
|
||||
pktinfo_buffer_t p_buff;
|
||||
custom_buffer_t c_buff;
|
||||
|
||||
virtual void SetUp() {}
|
||||
|
||||
virtual void TearDown() {}
|
||||
};
|
||||
|
||||
TEST_F(TestMsgHeaderIterator, pktinfo_list)
|
||||
{
|
||||
nsapi_msghdr_t *hdr = reinterpret_cast<nsapi_msghdr_t *>(&p_buff);
|
||||
MsgHeaderIterator it(hdr, sizeof(p_buff));
|
||||
|
||||
EXPECT_EQ(it.next(), &p_buff.pkt_info_1.hdr);
|
||||
EXPECT_EQ(it.next(), &p_buff.pkt_info_2.hdr);
|
||||
EXPECT_TRUE(it.next() == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(TestMsgHeaderIterator, custom_list)
|
||||
{
|
||||
nsapi_msghdr_t *hdr_c = reinterpret_cast<nsapi_msghdr_t *>(&c_buff);
|
||||
MsgHeaderIterator it(hdr_c, sizeof(c_buff));
|
||||
|
||||
EXPECT_EQ(it.next(), &c_buff.pkt_info.hdr);
|
||||
EXPECT_EQ(it.next(), &c_buff.msg_hdr);
|
||||
EXPECT_EQ(it.next(), &c_buff.custom.hdr);
|
||||
EXPECT_TRUE(it.next() == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(TestMsgHeaderIterator, null_list)
|
||||
{
|
||||
MsgHeaderIterator it(nullptr, sizeof(p_buff));
|
||||
|
||||
EXPECT_TRUE(it.next() == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(TestMsgHeaderIterator, wrong_list_size)
|
||||
{
|
||||
nsapi_msghdr_t *hdr = reinterpret_cast<nsapi_msghdr_t *>(&p_buff);
|
||||
MsgHeaderIterator it(hdr, 0);
|
||||
|
||||
EXPECT_TRUE(it.next() == nullptr);
|
||||
}
|
||||
|
||||
TEST_F(TestMsgHeaderIterator, wrong_member_len)
|
||||
{
|
||||
nsapi_msghdr_t *hdr = reinterpret_cast<nsapi_msghdr_t *>(&p_buff);
|
||||
MsgHeaderIterator it(hdr, sizeof(p_buff));
|
||||
p_buff.pkt_info_1.hdr.len = 0;
|
||||
|
||||
EXPECT_TRUE(it.next() == nullptr);
|
||||
}
|
Loading…
Reference in New Issue