[IOT-3022] cloud fix #2 95/24795/5
authorAleksey Volkov <a.volkov@samsung.com>
Tue, 24 Apr 2018 12:59:54 +0000 (15:59 +0300)
committerAleksey Volkov <a.volkov@samsung.com>
Wed, 16 May 2018 08:57:49 +0000 (08:57 +0000)
a) sample server justwork: added key press check
b) fixed apn check
c) signout in delete cloudconfig
d) delete cloud
e) use redirect uri
f) update cloud if not working
g) token refresh timeout

Change-Id: Iefe5e0d0c37359a5699f021364a0aa82e8799f68
Signed-off-by: Oleksandr Dmytrenko <o.dmytrenko@samsung.com>
Signed-off-by: Aleksey Volkov <a.volkov@samsung.com>
resource/csdk/security/provisioning/include/cloud/auth.h
resource/csdk/security/provisioning/include/cloud/cloudresource.h
resource/csdk/security/provisioning/sample/sampleserver_justworks.cpp
resource/csdk/security/provisioning/src/cloud/auth.c
resource/csdk/security/provisioning/src/cloud/cloudresource.c
resource/csdk/security/provisioning/unittest/cloudresource.cpp

index 45fe1b2..cfe8e97 100644 (file)
@@ -42,6 +42,11 @@ typedef enum
     OC_CLOUD_TOKEN_REFRESH3 = 8,
     OC_CLOUD_TOKEN_REFRESH4 = 9,
     /* Error codes */
+    OC_CLOUD_ERROR_REFRESHTOKEN = 244,
+    OC_CLOUD_ERROR_REDIRECT = 245,
+    OC_CLOUD_ERROR_TLS = 246,
+    OC_CLOUD_ERROR_INVALID_ACCESS_TOKEN = 247,
+    OC_CLOUD_ERROR_UNREACHABLE = 248,
     OC_CLOUD_ERROR_SIGNOUT = 249,
     OC_CLOUD_ERROR_SIGNIN = 250,
     OC_CLOUD_ERROR_CREATE_SESSION = 251,
@@ -58,9 +63,6 @@ typedef struct
     char        *refreshToken;
     long        expireSin;
     char        *uid;
-#if !defined(__MANDATORY__)
-    char        *redirectUri;
-#endif // __MANDATORY__
 } session_t;
 
 typedef struct OicCloud OicCloud_t;
@@ -75,6 +77,9 @@ struct OicCloud
     char        *cis;   // OCF Cloud URL
     char        *at;    // Access Token
     char        *sid;   // Cloud UUID
+#if !defined(__MANDATORY__)
+    char        *redirectUri;
+#endif // __MANDATORY__
     CloudStatus stat;
     oc_thread   pid;
     session_t   *session;
@@ -117,7 +122,7 @@ OCStackResult OCCloudSignOut(OicCloud_t *cloud);
  * @param[in] cloud
  * @return  OicCloud_t * pointer to next
  */
-OicCloud_t * FreeCloud(OicCloud_t *cloud);
+OicCloud_t *FreeCloud(OicCloud_t *cloud);
 
 /**
  * Cloud to CBOR
@@ -161,9 +166,9 @@ void *CloudStart(void *data);
  *
  * @param[in] cloud list
  * @param[in] cloud to find
- * @return  NULL
+ * @return  NULL if not find
  */
-bool CloudFind(OicCloud_t *list, const OicCloud_t *cloud);
+OicCloud_t *CloudFind(OicCloud_t *list, const OicCloud_t *cloud);
 
 /**
  * Cloud status
@@ -173,6 +178,30 @@ bool CloudFind(OicCloud_t *list, const OicCloud_t *cloud);
  */
 const char *GetCloudStatus(const OicCloud_t *cloud);
 
+/**
+ * Cloud validate
+ *
+ * @param[in] cloud
+ * @return bool true - Ok
+ */
+bool ValidCloud(OicCloud_t *cloud);
+
+/**
+ * Cloud delete
+ *
+ * @param[in] cloud
+ * @return  OCStackResult application result
+ */
+OCStackResult OCCloudDelete(OicCloud_t *cloud);
+
+/**
+ * Cloud copy
+ *
+ * @param[in] src cloud source
+ * @param[in] dst cloud destination
+ * @return bool true - Ok
+ */
+bool CloudCopy(const OicCloud_t *src, OicCloud_t *dst);
 
 #ifdef __cplusplus
 }
index fb6442d..fbb2c05 100644 (file)
@@ -55,6 +55,15 @@ OCStackResult CreateCloudResource();
 */
 bool UpdateCloudPersistentStorage();
 
+/**
+* SignOut clouds
+*/
+void StopClouds();
+/**
+* Delete clouds acount
+*/
+void DeleteCloudAccount();
+
 #ifdef __cplusplus
 }
 #endif
index a6d26ff..c82a39f 100644 (file)
@@ -424,6 +424,35 @@ FILE* server_fopen(const char *path, const char *mode)
     }
 }
 
+static int keyEvent(int *key)
+{
+#if defined(WITH_POSIX)
+    struct timeval tv;
+    fd_set fd;
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    FD_ZERO(&fd);
+    FD_SET(STDIN_FILENO, &fd);
+
+    select(STDIN_FILENO + 1, &fd, NULL, NULL, &tv);
+
+    if (FD_ISSET(STDIN_FILENO, &fd))
+    {
+        OIC_LOG_V(DEBUG, TAG, "%s: pressed key", __func__);
+        if (key != NULL)
+        {
+            *key = getchar();
+        }
+        return 1;
+    }
+#else
+    OC_UNUSED(key);
+#endif // WITH_POSIX
+    return 0;
+}
+
 int main(void)
 {
     struct timespec timeout;
@@ -466,6 +495,21 @@ int main(void)
             return 0;
         }
         nanosleep(&timeout, NULL);
+        int key = 0;
+        if (keyEvent(&key))
+        {
+            OIC_LOG_V(DEBUG, TAG, "pressed key: %d", key);
+#if defined(__WITH_TLS__) && defined(WITH_CLOUD)
+            if (111 == key)//o
+            {
+                StopClouds();
+            }
+            else if( 100 == key)//d
+            {
+                DeleteCloudAccount();
+            }
+#endif // __WITH_TLS__ && WITH_CLOUD
+        }
     }
 
     OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
index d219003..9e8ace7 100644 (file)
@@ -46,9 +46,7 @@
 
 #define LOGIN_OK 4
 
-static const int TIME_OUT_SHIFT = 3;
-
-#define CBOR_CLOUD_MAP_SIZE 4
+#define SESSION_CBOR_CLOUD_MAP_SIZE 3
 #define MAX_STR_LEN 2048
 
 const char *OIC_JSON_CLOUD_SESSION_ACCESS_TOKEN = "accesstoken";
@@ -56,10 +54,10 @@ const char *OIC_JSON_CLOUD_SESSION_REFRESH_TOKEN = "refreshtoken";
 const char *OIC_JSON_CLOUD_SESSION_UID = "uid";
 
 #if !defined(__MANDATORY__)
-#define SESSION_CBOR_CLOUD_MAP_SIZE 4
+#define CBOR_CLOUD_MAP_SIZE 5
 const char *OIC_JSON_CLOUD_SESSION_REDIRECT_URL = "redirecturl";
 #else
-#define SESSION_CBOR_CLOUD_MAP_SIZE 3
+#define CBOR_CLOUD_MAP_SIZE 4
 #endif // __MANDATORY__
 
 static const size_t CBOR_DEFAULT_SIZE = MAX_STR_LEN * (CBOR_CLOUD_MAP_SIZE +
@@ -88,10 +86,7 @@ void SessionFree(session_t *session)
     }
     OICFree(session->uid);
     session->uid = NULL;
-#if !defined(__MANDATORY__)
-    OICFree(session->redirectUri);
-    session->redirectUri = NULL;
-#endif // __MANDATORY__
+
     OICFree(session);
     session = NULL;
 }
@@ -126,16 +121,36 @@ OicCloud_t *FreeCloud(OicCloud_t *cloud)
 
     OicCloud_t *ret = cloud->next;
     cloud->next = NULL;
-    OICFree(cloud->apn);
-    cloud->apn = NULL;
-    OICFree(cloud->cis);
-    cloud->cis = NULL;
-    OICFree(cloud->at);
-    cloud->at = NULL;
-    OICFree(cloud->sid);
-    cloud->sid = NULL;
 
-    SessionFree(cloud->session);
+    if (cloud->apn)
+    {
+        OICFree(cloud->apn);
+        cloud->apn = NULL;
+    }
+    if (cloud->cis)
+    {
+        OICFree(cloud->cis);
+        cloud->cis = NULL;
+    }
+    if (cloud->at)
+    {
+        OICFree(cloud->at);
+        cloud->at = NULL;
+    }
+    if (cloud->sid)
+    {
+        OICFree(cloud->sid);
+        cloud->sid = NULL;
+    }
+    if (cloud->session)
+    {
+        SessionFree(cloud->session);
+        cloud->session = NULL;
+    }
+#if !defined(__MANDATORY__)
+    OICFree(cloud->redirectUri);
+    cloud->redirectUri = NULL;
+#endif // __MANDATORY__
 
     OICFree(cloud);
     cloud = NULL;
@@ -143,22 +158,52 @@ OicCloud_t *FreeCloud(OicCloud_t *cloud)
     return ret;
 }
 
-bool CloudFind(OicCloud_t *list, const OicCloud_t *cloud)
+bool strCopy(const char *src, char **dst)
 {
-    if (!list || !cloud || !cloud->cis)
+    if (!src || !dst)
+    {
+        return false;
+    }
+    OICFree(*dst);
+    size_t len = strlen(src) + 1;
+    *dst = (char *)OICCalloc(1, len);
+    if (*dst)
+    {
+        memcpy(*dst, src, len);
+        return true;
+    }
+    return false;
+}
+
+bool CloudCopy(const OicCloud_t *src, OicCloud_t *dst)
+{
+    if (!strCopy(src->apn, &dst->apn)
+        || !strCopy(src->cis, &dst->cis)
+        || !strCopy(src->at, &dst->at)
+        || !strCopy(src->sid, &dst->sid))
     {
         return false;
     }
 
+    return true;
+}
+
+OicCloud_t *CloudFind(OicCloud_t *list, const OicCloud_t *cloud)
+{
+    if (!list || !cloud || !cloud->cis)
+    {
+        return NULL;
+    }
+
     OicCloud_t *p1 = NULL, *p2 = NULL;
     LL_FOREACH_SAFE(list, p1, p2)
     {
         if (p1 && p1->cis && 0 == strcmp(p1->cis, cloud->cis))
         {
-            return true;
+            return p1;
         }
     }
-    return false;
+    return NULL;
 }
 
 
@@ -172,6 +217,42 @@ static size_t CloudsCount(const OicCloud_t *clouds)
     return size;
 }
 
+bool ValidCloud(OicCloud_t *cloud)
+{
+    OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+    VERIFY_NOT_NULL_RETURN(TAG, cloud, ERROR, false);
+
+    bool ret = true;
+
+    if (!cloud->apn)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: Authorization Provider Name validate: %s", __func__,
+                  cloud->apn ? cloud->apn : "NULL");
+        ret = false;
+    }
+    if (!cloud->cis || 0 != strncmp(cloud->cis, "coaps+tcp://", 11))
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: OCF Cloud URL validate: %s", __func__, cloud->cis ? cloud->cis : "NULL");
+        ret = false;
+    }
+    if (!cloud->at)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: Access token validate: %s", __func__, cloud->at ? cloud->at : "NULL");
+        ret = false;
+    }
+
+#if !defined(__MANDATORY__)
+    if (cloud->redirectUri && 0 != strncmp(cloud->redirectUri, "coaps+tcp://", 11))
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: OCF Redirect URI validate: %s", __func__,
+                  cloud->redirectUri ? cloud->redirectUri : "NULL");
+        ret = false;
+    }
+#endif // __MANDATORY__
+    OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+    return ret;
+}
+
 OCStackResult CloudSessionToCBORPayload(const session_t *session, CborEncoder *map)
 {
     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
@@ -202,17 +283,6 @@ OCStackResult CloudSessionToCBORPayload(const session_t *session, CborEncoder *m
     cborError = cbor_encode_text_string(map, session->uid, strnlen(session->uid, MAX_STR_LEN));
     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborError, "Failed add value: uid");
 
-#if !defined(__MANDATORY__)
-    if (session->redirectUri)
-    {
-        cbor_encode_text_string(map, OIC_JSON_CLOUD_SESSION_REDIRECT_URL,
-                            sizeof(OIC_JSON_CLOUD_SESSION_REDIRECT_URL) + 1);
-        VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborError, "Failed add tag: redirect uri");
-        cbor_encode_text_string(map, session->redirectUri, strnlen(session->redirectUri, MAX_STR_LEN));
-        VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborError, "Failed add value: redirect uri");
-    }
-#endif // __MANDATORY__
-
     ret = OC_STACK_OK;
 exit:
     if (CborNoError != cborError)
@@ -328,6 +398,14 @@ static OCStackResult CloudToCBORPayloadInternal(const OicCloud_t *clouds, uint8_
             }
         }
 
+#if !defined(__MANDATORY__)
+        cbor_encode_text_string(&map, OIC_JSON_CLOUD_SESSION_REDIRECT_URL,
+                                sizeof(OIC_JSON_CLOUD_SESSION_REDIRECT_URL) + 1);
+        VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborError, "Failed add tag: redirect uri");
+        cbor_encode_text_string(&map, cloud->redirectUri, strnlen(cloud->redirectUri, MAX_STR_LEN));
+        VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborError, "Failed add value: redirect uri");
+#endif // __MANDATORY__
+
         cborError = cbor_encoder_close_container(&cloudArray, &map);
         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborError, "Failed close cloud map");
 
@@ -520,7 +598,7 @@ OCStackResult CBORPayloadToCloud(const uint8_t *cborPayload, size_t size, OicClo
 #if !defined(__MANDATORY__)
                 else if (strncmp(name, OIC_JSON_CLOUD_SESSION_REDIRECT_URL, len)  == 0)
                 {
-                    cborError = cbor_value_dup_text_string(&map, &cloud->session->redirectUri, &len, NULL);
+                    cborError = cbor_value_dup_text_string(&map, &cloud->redirectUri, &len, NULL);
                     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborError, "Failed get redirect uri");
                     goto next;
                 }
@@ -630,6 +708,11 @@ OCStackResult OCCloudTokenRefresh(OicCloud_t *cloud)
     OCStackResult ret = OC_STACK_OK;
 
     VERIFY_NOT_NULL_RETURN(TAG, cloud, ERROR, OC_STACK_INVALID_PARAM);
+    if (OC_CLOUD_TOKEN_REFRESH4 < cloud->stat)
+    {
+        OIC_LOG_V(DEBUG, TAG, "%s: invalid cloud status: %s", __func__, GetCloudStatus(cloud));
+        return OC_STACK_INVALID_PARAM;
+    }
     VERIFY_NOT_NULL_RETURN(TAG, cloud->cis, ERROR, OC_STACK_INVALID_PARAM);
     VERIFY_NOT_NULL_RETURN(TAG, cloud->session, ERROR, OC_STACK_INVALID_PARAM);
     VERIFY_NOT_NULL_RETURN(TAG, cloud->session->uid, ERROR, OC_STACK_INVALID_PARAM);
@@ -675,24 +758,47 @@ static void *CloudTokenRefresh(void *data)
 {
     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
 
+    long ts_sec_eta = 0L;
+
+    struct timespec second =
+    {
+        .tv_sec  = 1L,
+        .tv_nsec = 0L
+    };
+
     OicCloud_t *cloud = (OicCloud_t *)data;
     VERIFY_NOT_NULL(TAG, cloud, ERROR);
+    VERIFY_NOT_NULL(TAG, cloud->session, ERROR);
 
     OIC_LOG_V(INFO, TAG, "%s: cloud(%s) refresh start", __func__, cloud->cis);
 
+    ts_sec_eta = cloud->session->expireSin;
     cloud->stat = OC_CLOUD_TOKEN_REFRESH0;
 
     while (OC_CLOUD_TOKEN_REFRESH4 > cloud->stat)
     {
-
-        long ts_nsec = cloud->session->expireSin - TIME_OUT_SHIFT;
-        if (2 < ts_nsec)
+        long ts_sec = ts_sec_eta;;
+        while (ts_sec--)
         {
-            ts_nsec = 1;
-        }
-        struct timespec timeout = {ts_nsec / 1000000000, ts_nsec % 1000000000};
+            nanosleep(&second, NULL);
+
+            VERIFY_NOT_NULL(TAG, cloud->session, ERROR);
+
+            if (cloud->session->expireSin != ts_sec_eta)
+            {
+                if (-1 == cloud->session->expireSin)
+                {
+                    OIC_LOG_V(DEBUG, TAG, "%s: cloud(%s) expireSin: -1", __func__, cloud->cis);
+                    goto exit;
+                }
+                ts_sec = ts_sec_eta = cloud->session->expireSin;
+            }
 
-        nanosleep(&timeout, NULL);
+            if (OC_CLOUD_TOKEN_REFRESH4 < cloud->stat)
+            {
+                break;
+            }
+        }
 
         if (OC_STACK_OK != OCCloudTokenRefresh(cloud))
         {
@@ -887,45 +993,46 @@ OCStackResult OCCloudSignOut(OicCloud_t *cloud)
 }
 
 /**
- * Session parse payload
+ * SignUp parse payload
  *
  * @param[in] payload
- * @param[in] session session data
- * @return  OCStackResult application result
+ * @param[out] pointer to cloud
+ * @return  bool: true if Ok
  */
-static bool SessionParsePayload(const OCRepPayload *payload, session_t *session)
+static bool CloudSignUpParsePayload(const OCRepPayload *payload, OicCloud_t *cloud)
 {
     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
     bool ret = true;
     VERIFY_NOT_NULL_RETURN(TAG, payload, ERROR, false);
-    VERIFY_NOT_NULL_RETURN(TAG, session, ERROR, false);
+    VERIFY_NOT_NULL_RETURN(TAG, cloud, ERROR, false);
+    VERIFY_NOT_NULL_RETURN(TAG, cloud->session, ERROR, false);
 
     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
-                                   &session->accessToken))
+                                   &cloud->session->accessToken))
     {
         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_ACCESS_TOKEN);
         ret = false;
     }
     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REFRESH_TOKEN,
-                                   &session->refreshToken))
+                                   &cloud->session->refreshToken))
     {
         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_REFRESH_TOKEN);
         ret = false;
     }
-    if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_EXPIRES_IN, &session->expireSin))
+    if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_EXPIRES_IN, &cloud->session->expireSin))
     {
         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_EXPIRES_IN);
         ret = false;
     }
     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_USER_UUID,
-                                   &session->uid))
+                                   &cloud->session->uid))
     {
         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_USER_UUID);
         ret = false;
     }
 #if !defined(__MANDATORY__)
     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REDIRECT_URI,
-                                   &session->redirectUri))
+                                   &cloud->redirectUri))
     {
         OIC_LOG_V(WARNING, TAG, "Can't get: %s", OC_RSRVD_REDIRECT_URI);
     }
@@ -934,6 +1041,35 @@ static bool SessionParsePayload(const OCRepPayload *payload, session_t *session)
     return ret;
 }
 
+/**
+ * Sends Delete request to cloud
+ *
+ * @param[in] ctx                    context
+ * @param[in] handle                 handle
+ * @param[in] response               response from peer
+ * @return  OCStackApplicationResult application result
+ */
+static OCStackApplicationResult handleCloudDeleteResponse(void *ctx,
+        OCDoHandle handle,
+        OCClientResponse *response)
+{
+    OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+
+    OC_UNUSED(handle);
+    OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
+    OicCloud_t *cloud = (OicCloud_t *)ctx;
+
+    VERIFY_NOT_NULL_RETURN(TAG, response, ERROR, OC_STACK_DELETE_TRANSACTION);
+    VERIFY_NOT_NULL_RETURN(TAG, cloud, ERROR, OC_STACK_DELETE_TRANSACTION);
+    VERIFY_NOT_NULL_RETURN(TAG, cloud->session, ERROR, OC_STACK_DELETE_TRANSACTION);
+
+    OIC_LOG_V(ERROR, TAG, "%s: response result: %d", __func__, response->result);
+
+    cloud->stat = OC_CLOUD_EXIT;
+
+    OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+    return ret;
+}
 /**
  * Sends Sign Up request to cloud
  *
@@ -983,7 +1119,7 @@ static OCStackApplicationResult handleCloudSignUpResponse(void *ctx,
 
     VERIFY_NOT_NULL_RETURN(TAG, cloud->session, ERROR, OC_STACK_DELETE_TRANSACTION);
 
-    if (!SessionParsePayload((OCRepPayload *)response->payload, cloud->session))
+    if (!CloudSignUpParsePayload((OCRepPayload *)response->payload, cloud))
     {
         OIC_LOG_V(ERROR, TAG, "%s: parse payload", __func__);
         SessionFree(cloud->session);
@@ -991,6 +1127,34 @@ static OCStackApplicationResult handleCloudSignUpResponse(void *ctx,
         goto exit;
     }
 
+#if !defined(__MANDATORY__)
+    if (cloud->redirectUri)
+    {
+        OIC_LOG_V(WARNING, TAG, "%s: redirect to: %s", __func__, cloud->redirectUri);
+
+        if (ValidCloud(cloud))
+        {
+            strCopy(cloud->redirectUri, &cloud->cis);
+
+            OICFree(cloud->redirectUri);
+            cloud->redirectUri = NULL;
+
+            SessionFree(cloud->session);
+
+            cloud->stat = OC_CLOUD_PROV;
+
+            if (OC_STACK_OK != OCCloudSignUp(cloud))
+            {
+                OIC_LOG_V(ERROR, TAG, "%s: cloud sign up", __func__);
+            }
+            goto exit;
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: cannot redirect", __func__);
+        }
+    }
+#endif // __MANDATORY__
     OIC_LOG_V(INFO, TAG, "%s: Sign Up OK", __func__);
     OCCloudSignIn(cloud);
 exit:
@@ -998,7 +1162,7 @@ exit:
     return ret;
 }
 
-OCStackResult OCCloudSignUp(OicCloud_t *cloud)
+static OCStackResult OCCloudAccountResource(OicCloud_t *cloud, OCMethod method)
 {
     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
 
@@ -1016,34 +1180,53 @@ OCStackResult OCCloudSignUp(OicCloud_t *cloud)
         return OC_STACK_ERROR;
     }
 
+    if (OC_REST_POST != method && OC_REST_DELETE != method)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s: unsupported method: %d", __func__, method);
+        return OC_STACK_ERROR;
+    }
+
     char *deviceId = getDeviceId();
     VERIFY_NON_NULL_RET(deviceId, TAG, "Can't get the device id", OC_STACK_ERROR);
 
     snprintf(uri, MAX_URI_LENGTH, "%s%s", cloud->cis, OC_RSRVD_ACCOUNT_URI);
 
+    OCCallbackData cbData =
+    {
+        .context = (void *)cloud,
+        .cb = NULL,
+        .cd = NULL
+    };
+
     OCRepPayload *payload = OCRepPayloadCreate();
     VERIFY_NON_NULL_RET(payload, TAG, "Failed to allocate payload", OC_STACK_NO_MEMORY);
 
     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
-#if !defined(__MANDATORY__)
-    if (cloud->apn)
+    OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN, cloud->at);
+
+    if (OC_REST_POST == method)
     {
-        OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHPROVIDER, cloud->apn);
-    }
+#if !defined(__MANDATORY__)
+        if (cloud->apn)
+        {
+            VERIFY_NOT_NULL_RETURN(TAG, cloud->apn, ERROR, OC_STACK_INVALID_PARAM);
+            OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHPROVIDER, cloud->apn);
+        }
 #endif // __MANDATORY__
-    OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN, cloud->at);
-    OCRepPayloadSetPropString(payload, OC_RSRVD_SUBJECT_ID, cloud->sid);
+        OCRepPayloadSetPropString(payload, OC_RSRVD_SUBJECT_ID, cloud->sid);
 
-    OCCallbackData cbData =
+        cbData.cb = handleCloudSignUpResponse;
+
+        cloud->stat = OC_CLOUD_SIGNUP;
+    }
+    else
     {
-        .context = (void *)cloud,
-        .cb = handleCloudSignUpResponse,
-        .cd = NULL
-    };
+        cloud->stat = OC_CLOUD_EXIT;
 
-    cloud->stat = OC_CLOUD_SIGNUP;
+        cbData.cb = handleCloudDeleteResponse;
+    }
 
-    ret = OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
+    ret = OCDoResource(NULL, method, uri, NULL, (OCPayload *)payload,
                        CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
 
     OIC_LOG_V(INFO, TAG, "%s: cloud(%s) sign in", __func__, cloud->cis);
@@ -1055,6 +1238,26 @@ OCStackResult OCCloudSignUp(OicCloud_t *cloud)
     return ret;
 }
 
+OCStackResult OCCloudSignUp(OicCloud_t *cloud)
+{
+    OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+
+    OCStackResult ret = OCCloudAccountResource(cloud, OC_REST_POST);
+
+    OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+    return ret;
+}
+
+OCStackResult OCCloudDelete(OicCloud_t *cloud)
+{
+    OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
+
+    OCStackResult ret = OCCloudAccountResource(cloud, OC_REST_DELETE);
+
+    OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
+    return ret;
+}
+
 const char *GetCloudStatus(const OicCloud_t *cloud)
 {
     switch (cloud->stat)
index 53be093..74a6126 100644 (file)
@@ -50,9 +50,11 @@ static oc_mutex     gCloudMutex;
 #define OC_CLOUD_PROVISIONING_CIS   "cis"
 #define OC_CLOUD_PROVISIONING_AT    "at"
 #define OC_CLOUD_PROVISIONING_SID   "sid"
+#define OC_CLOUD_PROVISIONING_CLEC  "clec"
 
 static OicCloud_t gDefaultCloud =
 {
+    NULL,
     NULL,
     NULL,
     NULL,
@@ -63,53 +65,44 @@ static OicCloud_t gDefaultCloud =
     NULL
 };
 
-static bool ValidCloud(OicCloud_t *cloud)
+static void DeleteCloudList(OicCloud_t *clouds)
 {
     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
-    VERIFY_NOT_NULL_RETURN(TAG, cloud, ERROR, false);
-
-    bool ret = true;
 
-    if (!cloud->apn)
-    {
-        OIC_LOG_V(ERROR, TAG, "%s: Authorization Provider Name validate: %s", __func__,
-                  cloud->apn ? cloud->apn : "NULL");
-        ret = false;
-    }
-    if (!cloud->cis || 0 != strncmp(cloud->cis, "coaps+tcp://", 11))
+    if (!clouds)
     {
-        OIC_LOG_V(ERROR, TAG, "%s: OCF Cloud URL validate: %s", __func__, cloud->cis ? cloud->cis : "NULL");
-        ret = false;
+        OIC_LOG_V(WARNING, TAG, "%s: cloud is NULL", __func__);
+        return;
     }
-    if (!cloud->at)
+
+    OicCloud_t *p1 = NULL, *p2 = NULL;
+    oc_mutex_lock(gCloudMutex);
+    LL_FOREACH_SAFE(clouds, p1, p2)
     {
-        OIC_LOG_V(ERROR, TAG, "%s: Access token validate: %s", __func__, cloud->at ? cloud->at : "NULL");
-        ret = false;
+        OCCloudSignOut(p1);
+        LL_DELETE(clouds, p1);
+        p1 = NULL;
     }
+    oc_mutex_unlock(gCloudMutex);
 
     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
-    return ret;
 }
 
-static void DeleteCloudList(OicCloud_t *clouds)
+void StopClouds()
 {
-    OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
-    if (!clouds)
+    DeleteCloudList(gCloud);
+}
+
+void DeleteCloudAccount()
+{
+    if ( OC_STACK_OK != OCCloudDelete(gCloud))
     {
-        OIC_LOG_V(WARNING, TAG, "%s: cloud is NULL", __func__);
+        OIC_LOG_V(ERROR, TAG, "%s: cannot delete cloud", __func__);
     }
     else
     {
-        oc_mutex_lock(gCloudMutex);
-        OicCloud_t *p1 = clouds->next;
-        while(p1)
-        {
-            p1 = FreeCloud(p1);
-        }
-        FreeCloud(clouds);
-        oc_mutex_unlock(gCloudMutex);
+        OIC_LOG_V(ERROR, TAG, "%s: cloud is deleted", __func__);
     }
-    OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
 }
 
 static void *CloudWaitForRFNOP(void *data)
@@ -145,6 +138,7 @@ static OCEntityHandlerResult HandleCloudPostRequest(OCEntityHandlerRequest *ehRe
     OicCloud_t *newCloud = NULL;
     OCRepPayload *payload = NULL;
     bool isDeviceOwned = false;
+    OicCloud_t *xcloud = NULL;
 
     VERIFY_NOT_NULL(TAG, ehRequest, ERROR);
     VERIFY_NOT_NULL(TAG, ehRequest->payload, ERROR);
@@ -199,9 +193,23 @@ static OCEntityHandlerResult HandleCloudPostRequest(OCEntityHandlerRequest *ehRe
         goto exit;
     }
 
-    if (CloudFind(gCloud, newCloud))
+    xcloud = CloudFind(gCloud, newCloud);
+    if (xcloud)
     {
-        OIC_LOG_V(ERROR, TAG, "%s: cloud: %s exist", __func__, newCloud->cis);
+        OIC_LOG_V(WARNING, TAG, "%s: cloud: %s exist", __func__, newCloud->cis);
+        if (OC_CLOUD_TOKEN_REFRESH0 < xcloud->stat)
+        {
+            if (!CloudCopy(newCloud, xcloud))
+            {
+                OIC_LOG_V(WARNING, TAG, "%s: cloud: cannot update: %s", __func__, xcloud->cis);
+            }
+        }
+        else
+        {
+            OIC_LOG_V(WARNING, TAG, "%s: cloud: cannot update: %s status: %s", __func__, xcloud->cis,
+                      GetCloudStatus(xcloud));
+        }
+        FreeCloud(newCloud);
         goto exit;
     }
 
@@ -238,6 +246,41 @@ exit:
     return ehRet;
 }
 
+static int64_t  GetClec(const OicCloud_t *cloud)
+{
+    switch (cloud->stat)
+    {
+        case OC_CLOUD_OK:
+        case OC_CLOUD_PROV:
+        case OC_CLOUD_SIGNUP:
+        case OC_CLOUD_SIGNIN:
+        case OC_CLOUD_SIGNOUT:
+        case OC_CLOUD_TOKEN_REFRESH0:
+        case OC_CLOUD_TOKEN_REFRESH1:
+        case OC_CLOUD_TOKEN_REFRESH2:
+        case OC_CLOUD_TOKEN_REFRESH3:
+        case OC_CLOUD_TOKEN_REFRESH4:
+            return 0;
+        case OC_CLOUD_ERROR_INVALID_ACCESS_TOKEN:
+            return 1;
+        case OC_CLOUD_ERROR_UNREACHABLE:
+        case OC_CLOUD_ERROR_TLS:
+        case OC_CLOUD_ERROR_REDIRECT:
+            return 2;
+        case OC_CLOUD_ERROR_REFRESHTOKEN:
+            return 3;
+        case OC_CLOUD_ERROR_SIGNOUT:
+        case OC_CLOUD_ERROR_SIGNIN:
+        case OC_CLOUD_ERROR_CREATE_SESSION:
+        case OC_CLOUD_ERROR_CHECK_SESSION:
+        case OC_CLOUD_ERROR_SIGNUP:
+        case OC_CLOUD_ERROR:
+        case OC_CLOUD_EXIT:
+            return 4;
+    }
+    return 0;
+}
+
 OCRepPayload *CreateCloudGetPayload(const OicCloud_t *cloud)
 {
     OIC_LOG_V(DEBUG, TAG, "%s: IN", __func__);
@@ -259,12 +302,23 @@ OCRepPayload *CreateCloudGetPayload(const OicCloud_t *cloud)
     }
     else
     {
-        OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_APN, cloud->apn);
-        OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_CIS, cloud->cis);
-        OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_SID, cloud->sid);
-        OCRepPayloadSetPropInt(payload, OIC_JSON_CLOUD_CLEC, (int64_t)cloud->stat);
+        if (OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_APN, cloud->apn))
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_APN);
+        }
+        if (OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_CIS, cloud->cis))
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_CIS);
+        }
+        if (!OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_SID, cloud->sid))
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_SID);
+        }
+        if (!OCRepPayloadSetPropInt(payload, OIC_JSON_CLOUD_CLEC, GetClec(cloud)))
+        {
+            OIC_LOG_V(ERROR, TAG, "%s: Can't set: %s", __func__, OC_CLOUD_PROVISIONING_SID);
+        }
     }
-
 exit:
     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
     return payload;
@@ -302,7 +356,7 @@ static OCEntityHandlerResult HandleCloudGetRequest(OCEntityHandlerRequest *ehReq
 
     payload = (OCRepPayload *)ehRequest->payload;
 
-    if (!payload || !cloud->cis || !OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_CIS, &cloud->cis))
+    if (!payload || !OCRepPayloadGetPropString(payload, OC_CLOUD_PROVISIONING_CIS, &cloud->cis))
     {
         OIC_LOG_V(ERROR, TAG, "%s: Can't get: %s", __func__, OC_CLOUD_PROVISIONING_CIS);
         p1 = gCloud;
@@ -339,7 +393,6 @@ exit:
         ehRet = OC_EH_ERROR;
     }
 
-    OCPayloadDestroy((OCPayload *)response.payload);
     FreeCloud(cloud);
 
     OIC_LOG_V(DEBUG, TAG, "%s: OUT", __func__);
@@ -394,8 +447,8 @@ static OCEntityHandlerResult HandleCloudDeleteRequest(OCEntityHandlerRequest *eh
         {
             OIC_LOG_V(INFO, TAG, "%s: delete cloud: %s", __func__, p1->cis);
             p1->stat = OC_CLOUD_EXIT;
+            OCCloudSignOut(p1);
             LL_DELETE(gCloud, p1);
-            FreeCloud(p1);
             ehRet = OC_EH_OK;
             break;
         }
index 82b61aa..94e66b0 100644 (file)
@@ -71,16 +71,12 @@ void sessionInit(session_t *ses)
     ses->accessToken = (char *)OICCalloc(STR_LEN, sizeof(char));
     ses->refreshToken = (char *)OICCalloc(STR_LEN, sizeof(char));
     ses->uid = (char *)OICCalloc(STR_LEN, sizeof(char));
-#if !defined(__MANDATORY__)
-    ses->redirectUri = (char *)OICCalloc(STR_LEN, sizeof(char));
-    snprintf(ses->redirectUri, STR_LEN, "coaps+tcp://127.0.0.1:80");
-#endif // __MANDATORY__
     for (int i = 0; i < STR_LEN; i++)
     {
         ses->accessToken[i] = sample[rand() % STR_LEN];
         ses->refreshToken[i] = sample[rand() % STR_LEN];
         ses->uid[i] = sample[rand() % STR_LEN];
-   }
+    }
 }
 
 OicCloud_t *getCloud()
@@ -94,6 +90,10 @@ OicCloud_t *getCloud()
     cloud->cis = (char *)OICCalloc(STR_LEN, sizeof(char));
     cloud->at = (char *)OICCalloc(STR_LEN, sizeof(char));
     cloud->sid = (char *)OICCalloc(STR_LEN, sizeof(char));
+#if !defined(__MANDATORY__)
+    cloud->redirectUri = (char *)OICCalloc(STR_LEN, sizeof(char));
+    snprintf(cloud->redirectUri, STR_LEN, "coaps+tcp://127.0.0.1:80");
+#endif // __MANDATORY__
 
     for (int i = 0; i < STR_LEN; i++)
     {
@@ -231,7 +231,7 @@ TEST(CloudResourceTest, CBORPayloadToCloudFULL)
         ASSERT_STREQ(cloudX->session->refreshToken, cloud->session->refreshToken);
         ASSERT_STREQ(cloudX->session->uid, cloud->session->uid);
 #if !defined(__MANDATORY__)
-        ASSERT_STREQ(cloudX->session->redirectUri, cloud->session->redirectUri);
+        ASSERT_STREQ(cloudX->redirectUri, cloud->redirectUri);
 #endif // __MANDATORY__
     }
 
@@ -240,6 +240,26 @@ TEST(CloudResourceTest, CBORPayloadToCloudFULL)
     OCPayloadDestroy((OCPayload *)payload);
 }
 
+TEST(CloudResourceTest, strCopyFULL)
+{
+    EXPECT_FALSE(strCopy(NULL, NULL));
+    char *sample1 = (char *)OICCalloc(1, 1024);
+    EXPECT_TRUE(NULL != sample1);
+    snprintf(sample1, 1024, "sample1 test string");
+    char *dst = (char *)OICCalloc(1, 1024);
+    EXPECT_TRUE(strCopy(sample1, &dst));
+    EXPECT_TRUE(NULL != dst);
+    ASSERT_STREQ(sample1, dst);
+    OICFree(dst);
+    dst = NULL;
+    EXPECT_TRUE(strCopy(sample1, &dst));
+    EXPECT_TRUE(NULL != dst);
+    ASSERT_STREQ(sample1, dst);
+    OICFree(dst);
+
+    OICFree(sample1);
+}
+
 TEST(CloudResourceTest, CBORPayloadToCloudResourceFULL)
 {
     OicCloud_t *cloud =  getCloud();
@@ -266,6 +286,7 @@ TEST(CloudResourceTest, ValidCloudFULL)
     OicCloud_t *cloud =  getCloud();
     ASSERT_TRUE(false == ValidCloud(cloud));
     sprintf(cloud->cis, "coaps+tcp://");
+    sprintf(cloud->redirectUri, "coaps+tcp://");
     ASSERT_TRUE(true == ValidCloud(cloud));
     OICFree(cloud->apn); cloud->apn = NULL;
     OICFree(cloud->at); cloud->at = NULL;
@@ -358,7 +379,8 @@ TEST(CloudResourceTest, HandleCloudPostRequestFULL)
     ASSERT_TRUE(NULL != payload);
     ehRequest->payload = (OCPayload *)payload;
 
-    sprintf(cloud->cis, "coaps+tcp://");
+    sprintf(cloud->cis, "coaps+tcp://192.168.1.1:90");
+    sprintf(cloud->redirectUri, "coaps+tcp://192.168.1.1:91");
     ASSERT_TRUE(OC_EH_ERROR == HandleCloudPostRequest(ehRequest));
     OCRepPayloadSetPropString(payload, OIC_JSON_CLOUD_APN, cloud->apn);
     ASSERT_TRUE(OC_EH_ERROR == HandleCloudPostRequest(ehRequest));
@@ -376,6 +398,7 @@ TEST(CloudResourceTest, HandleCloudPostRequestFULL)
     ASSERT_TRUE(OC_STACK_OK == SetDosState(DOS_RFNOP));
     OCPayloadDestroy(ehRequest->payload);
     OICFree(ehRequest);
+    exit(0);
 }
 
 TEST(CloudResourceTest, HandleCloudGetRequestFULL)
@@ -761,7 +784,7 @@ TEST(CloudResourceTest, handleCloudSignUpResponseFULL)
     OCRepPayloadSetPropString((OCRepPayload *)response->payload, OC_RSRVD_USER_UUID,
                               cloud->session->uid);
     OCRepPayloadSetPropString((OCRepPayload *)response->payload, OC_RSRVD_REDIRECT_URI,
-                              cloud->session->redirectUri);
+                              cloud->redirectUri);
     SessionFree(cloud->session);
     cloud->session = NULL;
     ASSERT_TRUE(OC_STACK_DELETE_TRANSACTION == handleCloudSignUpResponse(ctx, handle, response));
@@ -814,7 +837,7 @@ TEST(CloudResourceTest, handleCloudSignInResponseFULL)
     OCRepPayloadSetPropString((OCRepPayload *)response->payload, OC_RSRVD_USER_UUID,
                               cloud->session->uid);
     OCRepPayloadSetPropString((OCRepPayload *)response->payload, OC_RSRVD_REDIRECT_URI,
-                              cloud->session->redirectUri);
+                              cloud->redirectUri);
 
     ASSERT_TRUE(OC_STACK_DELETE_TRANSACTION == handleCloudSignInResponse(ctx, handle, response));
 
@@ -837,52 +860,74 @@ TEST(CloudResourceTest, CloudSignFULL)
     FreeCloud(cloud);
 }
 
-
-TEST(CloudResourceTest, SessionParsePayloadFULL)
+TEST(CloudResourceTest, CloudSignUpParsePayloadFULL)
 {
-    OicCloud_t *cloud = getCloud();
-    session_t *session = NULL;
-    OCRepPayload *payload = OCRepPayloadCreate();
-    ASSERT_TRUE(!SessionParsePayload(payload, session));
-    session = (session_t *)OICCalloc(1, sizeof(session_t));
-    ASSERT_TRUE(NULL != session);
-
-    ASSERT_TRUE(!SessionParsePayload(payload, session));
-    SessionFree(session);
-    session = (session_t *)OICCalloc(1, sizeof(session_t));
-    OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
-                              cloud->session->accessToken);
-    ASSERT_TRUE(!SessionParsePayload(payload, session));
-    SessionFree(session);
-    session = (session_t *)OICCalloc(1, sizeof(session_t));
-    OCRepPayloadSetPropString(payload, OC_RSRVD_REFRESH_TOKEN,
-                              cloud->session->refreshToken);
-    ASSERT_TRUE(!SessionParsePayload(payload, session));
-    SessionFree(session);
-    session = (session_t *)OICCalloc(1, sizeof(session_t));
-    OCRepPayloadSetPropInt(payload, OC_RSRVD_EXPIRES_IN,
-                           cloud->session->expireSin);
-    ASSERT_TRUE(!SessionParsePayload(payload, session));
-    SessionFree(session);
-    session = (session_t *)OICCalloc(1, sizeof(session_t));
-    OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID,
-                              cloud->session->uid);
-    ASSERT_TRUE(SessionParsePayload(payload, session));
-    SessionFree(session);
-    session = (session_t *)OICCalloc(1, sizeof(session_t));
-    OCRepPayloadSetPropString(payload, OC_RSRVD_REDIRECT_URI,
-                              cloud->session->redirectUri);
+    OicCloud_t *cloud = NULL;
+    OCRepPayload *payload = NULL;
+
+    ASSERT_FALSE(CloudSignUpParsePayload(NULL, NULL));
+
+    payload = OCRepPayloadCreate();
+    ASSERT_TRUE(NULL != payload);
+
+    cloud = (OicCloud_t *)OICCalloc(1, sizeof(OicCloud_t));
+    ASSERT_TRUE(NULL != cloud);
+    cloud->session = (session_t *)OICCalloc(1, sizeof(session_t));
+    ASSERT_TRUE(NULL != cloud->session);
+
+    ASSERT_FALSE(CloudSignUpParsePayload(payload, cloud));
+    FreeCloud(cloud);
+    cloud = (OicCloud_t *)OICCalloc(1, sizeof(OicCloud_t));
+    ASSERT_TRUE(NULL != cloud);
+    cloud->session = (session_t *)OICCalloc(1, sizeof(session_t));
+    ASSERT_TRUE(NULL != cloud->session);
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN, OC_RSRVD_ACCESS_TOKEN);
+    ASSERT_FALSE(CloudSignUpParsePayload(payload, cloud));
+    ASSERT_TRUE(NULL != cloud->session->accessToken);
+    FreeCloud(cloud);
+    cloud = (OicCloud_t *)OICCalloc(1, sizeof(OicCloud_t));
+    ASSERT_TRUE(NULL != cloud);
+    cloud->session = (session_t *)OICCalloc(1, sizeof(session_t));
+    ASSERT_TRUE(NULL != cloud->session);
 
-    ASSERT_TRUE(SessionParsePayload(payload, session));
-    SessionFree(session);
-    session = (session_t *)OICCalloc(1, sizeof(session_t));
+    OCRepPayloadSetPropString(payload, OC_RSRVD_REFRESH_TOKEN, OC_RSRVD_REFRESH_TOKEN);
+    ASSERT_FALSE(CloudSignUpParsePayload(payload, cloud));
+    ASSERT_TRUE(NULL != cloud);
+    FreeCloud(cloud);
+    cloud = (OicCloud_t *)OICCalloc(1, sizeof(OicCloud_t));
+    ASSERT_TRUE(NULL != cloud);
+    cloud->session = (session_t *)OICCalloc(1, sizeof(session_t));
+    ASSERT_TRUE(NULL != cloud->session);
+
+    OCRepPayloadSetPropInt(payload, OC_RSRVD_EXPIRES_IN, 10);
+    ASSERT_FALSE(CloudSignUpParsePayload(payload, cloud));
+    ASSERT_TRUE(NULL != cloud);
+    FreeCloud(cloud);
+    cloud = (OicCloud_t *)OICCalloc(1, sizeof(OicCloud_t));
+    ASSERT_TRUE(NULL != cloud);
+    cloud->session = (session_t *)OICCalloc(1, sizeof(session_t));
+    ASSERT_TRUE(NULL != cloud->session);
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, OC_RSRVD_USER_UUID);
+    ASSERT_TRUE(CloudSignUpParsePayload(payload, cloud));
+    ASSERT_TRUE(NULL != cloud);
+    FreeCloud(cloud);
+    cloud = (OicCloud_t *)OICCalloc(1, sizeof(OicCloud_t));
+    ASSERT_TRUE(NULL != cloud);
+    cloud->session = (session_t *)OICCalloc(1, sizeof(session_t));
+    ASSERT_TRUE(NULL != cloud->session);
+
+
+    OCRepPayloadSetPropString(payload, OC_RSRVD_REDIRECT_URI,
+                              cloud->redirectUri);
+    ASSERT_TRUE(CloudSignUpParsePayload(payload, cloud));
+    ASSERT_TRUE(NULL != cloud);
 
-    SessionFree(session);
     OCPayloadDestroy((OCPayload *)payload);
     FreeCloud(cloud);
 }
 
-
 TEST(CloudResourceTest, handleCloudSignOutResponseFULL)
 {
     void *ctx = NULL;
@@ -901,7 +946,6 @@ TEST(CloudResourceTest, handleCloudSignOutResponseFULL)
 
     OCPayloadDestroy((OCPayload *)response->payload);
     OICFree(response);
-    FreeCloud(cloud);
 }
 
 TEST(CloudResourceTest, UpdateCloudPersistentStorageFULL)