[IOT-3284] IoTivity does not delete cloud account
[iotivity.git] / resource / csdk / security / provisioning / src / cloud / cloudresource.c
1 /* *****************************************************************
2  *
3  * Copyright 2018 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * *****************************************************************/
20
21 #include "iotivity_config.h"
22 #include "iotivity_debug.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <unistd.h>
27
28 #include "octypes.h"
29 #include "oic_malloc.h"
30 #include "utlist.h"
31 #include "experimental/logger.h"
32 #include "ocpayload.h"
33 #include "ocpayloadcbor.h"
34 #include "srmutility.h"
35 #include "psinterface.h"
36 #include "deviceonboardingstate.h"
37 #include "srmresourcestrings.h"
38 #include "resourcemanager.h"
39 #include "cloud/cloudresource.h"
40 #include "cloud/auth.h"
41 #include "oic_string.h"
42
43 #define TAG  "OIC_CLOUD_RESOURCE"
44
45 static OicCloud_t           *gCloud = NULL;
46 static OCResourceHandle     gCloudHandle = NULL;
47
48 static oc_mutex     gCloudMutex;
49
50 #define OC_CLOUD_PROVISIONING_APN   "apn"
51 #define OC_CLOUD_PROVISIONING_CIS   "cis"
52 #define OC_CLOUD_PROVISIONING_AT    "at"
53 #define OC_CLOUD_PROVISIONING_SID   "sid"
54 #define OC_CLOUD_PROVISIONING_CLEC  "clec"
55
56 static OicCloud_t gDefaultCloud =
57 {
58     NULL,
59     NULL,
60     NULL,
61     NULL,
62     NULL,
63     OC_CLOUD_OK,
64     NULL,
65     NULL,
66     NULL,
67     NULL,
68     false
69 };
70
71 static void DeleteCloudList(OicCloud_t *clouds, bool delete_after_signout)
72 {
73     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
74
75     OicCloud_t *p1 = NULL, *p2 = NULL;
76     LL_FOREACH_SAFE(clouds, p1, p2)
77     {
78         if (delete_after_signout)
79         {
80             LL_DELETE(clouds, p1);
81         }
82         p1->delete_after_signout = delete_after_signout;
83         OCCloudSignOut(p1);
84     }
85
86     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
87 }
88
89 void CloudsSignOut()
90 {
91     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
92
93     oc_mutex_lock(gCloudMutex);
94     if (!gCloud)
95     {
96         OIC_LOG_V(WARNING, TAG, "%s: cloud is NULL", __func__);
97         oc_mutex_unlock(gCloudMutex);
98         return;
99     }
100     DeleteCloudList(gCloud, false);
101     oc_mutex_unlock(gCloudMutex);
102
103     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
104 }
105
106 void ResetClouds()
107 {
108     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
109
110     oc_mutex_lock(gCloudMutex);
111     if (!gCloud)
112     {
113         OIC_LOG_V(WARNING, TAG, "%s: cloud is NULL", __func__);
114         oc_mutex_unlock(gCloudMutex);
115         return;
116     }
117     DeleteCloudList(gCloud, true);
118     gCloud = NULL;
119     oc_mutex_unlock(gCloudMutex);
120
121     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
122 }
123
124 void DeleteCloudAccount()
125 {
126     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
127
128     oc_mutex_lock(gCloudMutex);
129     if (!gCloud)
130     {
131         OIC_LOG_V(WARNING, TAG, "%s: cloud is NULL", __func__);
132         oc_mutex_unlock(gCloudMutex);
133         return;
134     }
135     OicCloud_t *p1 = NULL, *p2 = NULL;
136     LL_FOREACH_SAFE(gCloud, p1, p2)
137     {
138         LL_DELETE(gCloud, p1);
139         OCCloudDelete(p1);
140     }
141     gCloud = NULL;
142     oc_mutex_unlock(gCloudMutex);
143
144     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
145 }
146
147 static void *CloudWaitForRFNOP(void *data)
148 {
149     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
150     OicSecDostype_t dos;
151
152     OicCloud_t *cloud = (OicCloud_t *)data;
153     VERIFY_NOT_NULL(TAG, cloud, ERROR);
154
155     VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&dos), ERROR);
156
157     while (DOS_RFNOP != dos.state && OC_CLOUD_EXIT != cloud->stat)
158     {
159         VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&dos), ERROR);
160         sleep(1);
161     }
162
163     if (OC_STACK_OK != OCCloudSignUp(cloud))
164     {
165         OIC_LOG_V(ERROR, TAG, "%s: cloud sign up", __func__);
166     }
167 exit:
168     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
169     return NULL;
170 }
171
172 static OCEntityHandlerResult HandleCloudPostRequest(OCEntityHandlerRequest *ehRequest)
173 {
174     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
175     OCEntityHandlerResult ehRet = OC_EH_INTERNAL_SERVER_ERROR;
176     OicSecDostype_t dos;
177     OicCloud_t *newCloud = NULL;
178     OCRepPayload *payload = NULL;
179     bool isDeviceOwned = false;
180     OicCloud_t *xCloud = NULL;
181     char *ipv6End = NULL;
182     char *percentChar = NULL;
183     char *cis = NULL;
184     char *ipv6Intf = NULL;
185
186     VERIFY_NOT_NULL(TAG, ehRequest, ERROR);
187     VERIFY_NOT_NULL(TAG, ehRequest->payload, ERROR);
188
189     VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&dos), ERROR);
190
191     if (DOS_RFNOP != dos.state && DOS_RFPRO != dos.state)
192     {
193         OIC_LOG_V(ERROR, TAG, "%s %s resource is read-only in not RFNOP or DOS_RFPRO", __func__,
194                   OIC_RSRC_TYPE_SEC_CLOUDCONF);
195         ehRet = OC_EH_NOT_ACCEPTABLE;
196         goto exit;
197     }
198
199     OCGetDeviceOwnedState(&isDeviceOwned);
200
201     if (!isDeviceOwned)
202     {
203         OIC_LOG_V(ERROR, TAG, "%s: device is not owned", __func__);
204         ehRet = OC_EH_NOT_ACCEPTABLE;
205         goto exit;
206     }
207
208     newCloud = (OicCloud_t *) OICCalloc(1, sizeof(OicCloud_t));
209     VERIFY_NOT_NULL(TAG, newCloud, ERROR);
210
211     payload = (OCRepPayload *)ehRequest->payload;
212
213     if (!OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_APN, &newCloud->apn))
214     {
215         OIC_LOG_V(WARNING, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_APN);
216     }
217     if (!OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_CIS, &newCloud->cis))
218     {
219         OIC_LOG_V(ERROR, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_CIS);
220         goto exit;
221     }
222     if (!OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_AT, &newCloud->at))
223     {
224         OIC_LOG_V(ERROR, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_AT);
225         goto exit;
226     }
227     if (!OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_SID, &newCloud->sid))
228     {
229         OIC_LOG_V(ERROR, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_SID);
230         goto exit;
231     }
232
233     if (!ValidCloud(newCloud))
234     {
235         OIC_LOG_V(ERROR, TAG, "%s: Error validate the new cloud", __func__);
236         goto exit;
237     }
238
239     // find the IPv6 address end bracket
240     ipv6End = strchr(newCloud->cis, ']');
241     if (NULL != ipv6End)
242     {
243         ipv6Intf = strchr(newCloud->cis, '%');
244         if (ipv6Intf == NULL)
245         {
246             // find the interface name from UDP address of sender
247             percentChar = strchr(ehRequest->devAddr.addr, '%');
248             if (NULL != percentChar)
249             {
250                 size_t ifLen = strlen(percentChar);
251                 size_t addrLen = strlen(newCloud->cis);
252                 size_t cisLen = addrLen + ifLen + 3;
253
254                 // fill the cloud uri with interface name inserted
255                 cis = (char *)OICMalloc(sizeof(char) * cisLen);
256                 OICStrcpy(cis, ipv6End - newCloud->cis + 1, newCloud->cis);
257                 OICStrcat(cis, cisLen, "%25");
258                 OICStrcat(cis, cisLen, percentChar + 1);
259                 OICStrcat(cis, cisLen, ipv6End);
260
261                 OICFree(newCloud->cis);
262                 newCloud->cis = cis;
263             }
264         }
265     }
266
267     xCloud = CloudFind(gCloud, newCloud);
268     if (xCloud)
269     {
270         OIC_LOG_V(WARNING, TAG, "%s: cloud: %s exist", __func__, newCloud->cis);
271         if (OC_CLOUD_TOKEN_REFRESH0 < xCloud->stat)
272         {
273             if (!CloudCopy(newCloud, xCloud))
274             {
275                 OIC_LOG_V(WARNING, TAG, "%s: cloud: cannot update: %s", __func__, xCloud->cis);
276             }
277         }
278         else
279         {
280             OIC_LOG_V(WARNING, TAG, "%s: cloud: cannot update: %s status: %s", __func__, xCloud->cis,
281                       GetCloudStatus(xCloud));
282
283             FreeCloud(newCloud);
284             goto exit;
285         }
286     }
287
288     oc_mutex_lock(gCloudMutex);
289 #ifdef _MULTIPLE_CNC_
290     LL_APPEND(gCloud, newCloud);
291 #else
292     FreeCloud(gCloud);
293     gCloud = newCloud;
294 #endif
295     oc_mutex_unlock(gCloudMutex);
296
297     newCloud->stat = OC_CLOUD_PROV;
298
299
300     if (DOS_RFNOP == dos.state)
301     {
302         if (OC_STACK_OK != OCCloudSignUp(newCloud))
303         {
304             OIC_LOG_V(ERROR, TAG, "%s: cloud sign up", __func__);
305         }
306     }
307     else
308     {
309         OCThreadResult_t res = OC_THREAD_SUCCESS;
310         res = oc_thread_new(&newCloud->pid, CloudWaitForRFNOP, newCloud);
311         if (OC_THREAD_SUCCESS != res)
312         {
313             OIC_LOG_V(ERROR, TAG, "%s: create thread: %d", __func__, res);
314         }
315     }
316
317     ehRet = OC_EH_OK;
318 exit:
319     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
320             OC_EH_OK : OC_EH_ERROR;
321
322     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
323
324     return ehRet;
325 }
326
327 static int64_t  GetClec(const OicCloud_t *cloud)
328 {
329     OIC_LOG_V(DEBUG, TAG, "%s: %d", __func__, cloud->stat);
330
331     switch (cloud->stat)
332     {
333         case OC_CLOUD_OK:
334         case OC_CLOUD_PROV:
335         case OC_CLOUD_SIGNUP:
336         case OC_CLOUD_SIGNIN:
337         case OC_CLOUD_SIGNOUT:
338         case OC_CLOUD_TOKEN_REFRESH0:
339         case OC_CLOUD_TOKEN_REFRESH1:
340         case OC_CLOUD_TOKEN_REFRESH2:
341         case OC_CLOUD_TOKEN_REFRESH3:
342         case OC_CLOUD_TOKEN_REFRESH4:
343             return 0;
344         case OC_CLOUD_ERROR_INVALID_ACCESS_TOKEN:
345             return 3;
346         case OC_CLOUD_ERROR_UNREACHABLE:
347         case OC_CLOUD_ERROR_TLS:
348         case OC_CLOUD_ERROR_REDIRECT:
349             return 2;
350         case OC_CLOUD_ERROR_REFRESHTOKEN:
351             return 3;
352         case OC_CLOUD_ERROR_SIGNOUT:
353         case OC_CLOUD_ERROR_SIGNIN:
354         case OC_CLOUD_ERROR_CREATE_SESSION:
355         case OC_CLOUD_ERROR_CHECK_SESSION:
356         case OC_CLOUD_ERROR_SIGNUP:
357         case OC_CLOUD_ERROR:
358         case OC_CLOUD_EXIT:
359             return 1;
360     }
361     return 0;
362 }
363
364 OCRepPayload *CreateCloudGetPayload(const OicCloud_t *cloud)
365 {
366     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
367
368     OCRepPayload *payload = NULL;
369     payload = OCRepPayloadCreate();
370     VERIFY_NOT_NULL(TAG, payload, ERROR);
371
372     OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_DEFAULT);
373     OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_READ_WRITE);
374     OCRepPayloadAddResourceType(payload, OIC_RSRC_TYPE_SEC_CLOUDCONF);
375
376     if (NULL == cloud)
377     {
378         OIC_LOG_V(DEBUG, TAG, "%s: Create empty filled payload", __func__);
379
380         if (!OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_APN, ""))
381         {
382             OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_APN);
383         }
384         if (!OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_CIS, "coaps+tcp://127.0.0.1"))
385         {
386             OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_CIS);
387         }
388         if (!OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_SID, "00000000-0000-0000-0000-000000000000"))
389         {
390             OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_SID);
391         }
392         if (!OCRepPayloadSetPropInt(payload, OIC_JSON_CLOUD_CLEC, (int64_t)0))
393         {
394             OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_CLEC);
395         }
396     }
397     else
398     {
399         if (cloud->apn)
400         {
401             if (!OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_APN, cloud->apn))
402             {
403                 OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_APN);
404             }
405         }
406         if (!OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_CIS, cloud->cis))
407         {
408             OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_CIS);
409         }
410         if (!OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_SID, cloud->sid))
411         {
412             OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_SID);
413         }
414         if (!OCRepPayloadSetPropInt(payload, OIC_JSON_CLOUD_CLEC, GetClec(cloud)))
415         {
416             OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_CLEC);
417         }
418     }
419 exit:
420     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
421     return payload;
422 }
423
424 static OCEntityHandlerResult HandleCloudGetRequest(OCEntityHandlerRequest *ehRequest)
425 {
426     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
427     OCEntityHandlerResult ehRet = OC_EH_INTERNAL_SERVER_ERROR;
428     OicCloud_t *cloud = NULL;
429     OCRepPayload *payload = NULL;
430     bool isDeviceOwned = false;
431     OicCloud_t *p1 = NULL, *p2 = NULL;
432     OCEntityHandlerResponse response;
433
434     VERIFY_NOT_NULL(TAG, ehRequest, ERROR);
435
436     OCGetDeviceOwnedState(&isDeviceOwned);
437
438     if (!isDeviceOwned)
439     {
440         OIC_LOG_V(ERROR, TAG, "%s: device is not owned", __func__);
441         ehRet = OC_EH_NOT_ACCEPTABLE;
442         goto exit;
443     }
444
445     if (NULL == gCloud)
446     {
447         ehRet = OC_EH_OK;
448         goto exit;
449     }
450
451     cloud = (OicCloud_t *) OICCalloc(1, sizeof(OicCloud_t));
452     VERIFY_NOT_NULL(TAG, cloud, ERROR);
453
454     payload = (OCRepPayload *)ehRequest->payload;
455
456     if (!payload || !OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_CIS, &cloud->cis))
457     {
458         OIC_LOG_V(ERROR, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_CIS);
459         p1 = gCloud;
460         ehRet = OC_EH_OK;
461         goto exit;
462     }
463     if (!OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_APN, &cloud->apn))
464     {
465         OIC_LOG_V(WARNING, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_APN);
466     }
467     if (!OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_AT, &cloud->at))
468     {
469         OIC_LOG_V(WARNING, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_AT);
470     }
471
472     LL_FOREACH_SAFE(gCloud, p1, p2)
473     {
474         if (p1 && p1->cis && 0 == strcmp(p1->cis, cloud->cis))
475         {
476             ehRet = OC_EH_OK;
477             break;
478         }
479     }
480 exit:
481     response.requestHandle = ehRequest ? ehRequest->requestHandle : NULL;
482     response.payload = (OCPayload *)CreateCloudGetPayload(p1);
483     if (response.payload)
484     {
485         response.payload->type = PAYLOAD_TYPE_REPRESENTATION;
486     }
487     response.persistentBufferFlag = 0;
488
489     if (OC_STACK_OK != OCDoResponse(&response))
490     {
491         OIC_LOG_V(ERROR, TAG, "%s: send response", __func__);
492         ehRet = OC_EH_ERROR;
493     }
494
495     FreeCloud(cloud);
496
497     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
498
499     return ehRet;
500 }
501
502 static OCEntityHandlerResult HandleCloudDeleteRequest(OCEntityHandlerRequest *ehRequest)
503 {
504     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
505     OCEntityHandlerResult ehRet = OC_EH_INTERNAL_SERVER_ERROR;
506     OicCloud_t *cloud = NULL;
507     OCRepPayload *payload = NULL;
508     bool isDeviceOwned = false;
509     OicCloud_t *p1 = NULL, *p2 = NULL;
510     OCEntityHandlerResponse response;
511
512     VERIFY_NOT_NULL(TAG, ehRequest, ERROR);
513     VERIFY_NOT_NULL(TAG, ehRequest->payload, ERROR);
514
515     OCGetDeviceOwnedState(&isDeviceOwned);
516
517     if (!isDeviceOwned)
518     {
519         OIC_LOG_V(ERROR, TAG, "%s: device is not owned", __func__);
520         ehRet = OC_EH_NOT_ACCEPTABLE;
521         goto exit;
522     }
523
524     cloud = (OicCloud_t *) OICCalloc(1, sizeof(OicCloud_t));
525     VERIFY_NOT_NULL(TAG, cloud, ERROR);
526
527     payload = (OCRepPayload *)ehRequest->payload;
528
529     if (!cloud->cis || !OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_CIS, &cloud->cis))
530     {
531         OIC_LOG_V(ERROR, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_CIS);
532         goto exit;
533     }
534     if (!OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_APN, &cloud->apn))
535     {
536         OIC_LOG_V(ERROR, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_APN);
537     }
538     if (!OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_AT, &cloud->at))
539     {
540         OIC_LOG_V(ERROR, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_AT);
541     }
542
543     LL_FOREACH_SAFE(gCloud, p1, p2)
544     {
545         if (p1 && p1->cis && 0 == strcmp(p1->cis, cloud->cis))
546         {
547             OIC_LOG_V(INFO, TAG, "%s: delete cloud: %s", __func__, p1->cis);
548             p1->stat = OC_CLOUD_EXIT;
549             p1->delete_after_signout = true;
550             OCCloudSignOut(p1);
551             LL_DELETE(gCloud, p1);
552             ehRet = OC_EH_OK;
553             break;
554         }
555     }
556 exit:
557     response.requestHandle = ehRequest ? ehRequest->requestHandle : NULL;
558     response.ehResult = ehRet;
559     response.payload = (OCPayload *)OCRepPayloadCreate();
560     if (NULL != response.payload)
561     {
562         response.payload->type = PAYLOAD_TYPE_REPRESENTATION;
563         response.persistentBufferFlag = 0;
564         if (OC_STACK_OK != OCDoResponse(&response))
565         {
566             OIC_LOG_V(ERROR, TAG, "%s: send response", __func__);
567             ehRet = OC_EH_ERROR;
568         }
569     }
570     else
571     {
572         OIC_LOG_V(ERROR, TAG, "%s: response payload is NULL", __func__);
573         ehRet = OC_EH_ERROR;
574     }
575
576     if (cloud)
577     {
578         FreeCloud(cloud);
579     }
580
581     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
582
583     return ehRet;
584 }
585
586
587 OCEntityHandlerResult CloudEntityHandler(OCEntityHandlerFlag flag,
588         OCEntityHandlerRequest *ehRequest, void *callbackParam)
589 {
590     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
591
592     OC_UNUSED(callbackParam);
593
594     VERIFY_NOT_NULL_RETURN(TAG, ehRequest, ERROR, OC_EH_ERROR);
595
596     OCEntityHandlerResult ehRet = OC_EH_ERROR;
597
598     if (flag & OC_REQUEST_FLAG)
599     {
600         switch (ehRequest->method)
601         {
602             case OC_REST_POST:
603                 ehRet = HandleCloudPostRequest(ehRequest);
604                 break;
605             case OC_REST_GET:
606                 ehRet = HandleCloudGetRequest(ehRequest);
607                 break;
608             case OC_REST_DELETE:
609                 ehRet = HandleCloudDeleteRequest(ehRequest);
610                 break;
611             default:
612                 OIC_LOG_V(WARNING, TAG, "%s: Unknow request: %d", __func__, ehRequest->method);
613                 usleep(300000);
614                 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
615                         OC_EH_OK : OC_EH_ERROR;
616                 break;
617         }
618     }
619     else
620     {
621         OIC_LOG_V(WARNING, TAG, "%s: Flag  does not includes OC_REQUEST_FLAG", __func__);
622     }
623
624     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
625     return ehRet;
626 }
627
628 OCStackResult CreateCloudResource()
629 {
630     OCStackResult ret = OCCreateResource(&gCloudHandle,
631                                          OIC_RSRC_TYPE_SEC_CLOUDCONF,
632                                          OC_RSRVD_INTERFACE_DEFAULT,
633                                          OIC_RSRC_CLOUDCONF_URI,
634                                          CloudEntityHandler,
635                                          NULL,
636                                          OC_SECURE | OC_DISCOVERABLE);
637
638     if (OC_STACK_OK != ret)
639     {
640         OIC_LOG (FATAL, TAG, "Unable to create cloud config resource");
641         DeInitCloudResource();
642     }
643
644     ret = OCBindResourceInterfaceToResource(gCloudHandle, OC_RSRVD_INTERFACE_READ_WRITE);
645     if (ret != OC_STACK_OK)
646     {
647         OIC_LOG_V(ERROR, TAG, "Binding Resource interface with result: %d", ret);
648         return ret;
649     }
650
651     return ret;
652 }
653
654 OCStackResult DeInitCloudResource()
655 {
656     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
657
658     OCStackResult ret = OCDeleteResource(gCloudHandle);
659     if (gCloud  != &gDefaultCloud)
660     {
661         DeleteCloudList(gCloud, true);
662     }
663
664     oc_mutex_free(gCloudMutex);
665
666     gCloud = NULL;
667
668     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
669
670     if (OC_STACK_OK == ret)
671     {
672         return OC_STACK_OK;
673     }
674     else
675     {
676         return OC_STACK_ERROR;
677     }
678 }
679
680 static void StartClouds()
681 {
682     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
683     bool isDeviceOwned = false;
684
685     OCGetDeviceOwnedState(&isDeviceOwned);
686
687     if (!isDeviceOwned)
688     {
689         OIC_LOG_V(ERROR, TAG, "%s: device is not owned", __func__);
690         return;
691     }
692
693     OicCloud_t *p1 = NULL, *p2 = NULL;
694     LL_FOREACH_SAFE(gCloud, p1, p2)
695     {
696         if (OC_CLOUD_PROV == p1->stat)
697         {
698             if (OC_STACK_OK != OCCloudSignUp(p1))
699             {
700                 OIC_LOG_V(ERROR, TAG, "%s: cloud sign up", __func__);
701             }
702         }
703     }
704
705     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
706 }
707
708 OCStackResult InitCloudResource()
709 {
710     uint8_t *data = NULL;
711     size_t size = 0;
712
713     gCloudMutex = oc_mutex_new();
714
715     if (OC_STACK_OK != GetSecureVirtualDatabaseFromPS(OIC_JSON_CLOUDS_NAME, &data, &size))
716     {
717         OIC_LOG (WARNING, TAG, "There is no cloud data in database");
718     }
719     else
720     {
721         if (data)
722         {
723             oc_mutex_lock(gCloudMutex);
724             if (OC_STACK_OK != CBORPayloadToCloud(data, size, &gCloud))
725             {
726                 OIC_LOG (WARNING, TAG, "There is no cloud data in database");
727             }
728             else
729             {
730                 StartClouds();
731             }
732             oc_mutex_unlock(gCloudMutex);
733         }
734     }
735
736     return CreateCloudResource();
737 }
738
739 bool UpdateCloudPersistentStorage()
740 {
741     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
742
743     VERIFY_NOT_NULL_RETURN(TAG, gCloud, ERROR, false);
744
745     bool ret = false;
746     uint8_t *payload = NULL;
747     size_t size = 0;
748     oc_mutex_lock(gCloudMutex);
749     if (OC_STACK_OK != CloudToCBORPayload(gCloud, &payload, &size))
750     {
751         OIC_LOG_V(ERROR, TAG, "%s: cloud to cbor", __func__);
752         goto exit;
753     }
754
755     VERIFY_NOT_NULL(TAG, payload, ERROR);
756
757     if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CLOUDS_NAME, payload, size))
758     {
759         ret = true;
760     }
761
762     OICFree(payload);
763 exit:
764     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
765     oc_mutex_unlock(gCloudMutex);
766     return ret;
767 }