Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cloud: add oc_cloud_manager_stop_v1 function #620

Merged
merged 1 commit into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading