Mbed OS Reference
Loading...
Searching...
No Matches
MsgHeader.h
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#ifndef MSG_HEADER_H
19#define MSG_HEADER_H
20
21#include "netsocket/nsapi_types.h"
22
23/**
24 * Allows iteration through the list of message headers received in the control parameter of the
25 * socket_sendto_control / socket_recvfrom_control methods.
26 *
27 * @par Members types
28 *
29 * MsgHeaderIterator works on the list which members are of type nsapi_msghdr_t or other types
30 * extending this struct. For example nsapi_pktinfo:
31 *
32 * @code
33 typedef struct nsapi_pktinfo {
34 nsapi_msghdr_t hdr;
35 nsapi_addr_t ipi_addr;
36 int ipi_ifindex;
37 void *network_interface;
38 } nsapi_pktinfo_t;
39 * @endcode
40 *
41 * There are two requirements for such structures to work well with MsgHeaderIterator.
42 * - First element needs to be of type nsapi_msghdr_t.
43 * - Value of the field len of the nsapi_msghdr_t needs to bet set to the size of the whole extending type.
44 * For example:
45 *
46 * @code
47 nsapi_pktinfo_t pkt_info;
48 pkt_info.hdr.len = sizeof(nsapi_pktinfo_t);
49 * @endcode
50 *
51 * This value is used in the MsgHeaderIterator to calculate proper addresses of the list elements.
52 *
53 * @par Example
54 *
55 * Code presenting minimal usage example.
56 *
57 * @code
58 struct default_buffer_t {
59 default_buffer_t()
60 {
61 el1.hdr.len = sizeof(nsapi_pktinfo_t);
62 el2.len = sizeof(nsapi_msghdr_t);
63 el3.len = sizeof(nsapi_msghdr_t);
64 el4.hdr.len = sizeof(nsapi_pktinfo_t);
65 }
66 nsapi_pktinfo_t el1;
67 nsapi_msghdr_t el2;
68 nsapi_msghdr_t el3;
69 nsapi_pktinfo_t el4;
70 };
71
72 default_buffer buff;
73 nsapi_msghdr_t *hdr_p = reinterpret_cast<nsapi_msghdr_t *>(&buff);
74
75 MsgHeaderIterator it(hdr_p, sizeof(buff));
76
77 it.has_next() // returns true
78 auto p1 = it.next() // returns pointer to el1
79 auto p2 = it.next() // returns pointer to el2
80 auto p3 = it.next() // returns pointer to el3
81 auto p4 = it.next() // returns pointer to el4
82
83 it.has_next() // returns false
84 auto p5 = it.next() // returns nullptr
85 * @endcode
86 *
87 * @note More usage examples are implemented in the MsgHeaderIterator unit test
88 * in netsocket/tests/UNITTESTS/NetworkStack/test_MsgHeaderIterator.cpp
89 */
90
92 /** Create a MsgHeaderIterator over given nsapi_msghdr_t list.
93 *
94 * @param hdr Pointer to the first list element.
95 * @param size Size of the whole list.
96 */
98 start(hdr),
99 current(nullptr),
100 size(size)
101 {}
102
103 /** Checks if the next address of the iterator is a valid list member.
104 *
105 * @retval True if the next address is a valid member.
106 * @retval False otherwise.
107 */
108 bool has_next()
109 {
110 if (current == nullptr) {
111 if (start != nullptr && start->len <= size && start->len >= sizeof(*start)) {
112 return true;
113 } else {
114 return false;
115 }
116 }
117
118 if (current->len < sizeof(*current)) {
119 return false;
120 }
121
122 if (get_next_aligned_addr() >= (reinterpret_cast<uint8_t *>(start) + size)) {
123 return false;
124 }
125
126 return true;
127 }
128
129 /** Returns next element of the list.
130 *
131 * @retval nullptr if the list doesn't contain next element.
132 * @retval Pointer to the next element otherwise.
133 */
135 {
136 if (!has_next()) {
137 return nullptr;
138 }
139
140 if (current == nullptr) {
141 current = start;
142 } else {
143 current = reinterpret_cast<nsapi_msghdr *>(get_next_aligned_addr());
144 }
145
146 return current;
147 }
148
149private:
150 // Get address of the next member aligned to the size of msghdr_t.
151 void *get_next_aligned_addr()
152 {
153 size_t remaining_size = size - (reinterpret_cast<uintptr_t>(current) - reinterpret_cast<uintptr_t>(start));
154 void *next = reinterpret_cast<void *>(reinterpret_cast<uint8_t *>(current) + current->len);
155
156 next = std::align(
157 alignof(nsapi_msghdr_t),
158 sizeof(nsapi_msghdr_t),
159 next,
160 remaining_size
161 );
162
163 return next;
164 }
165
166 nsapi_msghdr_t *start;
167 nsapi_msghdr_t *current;
168 nsapi_size_t size;
169};
170
171
172#endif
173
unsigned int nsapi_size_t
Type used to represent the size of data passed through sockets.
Definition: nsapi_types.h:146
Allows iteration through the list of message headers received in the control parameter of the socket_...
Definition: MsgHeader.h:91
bool has_next()
Checks if the next address of the iterator is a valid list member.
Definition: MsgHeader.h:108
MsgHeaderIterator(nsapi_msghdr_t *hdr, nsapi_size_t size)
Create a MsgHeaderIterator over given nsapi_msghdr_t list.
Definition: MsgHeader.h:97
nsapi_msghdr_t * next()
Returns next element of the list.
Definition: MsgHeader.h:134
Header structure for control info.
Definition: nsapi_types.h:416