Skip to content

Commit 5bf1f87

Browse files
committed
api: add support for creating device after device start up
1 parent ff6b7ad commit 5bf1f87

34 files changed

Lines changed: 920 additions & 149 deletions

api/oc_core_res.c

Lines changed: 183 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@
3939
#include "util/oc_macros_internal.h"
4040
#include "util/oc_secure_string_internal.h"
4141

42+
#ifdef OC_HAS_FEATURE_DEVICE_ADD
43+
#include "oc_acl.h"
44+
#include "oc_cred.h"
45+
#ifdef OC_SECURITY
46+
#include "security/oc_ael_internal.h"
47+
#include "security/oc_svr_internal.h"
48+
#endif /* OC_SECURITY*/
49+
#endif /* OC_HAS_FEATURE_DEVICE_ADD */
50+
4251
#ifdef OC_CLOUD
4352
#include "api/cloud/oc_cloud_resource_internal.h"
4453
#endif /* OC_CLOUD */
@@ -105,50 +114,70 @@ oc_core_init(void)
105114
#endif /* OC_DYNAMIC_ALLOCATION */
106115
}
107116

117+
#ifdef OC_DYNAMIC_ALLOCATION
108118
static void
109-
oc_core_free_device_info_properties(oc_device_info_t *oc_device_info_item)
119+
core_free_device_info_properties(oc_device_info_t *oc_device_info_item)
110120
{
111-
if (oc_device_info_item) {
112-
oc_free_string(&(oc_device_info_item->name));
113-
oc_free_string(&(oc_device_info_item->icv));
114-
oc_free_string(&(oc_device_info_item->dmv));
115-
}
121+
oc_free_string(&(oc_device_info_item->name));
122+
oc_free_string(&(oc_device_info_item->icv));
123+
oc_free_string(&(oc_device_info_item->dmv));
116124
}
125+
#endif /* OC_DYNAMIC_ALLOCATION */
117126

118-
void
119-
oc_core_shutdown(void)
127+
// Remove all core cesources
128+
static void
129+
core_resources_deinit(void)
120130
{
121-
oc_platform_deinit();
122-
123-
uint32_t device_count = OC_ATOMIC_LOAD32(g_device_count);
124-
#ifdef OC_DYNAMIC_ALLOCATION
125-
if (g_oc_device_info != NULL) {
126-
#endif /* OC_DYNAMIC_ALLOCATION */
127-
for (uint32_t i = 0; i < device_count; ++i) {
128-
oc_device_info_t *oc_device_info_item = &g_oc_device_info[i];
129-
oc_core_free_device_info_properties(oc_device_info_item);
130-
}
131131
#ifdef OC_DYNAMIC_ALLOCATION
132-
free(g_oc_device_info);
133-
g_oc_device_info = NULL;
132+
if (g_core_resources == NULL) {
133+
return;
134134
}
135135
#endif /* OC_DYNAMIC_ALLOCATION */
136+
uint32_t device_count = OC_ATOMIC_LOAD32(g_device_count);
136137

138+
for (size_t i = 0;
139+
i < OC_NUM_CORE_PLATFORM_RESOURCES +
140+
(OC_NUM_CORE_LOGICAL_DEVICE_RESOURCES * device_count);
141+
++i) {
142+
oc_resource_t *core_resource = &g_core_resources[i];
143+
oc_ri_free_resource_properties(core_resource);
144+
}
137145
#ifdef OC_DYNAMIC_ALLOCATION
138-
if (g_core_resources != NULL) {
146+
free(g_core_resources);
147+
g_core_resources = NULL;
148+
#else /* !OC_DYNAMIC_ALLOCATION */
149+
memset(g_core_resources, 0, sizeof(g_core_resources));
139150
#endif /* OC_DYNAMIC_ALLOCATION */
140-
for (size_t i = 0;
141-
i < OC_NUM_CORE_PLATFORM_RESOURCES +
142-
(OC_NUM_CORE_LOGICAL_DEVICE_RESOURCES * device_count);
143-
++i) {
144-
oc_resource_t *core_resource = &g_core_resources[i];
145-
oc_ri_free_resource_properties(core_resource);
146-
}
151+
}
152+
153+
// Remove all devices
154+
static void
155+
core_devices_deinit(void)
156+
{
147157
#ifdef OC_DYNAMIC_ALLOCATION
148-
free(g_core_resources);
149-
g_core_resources = NULL;
158+
if (g_oc_device_info == NULL) {
159+
return;
150160
}
151161
#endif /* OC_DYNAMIC_ALLOCATION */
162+
163+
uint32_t device_count = OC_ATOMIC_LOAD32(g_device_count);
164+
for (uint32_t i = 0; i < device_count; ++i) {
165+
core_free_device_info_properties(&g_oc_device_info[i]);
166+
}
167+
#ifdef OC_DYNAMIC_ALLOCATION
168+
free(g_oc_device_info);
169+
g_oc_device_info = NULL;
170+
#else /* !OC_DYNAMIC_ALLOCATION */
171+
memset(g_oc_device_info, 0, sizeof(g_oc_device_info));
172+
#endif /* OC_DYNAMIC_ALLOCATION */
173+
}
174+
175+
void
176+
oc_core_shutdown(void)
177+
{
178+
oc_platform_deinit();
179+
core_resources_deinit();
180+
core_devices_deinit();
152181
OC_ATOMIC_STORE32(g_device_count, 0);
153182
}
154183

@@ -265,11 +294,30 @@ oc_core_get_latency(void)
265294
}
266295

267296
static void
268-
core_update_device_data(uint32_t device_count, oc_add_new_device_t cfg)
297+
core_set_device_info(oc_device_info_t *info, oc_add_new_device_t cfg)
298+
{
299+
assert(cfg.name != NULL);
300+
assert(cfg.spec_version != NULL);
301+
assert(cfg.data_model_version != NULL);
302+
303+
oc_gen_uuid(&info->di);
304+
oc_gen_uuid(&info->piid);
305+
306+
oc_new_string(&info->name, cfg.name, strlen(cfg.name));
307+
oc_new_string(&info->icv, cfg.spec_version, strlen(cfg.spec_version));
308+
oc_new_string(&info->dmv, cfg.data_model_version,
309+
strlen(cfg.data_model_version));
310+
info->add_device_cb = cfg.add_device_cb;
311+
info->data = cfg.add_device_cb_data;
312+
}
313+
314+
static void
315+
core_update_device_data(size_t max_device_index, oc_add_new_device_t cfg)
269316
{
270317
#ifdef OC_DYNAMIC_ALLOCATION
271-
size_t new_num = OC_NUM_CORE_PLATFORM_RESOURCES +
272-
(OC_NUM_CORE_LOGICAL_DEVICE_RESOURCES * (device_count + 1));
318+
size_t new_num =
319+
OC_NUM_CORE_PLATFORM_RESOURCES +
320+
(OC_NUM_CORE_LOGICAL_DEVICE_RESOURCES * (max_device_index + 1));
273321
oc_resource_t *core_resources =
274322
(oc_resource_t *)realloc(g_core_resources, new_num * sizeof(oc_resource_t));
275323
if (core_resources == NULL) {
@@ -282,31 +330,23 @@ core_update_device_data(uint32_t device_count, oc_add_new_device_t cfg)
282330
g_core_resources = core_resources;
283331

284332
oc_device_info_t *device_info = (oc_device_info_t *)realloc(
285-
g_oc_device_info, (device_count + 1) * sizeof(oc_device_info_t));
286-
333+
g_oc_device_info, (max_device_index + 1) * sizeof(oc_device_info_t));
287334
if (device_info == NULL) {
288335
oc_abort("Insufficient memory");
289336
}
290-
memset(&device_info[device_count], 0, sizeof(oc_device_info_t));
337+
memset(&device_info[max_device_index], 0, sizeof(oc_device_info_t));
291338
g_oc_device_info = device_info;
292339
#endif /* OC_DYNAMIC_ALLOCATION */
293340

294-
oc_gen_uuid(&g_oc_device_info[device_count].di);
295-
oc_gen_uuid(&g_oc_device_info[device_count].piid);
296-
297-
oc_new_string(&g_oc_device_info[device_count].name, cfg.name,
298-
strlen(cfg.name));
299-
oc_new_string(&g_oc_device_info[device_count].icv, cfg.spec_version,
300-
strlen(cfg.spec_version));
301-
oc_new_string(&g_oc_device_info[device_count].dmv, cfg.data_model_version,
302-
strlen(cfg.data_model_version));
303-
g_oc_device_info[device_count].add_device_cb = cfg.add_device_cb;
304-
g_oc_device_info[device_count].data = cfg.add_device_cb_data;
341+
core_set_device_info(&g_oc_device_info[max_device_index], cfg);
305342
}
306343

307344
static void
308-
oc_create_device_resource(size_t device_count, const char *uri, const char *rt)
345+
oc_create_device_resource(size_t device, const char *uri, const char *rt)
309346
{
347+
assert(uri != NULL);
348+
assert(rt != NULL);
349+
310350
/* Construct device resource */
311351
int properties = OC_DISCOVERABLE;
312352
#ifdef OC_CLOUD
@@ -316,81 +356,92 @@ oc_create_device_resource(size_t device_count, const char *uri, const char *rt)
316356
oc_string_view(rt, oc_strnlen(rt, OC_CHAR_ARRAY_LEN(OCF_D_RT) + 1));
317357
if (oc_string_view_is_equal(
318358
rtv, oc_string_view(OCF_D_RT, OC_CHAR_ARRAY_LEN(OCF_D_RT)))) {
319-
oc_core_populate_resource(OCF_D, device_count, uri,
320-
OC_IF_R | OC_IF_BASELINE, OC_IF_R, properties,
321-
oc_core_device_handler, /*put*/ NULL,
359+
oc_core_populate_resource(OCF_D, device, uri, OC_IF_R | OC_IF_BASELINE,
360+
OC_IF_R, properties, oc_core_device_handler,
361+
/*put*/ NULL,
322362
/*post*/ NULL, /*delete*/ NULL, 1, rt);
323363
} else {
324-
oc_core_populate_resource(OCF_D, device_count, uri,
325-
OC_IF_R | OC_IF_BASELINE, OC_IF_R, properties,
326-
oc_core_device_handler, /*put*/ NULL,
364+
oc_core_populate_resource(OCF_D, device, uri, OC_IF_R | OC_IF_BASELINE,
365+
OC_IF_R, properties, oc_core_device_handler,
366+
/*put*/ NULL,
327367
/*post*/ NULL, /*delete*/ NULL, 2, rt, OCF_D_RT);
328368
}
329369
}
330370

331-
oc_device_info_t *
332-
oc_core_add_new_device(oc_add_new_device_t cfg)
371+
static int64_t
372+
core_increment_device_count(void)
333373
{
334-
assert(cfg.uri != NULL);
335-
assert(cfg.rt != NULL);
336-
assert(cfg.name != NULL);
337-
assert(cfg.spec_version != NULL);
338-
assert(cfg.data_model_version != NULL);
339-
340374
uint32_t device_count = OC_ATOMIC_LOAD32(g_device_count);
341375

342376
bool exchanged = false;
343377
while (!exchanged) {
344378
#ifndef OC_DYNAMIC_ALLOCATION
345379
if (device_count == OC_MAX_NUM_DEVICES) {
346380
OC_ERR("device limit reached");
347-
return NULL;
381+
return -1;
348382
}
349383
#endif /* !OC_DYNAMIC_ALLOCATION */
350384
if ((uint64_t)device_count == (uint64_t)MIN(SIZE_MAX, UINT32_MAX)) {
351385
OC_ERR("limit of value type of g_device_count reached");
352-
return NULL;
386+
return -1;
353387
}
354388
OC_ATOMIC_COMPARE_AND_SWAP32(g_device_count, device_count, device_count + 1,
355389
exchanged);
356390
}
391+
return device_count;
392+
}
357393

358-
core_update_device_data(device_count, cfg);
359-
360-
oc_create_device_resource(device_count, cfg.uri, cfg.rt);
394+
static void
395+
oc_core_set_device_resources_at_index(uint32_t device, const char *uri,
396+
const char *rt)
397+
{
398+
oc_create_device_resource(device, uri, rt);
361399

362400
if (oc_get_con_res_announced()) {
363401
/* Construct oic.wk.con resource for this device. */
364-
oc_create_con_resource(device_count);
402+
oc_create_con_resource(device);
365403
}
366404

367-
oc_create_discovery_resource(device_count);
405+
oc_create_discovery_resource(device);
368406

369407
#ifdef OC_WKCORE
370-
oc_create_wkcore_resource(device_count);
408+
oc_create_wkcore_resource(device);
371409
#endif /* OC_WKCORE */
372410

373411
#ifdef OC_INTROSPECTION
374-
oc_create_introspection_resource(device_count);
412+
oc_create_introspection_resource(device);
375413
#endif /* OC_INTROSPECTION */
376414

377415
#ifdef OC_MNT
378-
oc_create_maintenance_resource(device_count);
416+
oc_create_maintenance_resource(device);
379417
#endif /* OC_MNT */
380418
#if defined(OC_CLIENT) && defined(OC_SERVER) && defined(OC_CLOUD)
381-
oc_create_cloudconf_resource(device_count);
419+
oc_create_cloudconf_resource(device);
382420
#endif /* OC_CLIENT && OC_SERVER && OC_CLOUD */
383421

384422
#ifdef OC_HAS_FEATURE_PUSH
385-
oc_create_pushconf_resource(device_count);
386-
oc_create_pushreceiver_resource(device_count);
423+
oc_create_pushconf_resource(device);
424+
oc_create_pushreceiver_resource(device);
387425
#endif /* OC_HAS_FEATURE_PUSH */
426+
}
388427

389-
if (oc_connectivity_init(device_count, cfg.ports) < 0) {
428+
oc_device_info_t *
429+
oc_core_add_new_device(oc_add_new_device_t cfg)
430+
{
431+
int64_t new_index = core_increment_device_count();
432+
if (new_index < 0) {
433+
return NULL;
434+
}
435+
uint32_t device = (uint32_t)new_index;
436+
437+
core_update_device_data(device, cfg);
438+
oc_core_set_device_resources_at_index(device, cfg.uri, cfg.rt);
439+
440+
if (oc_connectivity_init(device, cfg.ports) < 0) {
390441
oc_abort("error initializing connectivity for device");
391442
}
392443

393-
return &g_oc_device_info[device_count];
444+
return &g_oc_device_info[device];
394445
}
395446

396447
bool
@@ -408,6 +459,61 @@ oc_core_get_device_index(oc_uuid_t di, size_t *device)
408459
return false;
409460
}
410461

462+
#ifdef OC_HAS_FEATURE_DEVICE_ADD
463+
464+
oc_device_info_t *
465+
oc_core_add_or_update_device_at_index(oc_add_new_device_t cfg, size_t index)
466+
{
467+
uint32_t device_count = OC_ATOMIC_LOAD32(g_device_count);
468+
469+
if (index > device_count) {
470+
OC_ERR("designated device index (%d) is bigger than current number of all "
471+
"devices",
472+
device_count);
473+
return NULL;
474+
}
475+
if (index < device_count) {
476+
OC_ERR("cannot replace existing device (%d)", device_count);
477+
return NULL;
478+
}
479+
480+
bool new_device = true;
481+
// follow normal procedure
482+
if (core_increment_device_count() < 0) {
483+
return NULL;
484+
}
485+
++device_count;
486+
core_update_device_data(index, cfg);
487+
488+
oc_core_set_device_resources_at_index(index, cfg.uri, cfg.rt);
489+
490+
#ifdef OC_HAS_FEATURE_PLGD_TIME
491+
// TODO: plgd time
492+
#endif /* OC_HAS_FEATURE_PLGD_TIME */
493+
494+
#ifdef OC_SECURITY
495+
oc_sec_svr_create_new_device(index, new_device);
496+
#endif /* OC_SECURITY */
497+
498+
#ifdef OC_SOFTWARE_UPDATE
499+
oc_swupdate_create_at_index(index, new_device);
500+
#endif /* OC_SOFTWARE_UPDATE */
501+
502+
#ifdef OC_SECURITY
503+
oc_sec_svr_init_new_device(index);
504+
#endif /* OC_SECURITY */
505+
506+
#ifdef OC_SOFTWARE_UPDATE
507+
OC_DBG("oc_core_add_or_update_device_at_index(): loading swupdate(%zu)",
508+
index);
509+
oc_swupdate_load(index);
510+
#endif /* OC_SOFTWARE_UPDATE */
511+
512+
return &g_oc_device_info[index];
513+
}
514+
515+
#endif /* OC_HAS_FEATURE_DEVICE_ADD */
516+
411517
static void
412518
oc_device_bind_rt(size_t device_index, const char *rt)
413519
{

api/oc_core_res_internal.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ void oc_core_shutdown(void);
5555
*/
5656
oc_device_info_t *oc_core_add_new_device(oc_add_new_device_t cfg);
5757

58+
#ifdef OC_HAS_FEATURE_DEVICE_ADD
59+
/**
60+
* @brief Add a new device or update an existing device at the position
61+
* designated by `index` of Device array (g_oc_device_info)
62+
*
63+
* @param cfg device configuration
64+
* @param index index of `g_oc_device_info[]`
65+
* @return oc_device_info_t* the device information
66+
*/
67+
oc_device_info_t *oc_core_add_or_update_device_at_index(oc_add_new_device_t cfg,
68+
size_t index);
69+
70+
#endif /* OC_HAS_FEATURE_DEVICE_ADD */
71+
5872
/**
5973
* @brief encode the interfaces with the cbor (payload) encoder
6074
*

0 commit comments

Comments
 (0)