Dawn Framework 1.0
Universal data acquisition framework for embedded systems
client.cxx
1// dawn/src/proto/wakaama/client.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "client.hxx"
7
8#include <cerrno>
9#include <cstring>
10#include <new>
11
12using namespace dawn;
13using namespace dawn::wakaama_internal;
14
16 : owner(owner_)
17 , ctx(nullptr)
18 , securityObj(nullptr)
19 , serverObj(nullptr)
20 , deviceObj(nullptr)
21 , instancePools(nullptr)
22{
23}
24
26{
27 closeContext();
28 destroy({});
29}
30
31int ClientRuntime::build(const std::vector<ObjectBinding *> &objects)
32{
33 int ret;
34
35 securityObj = new (std::nothrow) lwm2m_object_t();
36 serverObj = new (std::nothrow) lwm2m_object_t();
37 deviceObj = new (std::nothrow) lwm2m_object_t();
38 if (securityObj == nullptr || serverObj == nullptr || deviceObj == nullptr)
39 {
40 return -ENOMEM;
41 }
42
43 ret = buildSecurityAndServerObjects();
44 if (ret < 0)
45 {
46 return ret;
47 }
48
49 ret = buildDeviceObject();
50 if (ret < 0)
51 {
52 return ret;
53 }
54
55 lwm2mObjects.push_back(securityObj);
56 lwm2mObjects.push_back(serverObj);
57 lwm2mObjects.push_back(deviceObj);
58
59 for (ObjectBinding *obj : objects)
60 {
61 ret = obj->init();
62 if (ret < 0)
63 {
64 return ret;
65 }
66
67 lwm2mObjects.push_back(obj->object());
68 }
69
70 return OK;
71}
72
73int ClientRuntime::buildSecurityAndServerObjects()
74{
75 InstancePools *pools;
76 const size_t serverCapacity = owner.serverPoolCapacity();
77
78 pools = new (std::nothrow) InstancePools();
79 if (pools == nullptr)
80 {
81 return -ENOMEM;
82 }
83
84 pools->securityCapacity = serverCapacity;
85 pools->serverCapacity = serverCapacity;
86 pools->security = new (std::nothrow) security_instance_s[serverCapacity]();
87 pools->server = new (std::nothrow) server_instance_s[serverCapacity]();
88 if (pools->security == nullptr || pools->server == nullptr)
89 {
90 delete[] pools->security;
91 delete[] pools->server;
92 delete pools;
93 return -ENOMEM;
94 }
95
96 instancePools = pools;
97 for (const CProtoWakaama::ServerConfig &server : owner.servers)
98 {
99 security_instance_s *secInst;
100 server_instance_s *srvInst = nullptr;
101 std::string uri = owner.serverUri(server);
102
103 secInst = allocateSecurityInstance(pools);
104 if (!server.bootstrap)
105 {
106 srvInst = allocateServerInstance(pools);
107 }
108
109 if (secInst == nullptr || (!server.bootstrap && srvInst == nullptr))
110 {
111 return -ENOMEM;
112 }
113
114 secInst->id = server.securityInstanceId;
115 secInst->shortServerId = server.shortServerId;
116 secInst->holdoff = server.holdoff;
117 secInst->bootstrapTimeout = server.bootstrapTimeout;
118 secInst->securityMode = server.securityMode;
119 secInst->bootstrap = server.bootstrap;
120 if (!assignSecurityString(
121 *secInst, reinterpret_cast<const uint8_t *>(uri.c_str()), uri.size()) ||
122 !assignSecurityBuffer(reinterpret_cast<const uint8_t *>(server.pskIdentity.data()),
123 server.pskIdentity.size(),
124 secInst->publicIdentityBuffer,
125 sizeof(secInst->publicIdentityBuffer),
126 &secInst->publicIdentity,
127 &secInst->publicIdentityLen) ||
128 !assignSecurityBuffer(server.pskKey.data(),
129 server.pskKey.size(),
130 secInst->secretKeyBuffer,
131 sizeof(secInst->secretKeyBuffer),
132 &secInst->secretKey,
133 &secInst->secretKeyLen))
134 {
135 return -ENOMEM;
136 }
137
138 securityObj->instanceList = LWM2M_LIST_ADD(securityObj->instanceList, secInst);
139
140 if (!server.bootstrap)
141 {
142 srvInst->id = server.serverInstanceId;
143 srvInst->shortServerId = server.shortServerId;
144 srvInst->lifetime = server.lifetime;
145 strncpy(
146 srvInst->binding, (server.binding & BINDING_Q) ? "UQ" : "U", sizeof(srvInst->binding));
147 srvInst->storing = false;
148
149 serverObj->instanceList = LWM2M_LIST_ADD(serverObj->instanceList, srvInst);
150 }
151 }
152
153 securityObj->objID = LWM2M_SECURITY_OBJECT_ID;
154 securityObj->userData = pools;
155 securityObj->readFunc = securityRead;
156 securityObj->discoverFunc = securityDiscover;
157#ifdef CONFIG_WAKAAMA_BOOTSTRAP
158 securityObj->writeFunc = securityWrite;
159 securityObj->createFunc = securityCreate;
160 securityObj->deleteFunc = securityDelete;
161#endif
162
163 serverObj->objID = LWM2M_SERVER_OBJECT_ID;
164 serverObj->userData = pools;
165 serverObj->readFunc = serverRead;
166 serverObj->discoverFunc = serverDiscover;
167 serverObj->executeFunc = serverExecute;
168 serverObj->writeFunc = serverWrite;
169#ifdef CONFIG_WAKAAMA_BOOTSTRAP
170 serverObj->createFunc = serverCreate;
171 serverObj->deleteFunc = serverDelete;
172#endif
173
174 return OK;
175}
176
177int ClientRuntime::buildDeviceObject()
178{
179 device_instance_s *devInst = new (std::nothrow) device_instance_s();
180 if (devInst == nullptr)
181 {
182 return -ENOMEM;
183 }
184
185 devInst->id = 0;
186 deviceObj->objID = CProtoWakaama::WAKAAMA_OBJECT_DEVICE;
187 deviceObj->instanceList = LWM2M_LIST_ADD(deviceObj->instanceList, devInst);
188 deviceObj->userData = &owner;
189 deviceObj->readFunc = deviceRead;
190 deviceObj->discoverFunc = deviceDiscover;
191
192 // Resolve any battery IO bindings declared in the device: config block so the
193 // Device object can serve /3/0/7,9,20 from them.
194 deviceResolveBatteryBindings(&owner);
195
196 return OK;
197}
198
199void ClientRuntime::destroy(const std::vector<ObjectBinding *> &objects)
200{
201 closeContext();
202
203 for (ObjectBinding *obj : objects)
204 {
205 obj->deinit();
206 }
207
208 lwm2mObjects.clear();
209
210 if (securityObj != nullptr)
211 {
212 securityObj->instanceList = nullptr;
213 delete securityObj;
214 securityObj = nullptr;
215 }
216
217 if (serverObj != nullptr)
218 {
219 serverObj->instanceList = nullptr;
220 delete serverObj;
221 serverObj = nullptr;
222 }
223
224 if (deviceObj != nullptr)
225 {
226 while (deviceObj->instanceList != nullptr)
227 {
228 device_instance_s *inst = reinterpret_cast<device_instance_s *>(deviceObj->instanceList);
229
230 deviceObj->instanceList = deviceObj->instanceList->next;
231 delete inst;
232 }
233
234 delete deviceObj;
235 deviceObj = nullptr;
236 }
237
238 if (instancePools != nullptr)
239 {
240 delete[] instancePools->security;
241 delete[] instancePools->server;
242 delete instancePools;
243 instancePools = nullptr;
244 }
245}
246
247int ClientRuntime::openContext(void *userdata)
248{
249 ctx = lwm2m_init(userdata);
250
251 return ctx == nullptr ? -ENOMEM : OK;
252}
253
254int ClientRuntime::configure(const char *endpoint)
255{
256 if (ctx == nullptr)
257 {
258 return -ENODEV;
259 }
260
261 return lwm2m_configure(ctx,
262 endpoint,
263 nullptr,
264 nullptr,
265 static_cast<uint16_t>(lwm2mObjects.size()),
266 lwm2mObjects.data());
267}
268
269int ClientRuntime::step(time_t *timeout)
270{
271 return ctx == nullptr ? -ENODEV : lwm2m_step(ctx, timeout);
272}
273
275{
276 if (ctx != nullptr && ctx->state == STATE_BOOTSTRAP_REQUIRED &&
277 ctx->bootstrapServerList == nullptr && ctx->serverList != nullptr)
278 {
279 ctx->state = STATE_REGISTER_REQUIRED;
280 return true;
281 }
282
283 return false;
284}
285
287{
288 return ctx != nullptr && ctx->state == STATE_READY;
289}
290
291void ClientRuntime::handlePacket(uint8_t *buffer, size_t length, void *session)
292{
293 if (ctx != nullptr && session != nullptr)
294 {
295 lwm2m_handle_packet(ctx, buffer, length, session);
296 }
297}
298
300{
301 if (securityObj == nullptr)
302 {
303 return nullptr;
304 }
305
306 return reinterpret_cast<security_instance_s *>(
307 lwm2m_list_find(securityObj->instanceList, securityInstanceId));
308}
309
310void ClientRuntime::closeContext()
311{
312 if (ctx != nullptr)
313 {
314 lwm2m_close(ctx);
315 ctx = nullptr;
316 }
317}
Wakaama LwM2M client protocol implementation.
Definition wakaama.hxx:52
int configure(const char *endpoint)
Configure the Wakaama client endpoint and registered objects.
Definition client.cxx:254
bool recoverFromBootstrapWedge()
Nudge a registration-failed client (parked in STATE_BOOTSTRAP_REQUIRED with no bootstrap server) back...
Definition client.cxx:274
~ClientRuntime()
Close the Wakaama context and release owned object allocations.
Definition client.cxx:25
int build(const std::vector< ObjectBinding * > &objects)
Build built-in and descriptor-backed LwM2M objects.
Definition client.cxx:31
void destroy(const std::vector< ObjectBinding * > &objects)
Release built-in and descriptor-backed LwM2M objects.
Definition client.cxx:199
security_instance_s * findSecurityInstance(uint16_t securityInstanceId) const
Find a Security object instance by instance ID.
Definition client.cxx:299
bool ready() const
Return true when the Wakaama client has completed registration.
Definition client.cxx:286
ClientRuntime(CProtoWakaama &owner)
Construct runtime state for a Wakaama protocol owner.
Definition client.cxx:15
int step(time_t *timeout)
Run one Wakaama state-machine step.
Definition client.cxx:269
int openContext(void *userdata)
Open the Wakaama client context with transport callback userdata.
Definition client.cxx:247
void handlePacket(uint8_t *buffer, size_t length, void *session)
Deliver one received packet into the Wakaama client context.
Definition client.cxx:291
Runtime binding between one LwM2M object and Dawn IO resources.
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Fixed pools backing bootstrap-mutable Security and Server objects.
Definition internal.hxx:109
Runtime representation of the single LwM2M Device instance.
Definition internal.hxx:101
Runtime representation of one LwM2M Security object instance.
Definition internal.hxx:53
Runtime representation of one LwM2M Server object instance.
Definition internal.hxx:75