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
108118static 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
267296static 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
307344static 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
396447bool
@@ -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+
411517static void
412518oc_device_bind_rt (size_t device_index , const char * rt )
413519{
0 commit comments