Skip to content

Commit e34f63f

Browse files
New feature: send/recv message implementation added to network stack
1 parent 81aaef4 commit e34f63f

File tree

14 files changed

+535
-26
lines changed

14 files changed

+535
-26
lines changed

connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ class AT_CellularStack : public NetworkStack {
8888

8989
virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data);
9090

91+
// FIXME
92+
nsapi_size_or_error_t socket_sendmsg(nsapi_socket_t handle, const SocketAddress &address,
93+
const void *data, nsapi_size_t size,
94+
nsapi_msghdr_t *control, nsapi_size_t control_size) override
95+
{
96+
return NSAPI_ERROR_UNSUPPORTED;
97+
}
98+
99+
nsapi_size_or_error_t socket_recvmsg(nsapi_socket_t handle, SocketAddress *address,
100+
void *data, nsapi_size_t size,
101+
nsapi_msghdr_t *control, nsapi_size_t control_size) override
102+
{
103+
return NSAPI_ERROR_UNSUPPORTED;
104+
}
105+
91106
protected:
92107
class CellularSocket {
93108
public:

connectivity/lwipstack/include/lwipstack/LWIPStack.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,15 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> {
503503
nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
504504
void *buffer, nsapi_size_t size) override;
505505

506+
// TODO: Add doc
507+
nsapi_size_or_error_t socket_recvmsg(nsapi_socket_t handle, SocketAddress *address,
508+
void *data, nsapi_size_t size,
509+
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
510+
511+
nsapi_size_or_error_t socket_sendmsg(nsapi_socket_t handle, const SocketAddress &address,
512+
const void *data, nsapi_size_t size,
513+
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
514+
506515
/** Register a callback on state change of the socket
507516
*
508517
* The specified callback will be called on state changes such as when

connectivity/lwipstack/include/lwipstack/lwipopts.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@
311311

312312
#endif
313313

314+
// FIXME: Add compile time configuration and define conditionaly
315+
#define LWIP_NETBUF_RECVINFO 1
316+
314317
// Make sure we default these to off, so
315318
// LWIP doesn't default to on
316319
#ifndef LWIP_ARP

connectivity/lwipstack/source/LWIPStack.cpp

Lines changed: 117 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
* limitations under the License.
1616
*/
1717
#include "nsapi.h"
18+
#include "netsocket/MsgHeader.h"
1819
#include "mbed_interface.h"
1920
#include "mbed_assert.h"
2021
#include "Semaphore.h"
21-
#include <stdio.h>
2222
#include <stdbool.h>
2323
#include <string.h>
2424

@@ -37,6 +37,7 @@
3737
#include "lwip/raw.h"
3838
#include "lwip/netif.h"
3939
#include "lwip/lwip_errno.h"
40+
#include "lwip/ip_addr.h"
4041
#include "lwip-sys/arch/sys_arch.h"
4142

4243
#include "LWIPStack.h"
@@ -439,24 +440,109 @@ nsapi_size_or_error_t LWIP::socket_recv(nsapi_socket_t handle, void *data, nsapi
439440
}
440441

441442
nsapi_size_or_error_t LWIP::socket_sendto(nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size)
443+
{
444+
return socket_sendmsg(handle, address, data, size, NULL, 0);
445+
}
446+
447+
nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size)
448+
{
449+
return socket_recvmsg(handle, address, data, size, NULL, 0);
450+
451+
}
452+
453+
nsapi_size_or_error_t LWIP::socket_recvmsg(nsapi_socket_t handle, SocketAddress *address,
454+
void *data, nsapi_size_t size,
455+
nsapi_msghdr_t *control, nsapi_size_t control_size)
442456
{
443457
struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
444-
ip_addr_t ip_addr;
458+
struct netbuf *buf;
459+
460+
err_t err = netconn_recv(s->conn, &buf);
461+
if (err != ERR_OK) {
462+
return err_remap(err);
463+
}
464+
465+
if (address) {
466+
nsapi_addr_t addr;
467+
convert_lwip_addr_to_mbed(&addr, netbuf_fromaddr(buf));
468+
address->set_addr(addr);
469+
address->set_port(netbuf_fromport(buf));
470+
}
471+
472+
if ((s->conn->flags & NETCONN_FLAG_PKTINFO) && control && control_size >= sizeof(nsapi_pktinfo_t)) {
473+
nsapi_pktinfo_t *pkt_info = reinterpret_cast<nsapi_pktinfo *>(control);
474+
// Not optimal but sufficient. It should help the caller in not iterating over
475+
// the control data structure
476+
control->len = control_size;
477+
control->level = NSAPI_SOCKET;
478+
control->type = NSAPI_PKTINFO;
479+
// retrieve the destination
480+
convert_lwip_addr_to_mbed(&pkt_info->ipi_addr, netbuf_destaddr(buf));
481+
// retrieve the interface id
482+
pkt_info->ipi_ifindex = buf->p->if_idx;
483+
}
484+
485+
u16_t recv = netbuf_copy(buf, data, (u16_t)size);
486+
netbuf_delete(buf);
487+
488+
return recv;
489+
}
490+
491+
nsapi_size_or_error_t LWIP::socket_sendmsg(nsapi_socket_t handle, const SocketAddress &address,
492+
const void *data, nsapi_size_t size,
493+
nsapi_msghdr_t *control, nsapi_size_t control_size)
494+
{
495+
struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
496+
ip_addr_t ip_addr = {};
497+
498+
// Used for backup the bound address if the packet must be sent from a specific address,
499+
ip_addr_t bound_addr = {};
500+
ip_addr_t src_addr = {};
501+
502+
nsapi_pktinfo_t *pkt_info = nullptr;
445503

446504
nsapi_addr_t addr = address.get_addr();
447505
if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
448506
return NSAPI_ERROR_PARAMETER;
449507
}
450-
struct netif *netif_ = netif_get_by_index(s->conn->pcb.ip->netif_idx);
508+
509+
// We try to extract the pktinfo from the header
510+
511+
if (control) {
512+
MsgHeaderIterator it(control, control_size);
513+
while (it.has_next()) {
514+
auto *hdr = it.next();
515+
if (hdr->level == NSAPI_SOCKET && hdr->type == NSAPI_PKTINFO) {
516+
pkt_info = reinterpret_cast<nsapi_pktinfo_t *>(hdr);
517+
break;
518+
}
519+
}
520+
}
521+
522+
if (pkt_info) {
523+
if (!convert_mbed_addr_to_lwip(&src_addr, &pkt_info->ipi_addr)) {
524+
return NSAPI_ERROR_PARAMETER;
525+
}
526+
}
527+
528+
struct netif *netif_ = nullptr;
529+
530+
if (pkt_info) {
531+
netif_ = netif_get_by_index(pkt_info->ipi_ifindex);
532+
} else {
533+
netif_ = netif_get_by_index(s->conn->pcb.ip->netif_idx);
534+
}
451535
if (!netif_) {
452536
netif_ = &default_interface->netif;
453537
}
538+
454539
if (netif_) {
455540
if ((addr.version == NSAPI_IPv4 && !get_ipv4_addr(netif_)) ||
456541
(addr.version == NSAPI_IPv6 && !get_ipv6_addr(netif_) && !get_ipv6_link_local_addr(netif_))) {
457542
return NSAPI_ERROR_PARAMETER;
458543
}
459544
}
545+
460546
struct netbuf *buf = netbuf_new();
461547

462548
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
465551
return err_remap(err);
466552
}
467553

468-
err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port());
469-
netbuf_delete(buf);
470-
if (err != ERR_OK) {
471-
return err_remap(err);
554+
// handle src destination if required
555+
if (pkt_info) {
556+
// Backup the bound address
557+
ip_addr_copy(bound_addr, s->conn->pcb.udp->local_ip);
558+
// replace it with the source address
559+
if (!ip_addr_isany(&src_addr)) {
560+
ip_addr_copy(s->conn->pcb.udp->local_ip, src_addr);
561+
}
472562
}
473563

474-
return size;
475-
}
564+
err = netconn_sendto(s->conn, buf, &ip_addr, address.get_port());
476565

477-
nsapi_size_or_error_t LWIP::socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size)
478-
{
479-
struct mbed_lwip_socket *s = (struct mbed_lwip_socket *)handle;
480-
struct netbuf *buf;
566+
if (pkt_info) {
567+
// restore bound address
568+
ip_addr_copy(s->conn->pcb.udp->local_ip, bound_addr);
569+
}
481570

482-
err_t err = netconn_recv(s->conn, &buf);
571+
netbuf_delete(buf);
483572
if (err != ERR_OK) {
484573
return err_remap(err);
485574
}
486575

487-
if (address) {
488-
nsapi_addr_t addr;
489-
convert_lwip_addr_to_mbed(&addr, netbuf_fromaddr(buf));
490-
address->set_addr(addr);
491-
address->set_port(netbuf_fromport(buf));
492-
}
493-
494-
u16_t recv = netbuf_copy(buf, data, (u16_t)size);
495-
netbuf_delete(buf);
496-
497-
return recv;
576+
return size;
498577
}
499578

500579
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
687766
}
688767
s->conn->pcb.ip->tos = (u8_t)(*(const int *)optval);
689768
return 0;
769+
770+
case NSAPI_PKTINFO:
771+
// FIXME: Turn NETCONN_FLAG_PKTINFO off by default
772+
if (optlen != sizeof(int)) {
773+
return NSAPI_ERROR_UNSUPPORTED;
774+
}
775+
if (*(const int *)optval) {
776+
s->conn->flags |= NETCONN_FLAG_PKTINFO;
777+
} else {
778+
s->conn->flags &= ~NETCONN_FLAG_PKTINFO;
779+
}
780+
return 0;
781+
690782
default:
691783
return NSAPI_ERROR_UNSUPPORTED;
692784
}

connectivity/nanostack/include/nanostack-interface/Nanostack.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,21 @@ class Nanostack : public OnboardNetworkStack, private mbed::NonCopyable<Nanostac
302302
*/
303303
nsapi_error_t getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen) override;
304304

305+
// FIXME: Implement
306+
nsapi_size_or_error_t socket_sendmsg(nsapi_socket_t handle, const SocketAddress &address,
307+
const void *data, nsapi_size_t size,
308+
nsapi_msghdr_t *control, nsapi_size_t control_size) override
309+
{
310+
return NSAPI_ERROR_UNSUPPORTED;
311+
}
312+
313+
nsapi_size_or_error_t socket_recvmsg(nsapi_socket_t handle, SocketAddress *address,
314+
void *data, nsapi_size_t size,
315+
nsapi_msghdr_t *control, nsapi_size_t control_size) override
316+
{
317+
return NSAPI_ERROR_UNSUPPORTED;
318+
}
319+
305320
private:
306321

307322
/** Call in callback

connectivity/netsocket/include/netsocket/InternetDatagramSocket.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ class InternetDatagramSocket : public InternetSocket {
7474
nsapi_size_or_error_t recvfrom(SocketAddress *address,
7575
void *data, nsapi_size_t size) override;
7676

77+
// TODO: documentation
78+
nsapi_size_or_error_t sendmsg(const SocketAddress &address,
79+
const void *data, nsapi_size_t size,
80+
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
81+
82+
nsapi_size_or_error_t recvmsg(SocketAddress *address,
83+
void *data, nsapi_size_t size,
84+
nsapi_msghdr_t *control, nsapi_size_t control_size) override;
85+
7786
/** Set the remote address for next send() call and filtering
7887
* of incoming packets. To reset the address, zero initialized
7988
* SocketAddress must be in the address parameter.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (c) 2021 ARM Limited
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/* @file MeshInterface.h Mesh network interface */
19+
/** \addtogroup netinterface */
20+
/** @{*/
21+
22+
#ifndef MSG_HEADER_H
23+
#define MSG_HEADER_H
24+
25+
#include "netsocket/nsapi_types.h"
26+
27+
struct MsgHeaderIterator {
28+
MsgHeaderIterator(nsapi_msghdr_t *hdr, nsapi_size_t size) :
29+
start(hdr),
30+
current(nullptr),
31+
size(size)
32+
{}
33+
34+
bool has_next()
35+
{
36+
if (current == nullptr) {
37+
if (start != nullptr) {
38+
return true;
39+
} else {
40+
return false;
41+
}
42+
}
43+
44+
if (current->len < sizeof(*current)) {
45+
return false;
46+
}
47+
48+
if ((reinterpret_cast<uint8_t *>(current) + current->len) >= (reinterpret_cast<uint8_t *>(start) + size)) {
49+
return false;
50+
}
51+
52+
return true;
53+
}
54+
55+
nsapi_msghdr_t *next()
56+
{
57+
if (!has_next()) {
58+
return nullptr;
59+
}
60+
61+
if (current == nullptr) {
62+
current = start;
63+
} else {
64+
current = reinterpret_cast<nsapi_msghdr_t *>(reinterpret_cast<uint8_t *>(current) + current->len);
65+
}
66+
67+
return current;
68+
}
69+
70+
private:
71+
nsapi_msghdr_t *start;
72+
nsapi_msghdr_t *current;
73+
nsapi_size_t size;
74+
};
75+
76+
77+
#endif
78+
79+
/** @}*/

0 commit comments

Comments
 (0)