charon-tkm: Add acquire_ref method to ID manager
authorAdrian-Ken Rueegsegger <ken@codelabs.ch>
Fri, 1 Sep 2017 15:15:41 +0000 (17:15 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 15 Sep 2017 10:16:57 +0000 (12:16 +0200)
The function acquires a reference to the given context reference id for
a specific context kind.

src/charon-tkm/src/tkm/tkm_id_manager.c
src/charon-tkm/src/tkm/tkm_id_manager.h
src/charon-tkm/tests/id_manager_tests.c

index b07409d..2d28c3c 100644 (file)
@@ -103,6 +103,33 @@ METHOD(tkm_id_manager_t, acquire_id, int,
        return id;
 }
 
+METHOD(tkm_id_manager_t, acquire_ref, bool,
+       private_tkm_id_manager_t * const this, const tkm_context_kind_t kind,
+       const int ref_id)
+{
+       const int idx = ref_id - 1;
+
+       if (!is_valid_kind(kind))
+       {
+               DBG1(DBG_LIB, "tried to acquire reference for invalid context kind '%d'",
+                        kind);
+               return FALSE;
+       }
+
+       if (ref_id < 1 || (uint64_t)ref_id > this->limits[kind])
+       {
+               DBG1(DBG_LIB, "tried to acquire reference for context id %d out of "
+                        "bounds (max %llu)", ref_id, this->limits[kind]);
+               return FALSE;
+       }
+
+       this->locks[kind]->write_lock(this->locks[kind]);
+       this->ctxids[kind][idx]++;
+       this->locks[kind]->unlock(this->locks[kind]);
+
+       return TRUE;
+}
+
 METHOD(tkm_id_manager_t, release_id, bool,
        private_tkm_id_manager_t * const this, const tkm_context_kind_t kind,
        const int id)
@@ -150,6 +177,7 @@ tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits)
        INIT(this,
                .public = {
                        .acquire_id = _acquire_id,
+                       .acquire_ref = _acquire_ref,
                        .release_id = _release_id,
                        .destroy = _destroy,
                },
index 0fc9ff8..ec7b07f 100644 (file)
@@ -74,6 +74,18 @@ struct tkm_id_manager_t {
                                          const tkm_context_kind_t kind);
 
        /**
+        * Acquire reference to given context id for a specific context kind.
+        *
+        * @param kind                  kind of context id
+        * @param ref_id                id to acquire a reference for
+        * @return                              TRUE if reference could be acquired,
+        *                                              FALSE otherwise
+        */
+       bool (*acquire_ref)(tkm_id_manager_t * const this,
+                                               const tkm_context_kind_t kind,
+                                               const int ref_id);
+
+       /**
         * Release a previously acquired context id.
         *
         * @param kind                  kind of context id to release
index 8157496..392379a 100644 (file)
@@ -84,6 +84,71 @@ START_TEST(test_acquire_id_same)
 }
 END_TEST
 
+START_TEST(test_acquire_ref)
+{
+       int i, id = 0;
+       bool acquired = false;
+       tkm_id_manager_t *idmgr = tkm_id_manager_create(limits);
+
+       for (i = 0; i < TKM_CTX_MAX; i++)
+       {
+               id = idmgr->acquire_id(idmgr, i);
+               acquired = idmgr->acquire_ref(idmgr, i, id);
+               fail_unless(acquired, "Error acquiring reference context kind %d", i);
+
+               /* Reset test variable */
+               acquired = false;
+       }
+
+       idmgr->destroy(idmgr);
+}
+END_TEST
+
+START_TEST(test_acquire_ref_invalid_kind)
+{
+       bool acquired;
+       tkm_id_manager_t *idmgr = tkm_id_manager_create(limits);
+
+       acquired = idmgr->acquire_ref(idmgr, TKM_CTX_MAX, 1);
+       fail_if(acquired, "Acquired reference for invalid context kind %d", TKM_CTX_MAX);
+
+       /* Reset test variable */
+       acquired = 0;
+
+       acquired = idmgr->acquire_ref(idmgr, -1, 1);
+       fail_if(acquired, "Acquired reference for invalid context kind %d", -1);
+
+       idmgr->destroy(idmgr);
+}
+END_TEST
+
+START_TEST(test_acquire_ref_invalid_id)
+{
+       int i;
+       bool acquired;
+       tkm_id_manager_t *idmgr = tkm_id_manager_create(limits);
+
+       for (i = 0; i < TKM_CTX_MAX; i++)
+       {
+               acquired = idmgr->acquire_ref(idmgr, i, -1);
+               fail_if(acquired,
+                               "Acquired reference for negative id of context kind %d", i);
+
+               /* Reset test variable */
+               acquired = false;
+
+               acquired = idmgr->acquire_ref(idmgr, i, limits[i] + 1);
+               fail_if(acquired,
+                               "Acquired reference exceeding limit of context kind %d", i);
+
+               /* Reset test variable */
+               acquired = false;
+       }
+
+       idmgr->destroy(idmgr);
+}
+END_TEST
+
 START_TEST(test_release_id)
 {
        int i, id = 0;
@@ -150,6 +215,9 @@ Suite *make_id_manager_tests()
        tcase_add_test(tc, test_acquire_id);
        tcase_add_test(tc, test_acquire_id_invalid_kind);
        tcase_add_test(tc, test_acquire_id_same);
+       tcase_add_test(tc, test_acquire_ref);
+       tcase_add_test(tc, test_acquire_ref_invalid_kind);
+       tcase_add_test(tc, test_acquire_ref_invalid_id);
        suite_add_tcase(s, tc);
 
        tc = tcase_create("release");