Skip to content

Commit

Permalink
cloud: add oc_cloud_manager_stop_v1 function
Browse files Browse the repository at this point in the history
The function enables the caller to stop the cloud manager, but
without clearing the cloud configuration.
  • Loading branch information
Danielius1922 committed Apr 15, 2024
1 parent 953fc15 commit d7089cf
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 16 deletions.
50 changes: 36 additions & 14 deletions api/cloud/oc_cloud.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,7 @@ start_manager(void *user_data)
static void
cloud_manager_restart(oc_cloud_context_t *ctx)
{
if (!ctx->cloud_manager) {
OC_CLOUD_ERR("cloud manager is not running");
return;
}
assert(ctx->cloud_manager);
cloud_manager_stop(ctx);
oc_cloud_deregister_stop(ctx);
oc_reset_delayed_callback(ctx, start_manager, 0);
Expand All @@ -102,7 +99,9 @@ static oc_event_callback_retval_t
restart_manager(void *user_data)
{
oc_cloud_context_t *ctx = (oc_cloud_context_t *)user_data;
cloud_manager_restart(ctx);
if (ctx->cloud_manager) {
cloud_manager_restart(ctx);
}
return OC_EVENT_DONE;
}

Expand Down Expand Up @@ -449,8 +448,11 @@ oc_cloud_manager_start(oc_cloud_context_t *ctx, oc_cloud_cb_t cb, void *data)

cloud_manager_start(ctx);
ctx->cloud_manager = true;
oc_cloud_registration_context_init(&ctx->registration_ctx,
&ctx->store.ci_servers);
// in case we stopped the manager, but kept the configuration by calling
// oc_cloud_manager_stop_v1(ctx, true), we also need to keep the registration
// context
oc_cloud_registration_context_init_if_not_set(&ctx->registration_ctx,
&ctx->store.ci_servers);
#ifdef OC_SESSION_EVENTS
oc_remove_session_event_callback_v1(cloud_ep_session_event_handler, ctx,
false);
Expand All @@ -464,13 +466,16 @@ oc_cloud_manager_start(oc_cloud_context_t *ctx, oc_cloud_cb_t cb, void *data)
return 0;
}

int
oc_cloud_manager_stop(oc_cloud_context_t *ctx)
static bool
cloud_has_configuration(const oc_cloud_context_t *ctx)
{
if (ctx == NULL) {
return -1;
}
return oc_cloud_get_server_uri(ctx) != NULL &&
cloud_context_has_access_token(ctx);
}

void
oc_cloud_manager_stop_v1(oc_cloud_context_t *ctx, bool resetConfiguration)
{
#ifdef OC_SESSION_EVENTS
oc_remove_session_event_callback_v1(cloud_ep_session_event_handler, ctx,
false);
Expand All @@ -484,11 +489,28 @@ oc_cloud_manager_stop(oc_cloud_context_t *ctx)
oc_remove_delayed_callback(ctx, start_manager);
cloud_rd_reset_context(ctx);
cloud_manager_stop(ctx);
oc_cloud_store_reinitialize(&ctx->store);
oc_cloud_reset_endpoint(ctx);
oc_cloud_registration_context_deinit(&ctx->registration_ctx);
if (resetConfiguration || !cloud_has_configuration(ctx)) {
oc_cloud_store_reinitialize(&ctx->store);
oc_cloud_registration_context_deinit(&ctx->registration_ctx);
} else {
ctx->store.status &= ~OC_CLOUD_LOGGED_IN;
ctx->store.cps = (ctx->store.status & OC_CLOUD_REGISTERED) != 0
? OC_CPS_REGISTERED
: OC_CPS_READYTOREGISTER;
oc_cloud_registration_context_reset(&ctx->registration_ctx);
oc_cloud_store_dump_async(&ctx->store);
}
ctx->cloud_manager = false;
}

int
oc_cloud_manager_stop(oc_cloud_context_t *ctx)
{
if (ctx == NULL) {
return -1;
}
oc_cloud_manager_stop_v1(ctx, true);
return 0;
}

Expand Down
24 changes: 24 additions & 0 deletions api/cloud/oc_cloud_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,24 @@ oc_cloud_get_identity_cert_chain(const oc_cloud_context_t *ctx)
return ctx->selected_identity_cred_id;
}

bool
oc_cloud_registration_context_is_initialized(
const oc_cloud_registration_context_t *regctx)
{
return oc_string(regctx->initial_server) != NULL;
}

void
oc_cloud_registration_context_init_if_not_set(
oc_cloud_registration_context_t *regctx,
const oc_endpoint_addresses_t *servers)
{
if (oc_cloud_registration_context_is_initialized(regctx)) {
return;
}
oc_cloud_registration_context_init(regctx, servers);
}

void
oc_cloud_registration_context_init(oc_cloud_registration_context_t *regctx,
const oc_endpoint_addresses_t *servers)
Expand All @@ -325,6 +343,12 @@ oc_cloud_registration_context_deinit(oc_cloud_registration_context_t *regctx)
regctx->server_changed = false;
}

void
oc_cloud_registration_context_reset(oc_cloud_registration_context_t *regctx)
{
regctx->server_changed = false;
}

void
oc_cloud_set_keepalive(
oc_cloud_context_t *ctx,
Expand Down
14 changes: 14 additions & 0 deletions api/cloud/oc_cloud_context_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,20 @@ void oc_cloud_registration_context_init(oc_cloud_registration_context_t *regctx,
void oc_cloud_registration_context_deinit(
oc_cloud_registration_context_t *regctx) OC_NONNULL();

/** @brief Check if the registration context is initialized */
bool oc_cloud_registration_context_is_initialized(
const oc_cloud_registration_context_t *regctx) OC_NONNULL();

/** @brief Initialize the registration context if it hasn't been previously
* initialized */
void oc_cloud_registration_context_init_if_not_set(
oc_cloud_registration_context_t *regctx,
const oc_endpoint_addresses_t *servers) OC_NONNULL();

/** @brief Reset temporary data */
void oc_cloud_registration_context_reset(
oc_cloud_registration_context_t *regctx) OC_NONNULL();

#ifdef __cplusplus
}
#endif
Expand Down
57 changes: 57 additions & 0 deletions api/cloud/unittest/cloud_manager_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,63 @@ TEST_F(TestCloudManager, oc_cloud_manager_stop_fail)
EXPECT_EQ(-1, oc_cloud_manager_stop(nullptr));
}

TEST_F(TestCloudManager, oc_cloud_manager_stop_v1)
{
ASSERT_EQ(0, oc_cloud_manager_start(&m_context, nullptr, nullptr));
ASSERT_TRUE(oc_cloud_manager_is_started(&m_context));

// if cloud is registered and logged in, then the login flag should be
// removed, so on restart will attempt to login again
m_context.store.status =
OC_CLOUD_INITIALIZED | OC_CLOUD_REGISTERED | OC_CLOUD_LOGGED_IN;
m_context.store.cps = OC_CPS_REGISTERED;
oc_cloud_manager_stop_v1(&m_context, false);
EXPECT_FALSE(oc_cloud_manager_is_started(&m_context));
EXPECT_EQ(OC_CLOUD_INITIALIZED | OC_CLOUD_REGISTERED, m_context.store.status);
EXPECT_EQ(OC_CPS_REGISTERED, m_context.store.cps);

// if cloud is stopped during registration, then it should be in the ready to
// register state
ASSERT_EQ(0, oc_cloud_manager_start(&m_context, nullptr, nullptr));
ASSERT_TRUE(oc_cloud_manager_is_started(&m_context));
m_context.store.status = OC_CLOUD_INITIALIZED;
m_context.store.cps = OC_CPS_REGISTERING;
oc_cloud_manager_stop_v1(&m_context, false);
EXPECT_FALSE(oc_cloud_manager_is_started(&m_context));
EXPECT_EQ(OC_CLOUD_INITIALIZED, m_context.store.status);
EXPECT_EQ(OC_CPS_READYTOREGISTER, m_context.store.cps);

// if the cloud is not configured, then the configuration should be reset
ASSERT_EQ(0, oc_cloud_manager_start(&m_context, nullptr, nullptr));
ASSERT_TRUE(oc_cloud_manager_is_started(&m_context));
m_context.store.status =
OC_CLOUD_INITIALIZED | OC_CLOUD_REGISTERED | OC_CLOUD_LOGGED_IN;
m_context.store.cps = OC_CPS_REGISTERED;
// this sets the default cloud server, but access token will not be set
ASSERT_EQ(0, oc_cloud_provision_conf_resource(&m_context, "", "", "", ""));
ASSERT_EQ(nullptr, oc_string(*oc_cloud_get_access_token(&m_context)));
oc_cloud_manager_stop_v1(&m_context, false);
EXPECT_FALSE(oc_cloud_manager_is_started(&m_context));
EXPECT_EQ(OC_CLOUD_INITIALIZED, m_context.store.status);
EXPECT_EQ(OC_CPS_UNINITIALIZED, m_context.store.cps);

ASSERT_EQ(0, oc_cloud_manager_start(&m_context, nullptr, nullptr));
ASSERT_TRUE(oc_cloud_manager_is_started(&m_context));
m_context.store.status =
OC_CLOUD_INITIALIZED | OC_CLOUD_REGISTERED | OC_CLOUD_LOGGED_IN;
m_context.store.cps = OC_CPS_REGISTERED;
// access token set
ASSERT_EQ(0, oc_cloud_provision_conf_resource(&m_context, "", "access_token",
"", ""));
ASSERT_NE(nullptr, oc_string(*oc_cloud_get_access_token(&m_context)));
// but no cloud server set
oc_endpoint_addresses_clear(&m_context.store.ci_servers);
oc_cloud_manager_stop_v1(&m_context, false);
EXPECT_FALSE(oc_cloud_manager_is_started(&m_context));
EXPECT_EQ(OC_CLOUD_INITIALIZED, m_context.store.status);
EXPECT_EQ(OC_CPS_UNINITIALIZED, m_context.store.cps);
}

TEST_F(TestCloudManager, oc_cloud_manager_is_started)
{
EXPECT_FALSE(oc_cloud_manager_is_started(&m_context));
Expand Down
37 changes: 37 additions & 0 deletions api/cloud/unittest/cloud_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,43 @@ TEST_F(TestCloudWithServer, oc_cloud_provision_conf_resource)
EXPECT_EQ(OC_CLOUD_INITIALIZED, ctx->store.status);
}

TEST_F(TestCloudWithServer, oc_cloud_provision_conf_resource_with_started_cloud)
{
oc_cloud_context_t *ctx = oc_cloud_get_context(kDeviceID);
ASSERT_NE(nullptr, ctx);
ASSERT_FALSE(
oc_cloud_registration_context_is_initialized(&ctx->registration_ctx));
ctx->store.status = OC_CLOUD_INITIALIZED;
ASSERT_EQ(0, oc_cloud_manager_start(ctx, nullptr, nullptr));
ASSERT_TRUE(
oc_cloud_registration_context_is_initialized(&ctx->registration_ctx));
auto defaulServer = OC_STRING_LOCAL(OCF_COAPCLOUDCONF_DEFAULT_CIS);
EXPECT_TRUE(
oc_string_is_equal(&ctx->registration_ctx.initial_server, &defaulServer));

std::string_view ci_server = "ci_server";
std::string_view access_token = "access_token";
std::string_view sid = "12345678-1234-5678-1234-567812345678";
oc_uuid_t sid_uuid;
oc_str_to_uuid(sid.data(), &sid_uuid);
std::string_view auth_provider = "auth_provider";
ASSERT_EQ(0, oc_cloud_provision_conf_resource(ctx, ci_server.data(),
access_token.data(), sid.data(),
auth_provider.data()));
EXPECT_STREQ(access_token.data(), oc_string(*oc_cloud_get_access_token(ctx)));
EXPECT_STREQ(auth_provider.data(),
oc_string(*oc_cloud_get_authorization_provider_name(ctx)));
const auto *ctx_cis = oc_cloud_get_server_uri(ctx);
ASSERT_NE(nullptr, ctx_cis);
EXPECT_STREQ(ci_server.data(), oc_string(*ctx_cis));
EXPECT_TRUE(oc_uuid_is_equal(sid_uuid, *oc_cloud_get_server_id(ctx)));
EXPECT_EQ(OC_CLOUD_INITIALIZED, ctx->store.status);
EXPECT_TRUE(oc_cloud_manager_is_started(ctx));
EXPECT_TRUE(oc_string_view_is_equal(
oc_string_view2(&ctx->registration_ctx.initial_server),
oc_string_view(ci_server.data(), ci_server.length())));
}

TEST_F(TestCloudWithServer, oc_cloud_action_to_str)
{
std::string v;
Expand Down
19 changes: 17 additions & 2 deletions include/oc_cloud.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ oc_cps_t oc_cloud_get_provisioning_status(const oc_cloud_context_t *ctx)
/**
* @brief Start cloud registration process.
*
* @param ctx cloud context (cannot be NULL)
* @param ctx cloud context
* @param cb callback function invoked on status change
* @param data user data provided to the status change function
* @return int 0 on success
Expand All @@ -319,13 +319,28 @@ int oc_cloud_manager_start(oc_cloud_context_t *ctx, oc_cloud_cb_t cb,
* @brief Stop cloud registration process, remove related pending delayed
* callbacks and clean-up data.
*
* @param ctx cloud context (cannot be NULL)
* @param ctx cloud context
* @return int 0 on success
* @return int -1 on error
*/
OC_API
int oc_cloud_manager_stop(oc_cloud_context_t *ctx);

/**
* @brief Stop cloud registration process, remove related pending delayed
* callbacks and clean-up data.
*
* @param ctx cloud context (cannot be NULL)
* @param resetConfiguration if true, reset cloud configuration to default
* (cloud must be reconfigured by oc_cloud_provision_conf_resource or by
* updating the cloud resource); if false the previous cloud configuration is
* kept, but the cloud is reset to OC_CPS_REGISTERED state if it was registered
* or to OC_CPS_READYTOREGISTER otherwise
*/
OC_API
void oc_cloud_manager_stop_v1(oc_cloud_context_t *ctx, bool resetConfiguration)
OC_NONNULL();

/**
* @brief Restart cloud registration process with the current configuration.
*
Expand Down
21 changes: 21 additions & 0 deletions swig/swig_interfaces/oc_cloud.i
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,23 @@ int jni_cloud_manager_stop(oc_cloud_context_t *ctx)
}
%}

%ignore oc_cloud_manager_stop_v1;
%rename (managerStopV1) jni_cloud_manager_stop_v1;
%inline %{
void jni_cloud_manager_stop_v1(oc_cloud_context_t *ctx, bool resetConfiguration)
{
#ifdef OC_CLOUD
oc_cloud_manager_stop_v1(ctx, resetConfiguration);
jni_callback_data *item = jni_list_get_item_by_callback_valid(OC_CALLBACK_VALID_TILL_CLOUD_MANAGER_STOP);
jni_list_remove(item);
#else /* OC_CLOUD*/
OC_DBG("JNI: %s - Must build with OC_CLOUD defined to use this function.\n", __func__);
(void)ctx;
(void)resetConfiguration;
#endif /* !OC_CLOUD */
}
%}

%ignore oc_cloud_manager_restart;
%rename (managerRestart) jni_cloud_manager_restart;
%inline %{
Expand Down Expand Up @@ -712,10 +729,14 @@ void jni_cloud_context_clear(oc_cloud_context_t *ctx, bool dump_async)
%ignore cloud_context_has_permanent_access_token;
%ignore cloud_context_clear_access_token;
%ignore cloud_context_has_refresh_token;
%ignore cloud_context_on_server_change;

%ignore oc_cloud_registration_context_t;
%ignore oc_cloud_registration_context_init;
%ignore oc_cloud_registration_context_deinit;
%ignore oc_cloud_registration_context_is_initialized;
%ignore oc_cloud_registration_context_init_if_not_set;
%ignore oc_cloud_registration_context_reset;
%ignore oc_cloud_context_t::registration_ctx;
%include "api/cloud/oc_cloud_context_internal.h"

Expand Down

0 comments on commit d7089cf

Please sign in to comment.