diff --git a/libs/libblade/libblade.vcxproj b/libs/libblade/libblade.vcxproj index 43715b542a..8cb58199b1 100644 --- a/libs/libblade/libblade.vcxproj +++ b/libs/libblade/libblade.vcxproj @@ -188,10 +188,12 @@ + + @@ -210,10 +212,12 @@ + + diff --git a/libs/libblade/libblade.vcxproj.filters b/libs/libblade/libblade.vcxproj.filters index 2f896185bc..f3392d90c6 100644 --- a/libs/libblade/libblade.vcxproj.filters +++ b/libs/libblade/libblade.vcxproj.filters @@ -75,6 +75,12 @@ Source Files + + Source Files + + + Source Files + @@ -140,5 +146,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/libs/libblade/src/blade_channel.c b/libs/libblade/src/blade_channel.c new file mode 100644 index 0000000000..419d9e89ca --- /dev/null +++ b/libs/libblade/src/blade_channel.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017, Shane Bryldt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "blade.h" + +struct blade_channel_s { + const char *name; + ks_rwl_t *lock; + ks_hash_t *authorizations; +}; + + +static void blade_channel_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type) +{ + blade_channel_t *bc = (blade_channel_t *)ptr; + + ks_assert(bc); + + switch (action) { + case KS_MPCL_ANNOUNCE: + break; + case KS_MPCL_TEARDOWN: + if (bc->name) ks_pool_free(&bc->name); + if (bc->lock) ks_rwl_destroy(&bc->lock); + if (bc->authorizations) ks_hash_destroy(&bc->authorizations); + break; + case KS_MPCL_DESTROY: + break; + } +} + +KS_DECLARE(ks_status_t) blade_channel_create(blade_channel_t **bcP, ks_pool_t *pool, const char *name) +{ + blade_channel_t *bc = NULL; + + ks_assert(bcP); + ks_assert(pool); + ks_assert(name); + + bc = ks_pool_alloc(pool, sizeof(blade_channel_t)); + bc->name = ks_pstrdup(pool, name); + + ks_rwl_create(&bc->lock, pool); + ks_assert(bc->lock); + + ks_hash_create(&bc->authorizations, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool); + ks_assert(bc->authorizations); + + ks_pool_set_cleanup(bc, NULL, blade_channel_cleanup); + + *bcP = bc; + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(ks_status_t) blade_channel_destroy(blade_channel_t **bcP) +{ + ks_assert(bcP); + ks_assert(*bcP); + + ks_pool_free(bcP); + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(const char *) blade_channel_name_get(blade_channel_t *bc) +{ + ks_assert(bc); + return bc->name; +} + +KS_DECLARE(ks_status_t) blade_channel_read_lock(blade_channel_t *bc) +{ + ks_assert(bc); + return ks_rwl_read_lock(bc->lock); +} + +KS_DECLARE(ks_status_t) blade_channel_read_unlock(blade_channel_t *bc) +{ + ks_assert(bc); + return ks_rwl_read_unlock(bc->lock); +} + +KS_DECLARE(ks_status_t) blade_channel_write_lock(blade_channel_t *bc) +{ + ks_assert(bc); + return ks_rwl_write_lock(bc->lock); +} + +KS_DECLARE(ks_status_t) blade_channel_write_unlock(blade_channel_t *bc) +{ + ks_assert(bc); + return ks_rwl_write_unlock(bc->lock); +} + +KS_DECLARE(ks_bool_t) blade_channel_authorization_verify(blade_channel_t *bc, const char *target) +{ + ks_bool_t authorized = KS_FALSE; + + ks_assert(bc); + ks_assert(target); + + authorized = (ks_bool_t)(uintptr_t)ks_hash_search(bc->authorizations, (void *)target, KS_READLOCKED); + ks_hash_read_unlock(bc->authorizations); + + return authorized; +} + +KS_DECLARE(ks_status_t) blade_channel_authorization_add(blade_channel_t *bc, const char *target) +{ + ks_assert(bc); + ks_assert(target); + + ks_hash_insert(bc->authorizations, (void *)ks_pstrdup(ks_pool_get(bc), target), (void *)KS_TRUE); + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(ks_bool_t) blade_channel_authorization_remove(blade_channel_t *bc, const char *target) +{ + ks_bool_t ret = KS_FALSE; + + ks_assert(bc); + ks_assert(target); + + if (ks_hash_remove(bc->authorizations, (void *)target)) { + ret = KS_TRUE; + } + + return ret; +} + + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: + */ diff --git a/libs/libblade/src/blade_mastermgr.c b/libs/libblade/src/blade_mastermgr.c index 9693806b57..61337c98e8 100644 --- a/libs/libblade/src/blade_mastermgr.c +++ b/libs/libblade/src/blade_mastermgr.c @@ -36,8 +36,10 @@ struct blade_mastermgr_s { blade_handle_t *handle; + const char *master_nodeid; // @todo how does "exclusive" play into the controllers, does "exclusive" mean only one provider can exist for a given protocol and realm? what does non exclusive mean? - ks_hash_t *protocols; // protocols that have been published with blade.publish, and the details to locate a protocol controller with blade.locate + ks_hash_t *realms; + //ks_hash_t *protocols; // protocols that have been published with blade.publish, and the details to locate a protocol controller with blade.locate }; @@ -70,8 +72,8 @@ KS_DECLARE(ks_status_t) blade_mastermgr_create(blade_mastermgr_t **bmmgrP, blade bmmgr = ks_pool_alloc(pool, sizeof(blade_mastermgr_t)); bmmgr->handle = bh; - ks_hash_create(&bmmgr->protocols, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY | KS_HASH_FLAG_FREE_VALUE, pool); - ks_assert(bmmgr->protocols); + ks_hash_create(&bmmgr->realms, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY | KS_HASH_FLAG_FREE_VALUE, pool); + ks_assert(bmmgr->realms); ks_pool_set_cleanup(bmmgr, NULL, blade_mastermgr_cleanup); @@ -105,6 +107,78 @@ KS_DECLARE(blade_handle_t *) blade_mastermgr_handle_get(blade_mastermgr_t *bmmgr return bmmgr->handle; } +ks_status_t blade_mastermgr_config(blade_mastermgr_t *bmmgr, config_setting_t *config) +{ + ks_pool_t *pool = NULL; + config_setting_t *master = NULL; + config_setting_t *master_nodeid = NULL; + const char *nodeid = NULL; + + ks_assert(bmmgr); + + pool = ks_pool_get(bmmgr); + + if (!config_setting_is_group(config)) { + ks_log(KS_LOG_DEBUG, "!config_setting_is_group(config)\n"); + return KS_STATUS_FAIL; + } + + master = config_setting_get_member(config, "master"); + if (master) { + master_nodeid = config_lookup_from(master, "nodeid"); + if (!master_nodeid) return KS_STATUS_FAIL; + + if (config_setting_type(master_nodeid) != CONFIG_TYPE_STRING) return KS_STATUS_FAIL; + nodeid = config_setting_get_string(master_nodeid); + } + + if (master) { + bmmgr->master_nodeid = ks_pstrdup(pool, nodeid); + + ks_log(KS_LOG_DEBUG, "Configured\n"); + } + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(ks_status_t) blade_mastermgr_startup(blade_mastermgr_t *bmmgr, config_setting_t *config) +{ + ks_pool_t *pool = NULL; + + ks_assert(bmmgr); + + pool = ks_pool_get(bmmgr); + + if (blade_mastermgr_config(bmmgr, config) != KS_STATUS_SUCCESS) { + ks_log(KS_LOG_DEBUG, "blade_mastermgr_config failed\n"); + return KS_STATUS_FAIL; + } + + if (bmmgr->master_nodeid) { + blade_realm_t *br = NULL; + + blade_upstreammgr_localid_set(blade_handle_upstreammgr_get(bmmgr->handle), bmmgr->master_nodeid); + blade_upstreammgr_masterid_set(blade_handle_upstreammgr_get(bmmgr->handle), bmmgr->master_nodeid); + + // build the internal blade protocol controlled by the master for the purpose of global event channels for node presence + blade_realm_create(&br, pool, "blade"); + // @note realm should remain public, these event channels must be available to any node + blade_mastermgr_realm_add(bmmgr, br); + + blade_mastermgr_realm_protocol_controller_add(bmmgr, "blade", "presence", bmmgr->master_nodeid); + + blade_mastermgr_realm_protocol_channel_add(bmmgr, "blade", "presence", "join"); + blade_mastermgr_realm_protocol_channel_add(bmmgr, "blade", "presence", "leave"); + } + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(ks_status_t) blade_mastermgr_shutdown(blade_mastermgr_t *bmmgr) +{ + ks_assert(bmmgr); + return KS_STATUS_SUCCESS; +} + KS_DECLARE(ks_status_t) blade_mastermgr_purge(blade_mastermgr_t *bmmgr, const char *nodeid) { ks_pool_t *pool = NULL; @@ -114,252 +188,383 @@ KS_DECLARE(ks_status_t) blade_mastermgr_purge(blade_mastermgr_t *bmmgr, const ch pool = ks_pool_get(bmmgr); - ks_hash_write_lock(bmmgr->protocols); - for (ks_hash_iterator_t *it = ks_hash_first(bmmgr->protocols, KS_UNLOCKED); it; it = ks_hash_next(&it)) { - const char *key = NULL; - blade_protocol_t *bp = NULL; + ks_hash_write_lock(bmmgr->realms); - ks_hash_this(it, (const void **)&key, NULL, (void **)&bp); + for (ks_hash_iterator_t *it = ks_hash_first(bmmgr->realms, KS_UNLOCKED); it; it = ks_hash_next(&it)) { + const char *realm = NULL; + blade_realm_t *br = NULL; + ks_hash_this(it, (const void **)&realm, NULL, (void **)&br); - if (blade_protocol_purge(bp, nodeid)) { - if (!blade_protocol_controller_available(bp)) { - if (!cleanup) ks_hash_create(&cleanup, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK, pool); - ks_hash_insert(cleanup, (void *)key, bp); - } else { - // @todo not the last controller, may need to propagate that the controller is no longer available? - } - } - } - if (cleanup) { - for (ks_hash_iterator_t *it = ks_hash_first(cleanup, KS_UNLOCKED); it; it = ks_hash_next(&it)) { - const char *key = NULL; + blade_realm_write_lock(br); + + for (ks_hash_iterator_t *it2 = blade_realm_protocols_iterator(br, KS_UNLOCKED); it2; it2 = ks_hash_next(&it2)) { + const char *protocol = NULL; blade_protocol_t *bp = NULL; - ks_hash_this(it, (const void **)&key, NULL, (void **)&bp); + ks_hash_this(it2, (const void **)&protocol, NULL, (void **)&bp); - blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(bmmgr->handle), BLADE_RPCBROADCAST_COMMAND_PROTOCOL_REMOVE, NULL, blade_protocol_name_get(bp), blade_protocol_realm_get(bp), NULL, NULL, NULL, NULL, NULL); + blade_protocol_write_lock(bp); - ks_log(KS_LOG_DEBUG, "Protocol Removed: %s\n", key); - ks_hash_remove(bmmgr->protocols, (void *)key); + if (blade_protocol_purge(bp, nodeid)) { + if (!blade_protocol_controller_available(bp)) { + if (!cleanup) ks_hash_create(&cleanup, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK, pool); + ks_hash_insert(cleanup, (void *)protocol, bp); + } + else { + // @todo not the last controller, may need to propagate that the controller is no longer available? + } + } } - ks_hash_destroy(&cleanup); + + if (cleanup) { + for (ks_hash_iterator_t *it2 = ks_hash_first(cleanup, KS_UNLOCKED); it2; it2 = ks_hash_next(&it2)) { + const char *protocol = NULL; + blade_protocol_t *bp = NULL; + + ks_hash_this(it2, (const void **)&protocol, NULL, (void **)&bp); + + blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(bmmgr->handle), BLADE_RPCBROADCAST_COMMAND_PROTOCOL_REMOVE, NULL, protocol, realm, NULL, NULL, NULL, NULL, NULL); + + ks_log(KS_LOG_DEBUG, "Protocol Removed: %s@%s\n", protocol, realm); + blade_protocol_write_unlock(bp); + blade_realm_protocol_remove(br, protocol); + } + ks_hash_destroy(&cleanup); + } + + blade_realm_write_unlock(br); } - ks_hash_write_unlock(bmmgr->protocols); + ks_hash_write_unlock(bmmgr->realms); return KS_STATUS_SUCCESS; } -KS_DECLARE(blade_protocol_t *) blade_mastermgr_protocol_lookup(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm) +KS_DECLARE(ks_status_t) blade_mastermgr_realm_add(blade_mastermgr_t *bmmgr, blade_realm_t *realm) { + ks_assert(bmmgr); + ks_assert(realm); + + ks_log(KS_LOG_DEBUG, "Realm Added: %s\n", blade_realm_name_get(realm)); + ks_hash_insert(bmmgr->realms, (void *)ks_pstrdup(ks_pool_get(bmmgr), blade_realm_name_get(realm)), (void *)realm); + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(ks_bool_t) blade_mastermgr_realm_remove(blade_mastermgr_t *bmmgr, const char *realm) +{ + ks_bool_t ret = KS_FALSE; + + ks_assert(bmmgr); + ks_assert(realm); + + if (ks_hash_remove(bmmgr->realms, (void *)realm)) { + ret = KS_TRUE; + ks_log(KS_LOG_DEBUG, "Realm Removed: %s\n", realm); + } + + return ret; +} + +KS_DECLARE(blade_protocol_t *) blade_mastermgr_realm_protocol_lookup(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, ks_bool_t writelocked) +{ + blade_realm_t *br = NULL; blade_protocol_t *bp = NULL; - char *key = NULL; ks_assert(bmmgr); ks_assert(protocol); ks_assert(realm); - key = ks_psprintf(ks_pool_get(bmmgr), "%s@%s", protocol, realm); - - bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)key, KS_READLOCKED); - // @todo if (bp) blade_protocol_read_lock(bp); - ks_hash_read_unlock(bmmgr->protocols); + br = (blade_realm_t *)ks_hash_search(bmmgr->realms, (void *)realm, KS_READLOCKED); + if (br) bp = blade_realm_protocol_lookup(br, protocol, writelocked); + ks_hash_read_unlock(bmmgr->realms); return bp; } -KS_DECLARE(ks_status_t) blade_mastermgr_controller_add(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *controller) +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_controller_add(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *controller) { + ks_status_t ret = KS_STATUS_SUCCESS; ks_pool_t *pool = NULL; + blade_realm_t *br = NULL; blade_protocol_t *bp = NULL; - char *key = NULL; ks_assert(bmmgr); - ks_assert(protocol); ks_assert(realm); + ks_assert(protocol); ks_assert(controller); pool = ks_pool_get(bmmgr); - key = ks_psprintf(pool, "%s@%s", protocol, realm); + ks_hash_read_lock(bmmgr->realms); - ks_hash_write_lock(bmmgr->protocols); + br = (blade_realm_t *)ks_hash_search(bmmgr->realms, (void *)realm, KS_UNLOCKED); + if (!br) { + ret = KS_STATUS_FAIL; + goto done; + } - bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)key, KS_UNLOCKED); + bp = blade_realm_protocol_lookup(br, protocol, KS_TRUE); if (bp) { // @todo deal with exclusive stuff when the protocol is already registered } if (!bp) { - blade_protocol_create(&bp, pool, protocol, realm); + blade_protocol_create(&bp, pool, br, protocol); ks_assert(bp); - ks_log(KS_LOG_DEBUG, "Protocol Added: %s\n", key); - ks_hash_insert(bmmgr->protocols, (void *)ks_pstrdup(pool, key), bp); + blade_protocol_write_lock(bp); + + ks_log(KS_LOG_DEBUG, "Protocol Added: %s@%s\n", protocol, realm); + blade_realm_protocol_add(br, bp); } blade_protocol_controller_add(bp, controller); - ks_hash_write_unlock(bmmgr->protocols); + blade_protocol_write_unlock(bp); - ks_pool_free(&key); +done: + ks_hash_read_unlock(bmmgr->realms); - return KS_STATUS_SUCCESS; + return ret; } -KS_DECLARE(ks_status_t) blade_mastermgr_controller_remove(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *controller) +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_controller_remove(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *controller) { + ks_status_t ret = KS_STATUS_SUCCESS; ks_pool_t *pool = NULL; + blade_realm_t *br = NULL; blade_protocol_t *bp = NULL; - char *key = NULL; ks_assert(bmmgr); - ks_assert(protocol); ks_assert(realm); + ks_assert(protocol); ks_assert(controller); pool = ks_pool_get(bmmgr); - key = ks_psprintf(pool, "%s@%s", protocol, realm); + ks_hash_read_lock(bmmgr->realms); - ks_hash_write_lock(bmmgr->protocols); + br = (blade_realm_t *)ks_hash_search(bmmgr->realms, (void *)realm, KS_UNLOCKED); + if (!br) { + ret = KS_STATUS_FAIL; + goto done; + } - bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)key, KS_UNLOCKED); + bp = blade_realm_protocol_lookup(br, protocol, KS_TRUE); if (bp) { if (blade_protocol_controller_remove(bp, controller)) { if (!blade_protocol_controller_available(bp)) { - // @todo broadcast protocol removal to remove all channel subscriptions - ks_log(KS_LOG_DEBUG, "Protocol Removed: %s\n", key); - ks_hash_remove(bmmgr->protocols, (void *)key); + blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(bmmgr->handle), BLADE_RPCBROADCAST_COMMAND_PROTOCOL_REMOVE, NULL, protocol, realm, NULL, NULL, NULL, NULL, NULL); + + ks_log(KS_LOG_DEBUG, "Protocol Removed: %s@%s\n", protocol, realm); + blade_realm_protocol_remove(br, protocol); } else { // @todo not the last controller, may need to propagate when a specific controller becomes unavailable though } } + blade_protocol_write_unlock(bp); } - ks_hash_write_unlock(bmmgr->protocols); +done: + ks_hash_read_unlock(bmmgr->realms); - ks_pool_free(&key); - - return KS_STATUS_SUCCESS; + return ret; } -KS_DECLARE(ks_status_t) blade_mastermgr_channel_add(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *channel) +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_channel_add(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *channel) { ks_status_t ret = KS_STATUS_SUCCESS; + blade_realm_t *br = NULL; blade_protocol_t *bp = NULL; - char *key = NULL; + blade_channel_t *bc = NULL; ks_assert(bmmgr); - ks_assert(protocol); ks_assert(realm); + ks_assert(protocol); ks_assert(channel); - key = ks_psprintf(ks_pool_get(bmmgr), "%s@%s", protocol, realm); + ks_hash_read_lock(bmmgr->realms); - bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)key, KS_READLOCKED); + br = (blade_realm_t *)ks_hash_search(bmmgr->realms, (void *)realm, KS_UNLOCKED); + if (!br) { + ret = KS_STATUS_FAIL; + goto done; + } + + bp = blade_realm_protocol_lookup(br, protocol, KS_TRUE); if (!bp) { ret = KS_STATUS_NOT_FOUND; goto done; } - blade_protocol_channel_add(bp, channel); + bc = blade_protocol_channel_lookup(bp, channel, KS_TRUE); + if (!bc) { + ret = KS_STATUS_DUPLICATE_OPERATION; + goto done; + } + + blade_channel_create(&bc, ks_pool_get(bc), channel); + ks_assert(bc); + + blade_channel_write_lock(bc); + + if (blade_protocol_channel_add(bp, bc) == KS_STATUS_SUCCESS) { + ks_log(KS_LOG_DEBUG, "Protocol Channel Added: %s@%s/%s\n", blade_protocol_name_get(bp), blade_realm_name_get(br), blade_channel_name_get(bc)); + } done: - ks_pool_free(&key); - - ks_hash_read_unlock(bmmgr->protocols); + if (bc) blade_channel_write_unlock(bc); + if (bp) blade_protocol_write_unlock(bp); + ks_hash_read_unlock(bmmgr->realms); return ret; } -KS_DECLARE(ks_status_t) blade_mastermgr_channel_remove(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *channel) +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_channel_remove(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *channel) { ks_status_t ret = KS_STATUS_SUCCESS; + blade_realm_t *br = NULL; blade_protocol_t *bp = NULL; - char *key = NULL; + blade_channel_t *bc = NULL; ks_assert(bmmgr); - ks_assert(protocol); ks_assert(realm); + ks_assert(protocol); ks_assert(channel); - key = ks_psprintf(ks_pool_get(bmmgr), "%s@%s", protocol, realm); + ks_hash_read_lock(bmmgr->realms); - bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)key, KS_READLOCKED); + br = (blade_realm_t *)ks_hash_search(bmmgr->realms, (void *)realm, KS_UNLOCKED); + if (!br) { + ret = KS_STATUS_FAIL; + goto done; + } + + bp = blade_realm_protocol_lookup(br, protocol, KS_TRUE); if (!bp) { ret = KS_STATUS_NOT_FOUND; goto done; } + bc = blade_protocol_channel_lookup(bp, channel, KS_TRUE); + if (!bc) { + ret = KS_STATUS_NOT_FOUND; + goto done; + } + if (blade_protocol_channel_remove(bp, channel)) { - blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(bmmgr->handle), BLADE_RPCBROADCAST_COMMAND_CHANNEL_REMOVE, NULL, blade_protocol_name_get(bp), blade_protocol_realm_get(bp), channel, NULL, NULL, NULL, NULL); + blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(bmmgr->handle), BLADE_RPCBROADCAST_COMMAND_CHANNEL_REMOVE, NULL, protocol, realm, channel, NULL, NULL, NULL, NULL); + ks_log(KS_LOG_DEBUG, "Protocol Channel Removed: %s@%s/%s\n", blade_protocol_name_get(bp), blade_realm_name_get(br), blade_channel_name_get(bc)); + blade_channel_write_unlock(bc); + blade_channel_destroy(&bc); } done: - ks_pool_free(&key); - - ks_hash_read_unlock(bmmgr->protocols); + if (bp) blade_protocol_write_unlock(bp); + ks_hash_read_unlock(bmmgr->realms); return ret; } -KS_DECLARE(ks_status_t) blade_mastermgr_channel_authorize(blade_mastermgr_t *bmmgr, ks_bool_t remove, const char *protocol, const char *realm, const char *channel, const char *controller, const char *target) +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_channel_authorize(blade_mastermgr_t *bmmgr, ks_bool_t remove, const char *realm, const char *protocol, const char *channel, const char *controller, const char *target) { ks_status_t ret = KS_STATUS_SUCCESS; + blade_realm_t *br = NULL; blade_protocol_t *bp = NULL; - char *key = NULL; - //ks_hash_t *cleanup = NULL; + blade_channel_t *bc = NULL; ks_assert(bmmgr); - ks_assert(protocol); ks_assert(realm); + ks_assert(protocol); ks_assert(channel); ks_assert(controller); ks_assert(target); - key = ks_psprintf(ks_pool_get(bmmgr), "%s@%s", protocol, realm); + ks_hash_read_lock(bmmgr->realms); - bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)key, KS_READLOCKED); + br = (blade_realm_t *)ks_hash_search(bmmgr->realms, (void *)realm, KS_UNLOCKED); + if (!br) { + ret = KS_STATUS_FAIL; + goto done; + } + + bp = blade_realm_protocol_lookup(br, protocol, KS_FALSE); if (!bp) { ret = KS_STATUS_NOT_FOUND; goto done; } - ret = blade_protocol_channel_authorize(bp, remove, channel, controller, target); + if (!blade_protocol_controller_verify(bp, controller)) { + ret = KS_STATUS_NOT_ALLOWED; + goto done; + } + + bc = blade_protocol_channel_lookup(bp, channel, KS_TRUE); + if (!bc) { + ret = KS_STATUS_NOT_FOUND; + goto done; + } + + if (remove) { + if (blade_channel_authorization_remove(bc, target)) { + ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Removed: %s from %s@%s/%s\n", target, blade_protocol_name_get(bp), blade_realm_name_get(br), blade_channel_name_get(bc)); + } else ret = KS_STATUS_NOT_FOUND; + } else { + if (blade_channel_authorization_add(bc, target)) { + ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Added: %s to %s@%s/%s\n", target, blade_protocol_name_get(bp), blade_realm_name_get(br), blade_channel_name_get(bc)); + } + } done: - ks_pool_free(&key); - - ks_hash_read_unlock(bmmgr->protocols); + if (bc) blade_channel_write_unlock(bc); + if (bp) blade_protocol_read_unlock(bp); + ks_hash_read_unlock(bmmgr->realms); return ret; } -KS_DECLARE(ks_bool_t) blade_mastermgr_channel_verify(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *channel, const char *target) +KS_DECLARE(ks_bool_t) blade_mastermgr_realm_protocol_channel_authorization_verify(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *channel, const char *target) { ks_bool_t ret = KS_FALSE; + blade_realm_t *br = NULL; blade_protocol_t *bp = NULL; - char *key = NULL; - //ks_hash_t *cleanup = NULL; + blade_channel_t *bc = NULL; ks_assert(bmmgr); - ks_assert(protocol); ks_assert(realm); + ks_assert(protocol); ks_assert(channel); ks_assert(target); - key = ks_psprintf(ks_pool_get(bmmgr), "%s@%s", protocol, realm); + ks_hash_read_lock(bmmgr->realms); - bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)key, KS_READLOCKED); - if (!bp) goto done; + br = (blade_realm_t *)ks_hash_search(bmmgr->realms, (void *)realm, KS_UNLOCKED); + if (!br) { + ret = KS_STATUS_FAIL; + goto done; + } - ret = blade_protocol_channel_verify(bp, channel, target); + bp = blade_realm_protocol_lookup(br, protocol, KS_FALSE); + if (!bp) { + ret = KS_STATUS_NOT_FOUND; + goto done; + } + + bc = blade_protocol_channel_lookup(bp, channel, KS_FALSE); + if (!bc) { + ret = KS_STATUS_NOT_FOUND; + goto done; + } + + ret = blade_channel_authorization_verify(bc, target); + + blade_protocol_read_unlock(bp); done: - ks_pool_free(&key); - - ks_hash_read_unlock(bmmgr->protocols); + if (bc) blade_channel_read_unlock(bc); + if (bp) blade_protocol_read_unlock(bp); + ks_hash_read_unlock(bmmgr->realms); return ret; } diff --git a/libs/libblade/src/blade_module_master.c b/libs/libblade/src/blade_module_master.c deleted file mode 100644 index fc3163e944..0000000000 --- a/libs/libblade/src/blade_module_master.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2017, Shane Bryldt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "blade.h" - -typedef struct blade_module_master_s blade_module_master_t; - -struct blade_module_master_s { - blade_handle_t *handle; - ks_pool_t *pool; - blade_module_t *module; - - blade_space_t *blade_space; - blade_space_t *blade_application_space; -}; - - -ks_bool_t blade_register_request_handler(blade_module_t *bm, blade_request_t *breq); -// @todo blade_unregister_request_handler for more graceful shutdowns which intend to disconnect, and won't reconnect, which expire a session immediately -ks_bool_t blade_application_register_request_handler(blade_module_t *bm, blade_request_t *breq); // @todo response of registration indicates if you are the primary, or a slave -// @todo blade_application_unregister_request_handler for ability to unregister a slave (or primary) from the application, upon last node unregistering, the application entry would be automatically destroyed -// @todo event (or request to confirm acceptance with a response?) that allows a master to tell a slave it's the new primary for an application it has registered to provide when a primary disconnects, or a -// primary change is requested externally -// @todo to avoid a race condition, if a slave gets unexpected primary calls before being notified by an event, should it assume it has become the primary and not yet notified? - -static blade_module_callbacks_t g_module_master_callbacks = -{ - blade_module_master_on_startup, - blade_module_master_on_shutdown, -}; - - -static void blade_module_master_cleanup(ks_pool_t *pool, void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type) -{ - //blade_module_master_t *bm_master = (blade_module_master_t *)ptr; - - //ks_assert(bm_master); - - switch (action) { - case KS_MPCL_ANNOUNCE: - break; - case KS_MPCL_TEARDOWN: - break; - case KS_MPCL_DESTROY: - break; - } -} - -KS_DECLARE(ks_status_t) blade_module_master_create(blade_module_t **bmP, blade_handle_t *bh) -{ - blade_module_master_t *bm_master = NULL; - ks_pool_t *pool = NULL; - - ks_assert(bmP); - ks_assert(bh); - - ks_pool_open(&pool); - ks_assert(pool); - - bm_master = ks_pool_alloc(pool, sizeof(blade_module_master_t)); - bm_master->handle = bh; - bm_master->pool = pool; - - blade_module_create(&bm_master->module, bh, pool, bm_master, &g_module_master_callbacks); - - ks_pool_set_cleanup(pool, bm_master, NULL, blade_module_master_cleanup); - - ks_log(KS_LOG_DEBUG, "Created\n"); - - *bmP = bm_master->module; - - return KS_STATUS_SUCCESS; -} - - -ks_status_t blade_module_master_config(blade_module_master_t *bm_master, config_setting_t *config) -{ - ks_assert(bm_master); - ks_assert(config); - - ks_log(KS_LOG_DEBUG, "Configured\n"); - - return KS_STATUS_SUCCESS; -} - -KS_DECLARE(ks_status_t) blade_module_master_on_startup(blade_module_t *bm, config_setting_t *config) -{ - blade_module_master_t *bm_master = NULL; - blade_space_t *space = NULL; - blade_method_t *method = NULL; - - ks_assert(bm); - ks_assert(config); - - bm_master = (blade_module_master_t *)blade_module_data_get(bm); - - if (blade_module_master_config(bm_master, config) != KS_STATUS_SUCCESS) { - ks_log(KS_LOG_DEBUG, "blade_module_master_config failed\n"); - return KS_STATUS_FAIL; - } - - blade_space_create(&space, bm_master->handle, bm, "blade"); - ks_assert(space); - - bm_master->blade_space = space; - - blade_method_create(&method, space, "register", blade_register_request_handler); - ks_assert(method); - blade_space_methods_add(space, method); - - blade_handle_space_register(space); - - - blade_space_create(&space, bm_master->handle, bm, "blade.application"); - ks_assert(space); - - bm_master->blade_application_space = space; - - blade_method_create(&method, space, "register", blade_application_register_request_handler); - ks_assert(method); - blade_space_methods_add(space, method); - - blade_handle_space_register(space); - - - ks_log(KS_LOG_DEBUG, "Started\n"); - - return KS_STATUS_SUCCESS; -} - -KS_DECLARE(ks_status_t) blade_module_master_on_shutdown(blade_module_t *bm) -{ - blade_module_master_t *bm_master = NULL; - - ks_assert(bm); - - bm_master = (blade_module_master_t *)blade_module_data_get(bm); - - if (bm_master->blade_application_space) blade_handle_space_unregister(bm_master->blade_application_space); - if (bm_master->blade_space) blade_handle_space_unregister(bm_master->blade_space); - - ks_log(KS_LOG_DEBUG, "Stopped\n"); - - return KS_STATUS_SUCCESS; -} - -ks_bool_t blade_register_request_handler(blade_module_t *bm, blade_request_t *breq) -{ - blade_module_master_t *bm_master = NULL; - blade_session_t *bs = NULL; - cJSON *params = NULL; - cJSON *res = NULL; - const char *params_identity = NULL; - const char *identity = NULL; - - ks_assert(bm); - ks_assert(breq); - - ks_log(KS_LOG_DEBUG, "Request Received!\n"); - - bm_master = (blade_module_master_t *)blade_module_data_get(bm); - ks_assert(bm_master); - - bs = blade_handle_sessions_get(breq->handle, breq->session_id); - ks_assert(bs); - - blade_session_properties_write_lock(bs, KS_TRUE); - - params = cJSON_GetObjectItem(breq->message, "params"); // @todo cache this in blade_request_t for quicker/easier access - if (!params) { - ks_log(KS_LOG_DEBUG, "Session (%s) attempted to register with no 'params' object\n", blade_session_id_get(bs)); - blade_rpc_error_create(&res, NULL, breq->message_id, -32602, "Missing params object"); - } - else if (!(params_identity = cJSON_GetObjectCstr(params, "identity"))) { - ks_log(KS_LOG_DEBUG, "Session (%s) attempted to register with no 'identity'\n", blade_session_id_get(bs)); - blade_rpc_error_create(&res, NULL, breq->message_id, -32602, "Missing params identity string"); - } else { - identity = blade_session_identity_get(bs); - if (identity && identity[0]) { - ks_log(KS_LOG_DEBUG, "Session (%s) attempted to register with master but is already registered as %s\n", blade_session_id_get(bs), identity); - blade_rpc_error_create(&res, NULL, breq->message_id, -1000, "Already registered"); - } else { - // @todo plug in authentication to confirm if this registration is permitted, just allow it for now as long as it's not already in use - - blade_rpc_response_create(&res, NULL, breq->message_id); - - // @todo this is completely unfinished, return to finish this after catching up other changes - //blade_handle_session_identify(bh, identity, bs); - //blade_session_identity_set(bs, params_identity); - } - } - - blade_session_properties_write_unlock(bs); - - blade_session_send(bs, res, NULL); - - blade_session_read_unlock(bs); - - cJSON_Delete(res); - - return KS_FALSE; -} - -ks_bool_t blade_application_register_request_handler(blade_module_t *bm, blade_request_t *breq) -{ - blade_module_master_t *bm_master = NULL; - blade_session_t *bs = NULL; - //cJSON *res = NULL; - - ks_assert(bm); - ks_assert(breq); - - ks_log(KS_LOG_DEBUG, "Request Received!\n"); - - bm_master = (blade_module_master_t *)blade_module_data_get(bm); - ks_assert(bm_master); - - bs = blade_handle_sessions_get(breq->handle, breq->session_id); - ks_assert(bs); - - //blade_rpc_error_create(&res, NULL, breq->message_id, -10000, "???"); - //blade_rpc_response_create(&res, NULL, breq->message_id); - - - //blade_session_send(bs, res, NULL); - - blade_session_read_unlock(bs); - - //cJSON_Delete(res); - - return KS_FALSE; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libblade/src/blade_protocol.c b/libs/libblade/src/blade_protocol.c index e3de68a77f..79efbf1895 100644 --- a/libs/libblade/src/blade_protocol.c +++ b/libs/libblade/src/blade_protocol.c @@ -34,8 +34,9 @@ #include "blade.h" struct blade_protocol_s { + blade_realm_t *realm; const char *name; - const char *realm; + ks_rwl_t *lock; ks_hash_t *controllers; ks_hash_t *channels; // @todo descriptors (schema, etc) for each method within a protocol @@ -53,7 +54,7 @@ static void blade_protocol_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_ break; case KS_MPCL_TEARDOWN: if (bp->name) ks_pool_free(&bp->name); - if (bp->realm) ks_pool_free(&bp->realm); + if (bp->lock) ks_rwl_destroy(&bp->lock); if (bp->controllers) ks_hash_destroy(&bp->controllers); if (bp->channels) ks_hash_destroy(&bp->channels); break; @@ -62,18 +63,21 @@ static void blade_protocol_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_ } } -KS_DECLARE(ks_status_t) blade_protocol_create(blade_protocol_t **bpP, ks_pool_t *pool, const char *name, const char *realm) +KS_DECLARE(ks_status_t) blade_protocol_create(blade_protocol_t **bpP, ks_pool_t *pool, blade_realm_t *realm, const char *name) { blade_protocol_t *bp = NULL; ks_assert(bpP); ks_assert(pool); - ks_assert(name); ks_assert(realm); + ks_assert(name); bp = ks_pool_alloc(pool, sizeof(blade_protocol_t)); + bp->realm = realm; bp->name = ks_pstrdup(pool, name); - bp->realm = ks_pstrdup(pool, realm); + + ks_rwl_create(&bp->lock, pool); + ks_assert(bp->lock); ks_hash_create(&bp->controllers, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool); ks_assert(bp->controllers); @@ -98,16 +102,40 @@ KS_DECLARE(ks_status_t) blade_protocol_destroy(blade_protocol_t **bpP) return KS_STATUS_SUCCESS; } +KS_DECLARE(blade_realm_t *) blade_protocol_realm_get(blade_protocol_t *bp) +{ + ks_assert(bp); + return bp->realm; +} + KS_DECLARE(const char *) blade_protocol_name_get(blade_protocol_t *bp) { ks_assert(bp); return bp->name; } -KS_DECLARE(const char *) blade_protocol_realm_get(blade_protocol_t *bp) +KS_DECLARE(ks_status_t) blade_protocol_read_lock(blade_protocol_t *bp) { ks_assert(bp); - return bp->realm; + return ks_rwl_read_lock(bp->lock); +} + +KS_DECLARE(ks_status_t) blade_protocol_read_unlock(blade_protocol_t *bp) +{ + ks_assert(bp); + return ks_rwl_read_unlock(bp->lock); +} + +KS_DECLARE(ks_status_t) blade_protocol_write_lock(blade_protocol_t *bp) +{ + ks_assert(bp); + return ks_rwl_write_lock(bp->lock); +} + +KS_DECLARE(ks_status_t) blade_protocol_write_unlock(blade_protocol_t *bp) +{ + ks_assert(bp); + return ks_rwl_write_unlock(bp->lock); } KS_DECLARE(ks_bool_t) blade_protocol_purge(blade_protocol_t *bp, const char *nodeid) @@ -124,7 +152,7 @@ KS_DECLARE(ks_bool_t) blade_protocol_purge(blade_protocol_t *bp, const char *nod ks_hash_this(it, (const void **)&key, NULL, (void **)&authorizations); if (ks_hash_remove(authorizations, (void *)nodeid)) { - ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Removed: %s from %s@%s/%s\n", nodeid, bp->name, bp->realm, key); + ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Removed: %s from %s@%s/%s\n", nodeid, bp->name, blade_realm_name_get(bp->realm), key); } } ks_hash_write_unlock(bp->channels); @@ -152,6 +180,19 @@ KS_DECLARE(cJSON *) blade_protocol_controller_pack(blade_protocol_t *bp) return controllers; } +KS_DECLARE(ks_bool_t) blade_protocol_controller_verify(blade_protocol_t *bp, const char *controller) +{ + ks_bool_t ret = KS_FALSE; + + ks_assert(bp); + ks_assert(controller); + + ret = (ks_bool_t)(uintptr_t)ks_hash_search(bp->controllers, controller, KS_READLOCKED); + ks_hash_read_unlock(bp->controllers); + + return ret; +} + KS_DECLARE(ks_status_t) blade_protocol_controller_add(blade_protocol_t *bp, const char *nodeid) { char *key = NULL; @@ -162,7 +203,7 @@ KS_DECLARE(ks_status_t) blade_protocol_controller_add(blade_protocol_t *bp, cons key = ks_pstrdup(ks_pool_get(bp), nodeid); ks_hash_insert(bp->controllers, (void *)key, (void *)KS_TRUE); - ks_log(KS_LOG_DEBUG, "Protocol Controller Added: %s to %s@%s\n", nodeid, bp->name, bp->realm); + ks_log(KS_LOG_DEBUG, "Protocol Controller Added: %s to %s@%s\n", nodeid, bp->name, blade_realm_name_get(bp->realm)); return KS_STATUS_SUCCESS; } @@ -177,7 +218,7 @@ KS_DECLARE(ks_bool_t) blade_protocol_controller_remove(blade_protocol_t *bp, con ks_hash_write_lock(bp->controllers); if (ks_hash_remove(bp->controllers, (void *)nodeid)) { ret = KS_TRUE; - ks_log(KS_LOG_DEBUG, "Protocol Controller Removed: %s from %s@%s\n", nodeid, bp->name, bp->realm); + ks_log(KS_LOG_DEBUG, "Protocol Controller Removed: %s from %s@%s\n", nodeid, bp->name, blade_realm_name_get(bp->realm)); } ks_hash_write_unlock(bp->controllers); @@ -190,31 +231,43 @@ KS_DECLARE(ks_bool_t) blade_protocol_controller_available(blade_protocol_t *bp) return ks_hash_count(bp->controllers) > 0; } -KS_DECLARE(ks_status_t) blade_protocol_channel_add(blade_protocol_t *bp, const char *name) +KS_DECLARE(blade_channel_t *) blade_protocol_channel_lookup(blade_protocol_t *bp, const char *channel, ks_bool_t writelocked) +{ + blade_channel_t *bc = NULL; + + ks_assert(bp); + ks_assert(channel); + + bc = (blade_channel_t *)ks_hash_search(bp->channels, (void *)channel, KS_READLOCKED); + if (bc) { + if (writelocked) blade_channel_write_lock(bc); + else blade_channel_read_lock(bc); + } + ks_hash_read_unlock(bp->channels); + + return bc; +} + +KS_DECLARE(ks_status_t) blade_protocol_channel_add(blade_protocol_t *bp, blade_channel_t *channel) { ks_status_t ret = KS_STATUS_SUCCESS; ks_pool_t *pool = NULL; - ks_hash_t *authorized = NULL; char *key = NULL; ks_assert(bp); - ks_assert(name); + ks_assert(channel); pool = ks_pool_get(bp); ks_hash_write_lock(bp->channels); - if (ks_hash_search(bp->channels, (void *)name, KS_UNLOCKED)) { + if (ks_hash_search(bp->channels, (void *)blade_channel_name_get(channel), KS_UNLOCKED)) { ret = KS_STATUS_DUPLICATE_OPERATION; goto done; } - ks_hash_create(&authorized, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool); - - key = ks_pstrdup(pool, name); - ks_hash_insert(bp->channels, (void *)key, (void *)authorized); - - ks_log(KS_LOG_DEBUG, "Protocol Channel Added: %s to %s@%s\n", key, bp->name, bp->realm); + key = ks_pstrdup(pool, blade_channel_name_get(channel)); + ks_hash_insert(bp->channels, (void *)key, (void *)channel); done: @@ -223,79 +276,12 @@ done: return ret; } -KS_DECLARE(ks_bool_t) blade_protocol_channel_remove(blade_protocol_t *bp, const char *name) +KS_DECLARE(ks_bool_t) blade_protocol_channel_remove(blade_protocol_t *bp, const char *channel) { - ks_bool_t ret = KS_FALSE; - ks_hash_t *authorized = NULL; - - ks_assert(bp); - ks_assert(name); - - ks_hash_write_lock(bp->channels); - if ((authorized = ks_hash_remove(bp->channels, (void *)name))) { - ret = KS_TRUE; - ks_log(KS_LOG_DEBUG, "Protocol Channel Removed: %s from %s@%s\n", name, bp->name, bp->realm); - ks_hash_destroy(&authorized); - } - ks_hash_write_unlock(bp->channels); - - return ret; -} - -KS_DECLARE(ks_status_t) blade_protocol_channel_authorize(blade_protocol_t *bp, ks_bool_t remove, const char *channel, const char *controller, const char *target) -{ - ks_status_t ret = KS_STATUS_SUCCESS; - ks_hash_t *authorizations = NULL; - ks_bool_t allowed = KS_FALSE; - ks_assert(bp); ks_assert(channel); - ks_assert(controller); - ks_assert(target); - allowed = (ks_bool_t)(intptr_t)ks_hash_search(bp->controllers, (void *)controller, KS_READLOCKED); - ks_hash_read_unlock(bp->controllers); - - if (!allowed) { - ret = KS_STATUS_NOT_ALLOWED; - goto done; - } - - // @todo verify controller, get ks_hash_t* value based on channel, add target to the channels hash - authorizations = (ks_hash_t *)ks_hash_search(bp->channels, (void *)channel, KS_READLOCKED); - if (authorizations) { - if (remove) { - if (ks_hash_remove(authorizations, (void *)target)) { - ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Removed: %s from %s@%s/%s\n", target, bp->name, bp->realm, channel); - } else ret = KS_STATUS_NOT_FOUND; - } else { - ks_hash_insert(authorizations, (void *)ks_pstrdup(ks_pool_get(bp), target), (void *)KS_TRUE); - ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Added: %s to %s@%s/%s\n", target, bp->name, bp->realm, channel); - } - } - ks_hash_read_unlock(bp->channels); - - if (!authorizations) ret = KS_STATUS_NOT_FOUND; - -done: - return ret; -} - -KS_DECLARE(ks_bool_t) blade_protocol_channel_verify(blade_protocol_t *bp, const char *channel, const char *target) -{ - ks_bool_t ret = KS_FALSE; - ks_hash_t *authorizations = NULL; - - ks_assert(bp); - ks_assert(channel); - ks_assert(target); - - // @todo verify controller, get ks_hash_t* value based on channel, add target to the channels hash - authorizations = (ks_hash_t *)ks_hash_search(bp->channels, (void *)channel, KS_READLOCKED); - if (authorizations) ret = ks_hash_search(authorizations, (void *)target, KS_UNLOCKED) != NULL; - ks_hash_read_unlock(bp->channels); - - return ret; + return ks_hash_remove(bp->channels, (void *)channel) != NULL; } /* For Emacs: diff --git a/libs/libblade/src/blade_realm.c b/libs/libblade/src/blade_realm.c new file mode 100644 index 0000000000..149b57e66e --- /dev/null +++ b/libs/libblade/src/blade_realm.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2017, Shane Bryldt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "blade.h" + +struct blade_realm_s { + const char *name; + ks_rwl_t *lock; + ks_hash_t *protocols; +}; + + +static void blade_realm_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type) +{ + blade_realm_t *br = (blade_realm_t *)ptr; + + ks_assert(br); + + switch (action) { + case KS_MPCL_ANNOUNCE: + break; + case KS_MPCL_TEARDOWN: + if (br->name) ks_pool_free(&br->name); + if (br->lock) ks_rwl_destroy(&br->lock); + if (br->protocols) ks_hash_destroy(&br->protocols); + break; + case KS_MPCL_DESTROY: + break; + } +} + +KS_DECLARE(ks_status_t) blade_realm_create(blade_realm_t **brP, ks_pool_t *pool, const char *name) +{ + blade_realm_t *br = NULL; + + ks_assert(brP); + ks_assert(pool); + ks_assert(name); + + br = ks_pool_alloc(pool, sizeof(blade_realm_t)); + br->name = ks_pstrdup(pool, name); + + ks_rwl_create(&br->lock, pool); + ks_assert(br->lock); + + ks_hash_create(&br->protocols, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY | KS_HASH_FLAG_FREE_VALUE, pool); + ks_assert(br->protocols); + + ks_pool_set_cleanup(br, NULL, blade_realm_cleanup); + + *brP = br; + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(ks_status_t) blade_realm_destroy(blade_realm_t **brP) +{ + ks_assert(brP); + ks_assert(*brP); + + ks_pool_free(brP); + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(const char *) blade_realm_name_get(blade_realm_t *br) +{ + ks_assert(br); + return br->name; +} + +KS_DECLARE(ks_status_t) blade_realm_read_lock(blade_realm_t *br) +{ + ks_assert(br); + return ks_rwl_read_lock(br->lock); +} + +KS_DECLARE(ks_status_t) blade_realm_read_unlock(blade_realm_t *br) +{ + ks_assert(br); + return ks_rwl_read_unlock(br->lock); +} + +KS_DECLARE(ks_status_t) blade_realm_write_lock(blade_realm_t *br) +{ + ks_assert(br); + return ks_rwl_write_lock(br->lock); +} + +KS_DECLARE(ks_status_t) blade_realm_write_unlock(blade_realm_t *br) +{ + ks_assert(br); + return ks_rwl_write_unlock(br->lock); +} + +KS_DECLARE(ks_hash_iterator_t *) blade_realm_protocols_iterator(blade_realm_t *br, ks_locked_t locked) +{ + ks_assert(br); + return ks_hash_first(br->protocols, locked); +} + +KS_DECLARE(blade_protocol_t *) blade_realm_protocol_lookup(blade_realm_t *br, const char *protocol, ks_bool_t writelocked) +{ + blade_protocol_t *bp = NULL; + + ks_assert(br); + ks_assert(protocol); + + bp = (blade_protocol_t *)ks_hash_search(br->protocols, (void *)protocol, KS_READLOCKED); + if (bp) { + if (writelocked) blade_protocol_write_lock(bp); + else blade_protocol_read_lock(bp); + } + ks_hash_read_unlock(br->protocols); + + return bp; +} + +KS_DECLARE(ks_status_t) blade_realm_protocol_add(blade_realm_t *br, blade_protocol_t *protocol) +{ + ks_assert(br); + ks_assert(protocol); + + ks_hash_insert(br->protocols, (void *)ks_pstrdup(ks_pool_get(br), blade_protocol_name_get(protocol)), (void *)protocol); + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(ks_status_t) blade_realm_protocol_remove(blade_realm_t *br, const char *protocol) +{ + ks_assert(br); + ks_assert(protocol); + + ks_hash_remove(br->protocols, (void *)protocol); + + return KS_STATUS_SUCCESS; +} + + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: + */ diff --git a/libs/libblade/src/blade_routemgr.c b/libs/libblade/src/blade_routemgr.c index 5aceafd18b..277908a599 100644 --- a/libs/libblade/src/blade_routemgr.c +++ b/libs/libblade/src/blade_routemgr.c @@ -141,6 +141,13 @@ KS_DECLARE(ks_status_t) blade_routemgr_route_add(blade_routemgr_t *brmgr, const blade_handle_rpcregister(brmgr->handle, target, KS_FALSE, NULL, NULL); + if (blade_upstreammgr_masterlocal(blade_handle_upstreammgr_get(brmgr->handle))) { + cJSON *params = cJSON_CreateObject(); + cJSON_AddStringToObject(params, "nodeid", target); + blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(brmgr->handle), BLADE_RPCBROADCAST_COMMAND_EVENT, NULL, "presence", "blade", "join", "joined", params, NULL, NULL); + cJSON_Delete(params); + } + return KS_STATUS_SUCCESS; } @@ -165,6 +172,13 @@ KS_DECLARE(ks_status_t) blade_routemgr_route_remove(blade_routemgr_t *brmgr, con blade_mastermgr_purge(blade_handle_mastermgr_get(brmgr->handle), target); + if (blade_upstreammgr_masterlocal(blade_handle_upstreammgr_get(brmgr->handle))) { + cJSON *params = cJSON_CreateObject(); + cJSON_AddStringToObject(params, "nodeid", target); + blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(brmgr->handle), BLADE_RPCBROADCAST_COMMAND_EVENT, NULL, "presence", "blade", "leave", "left", params, NULL, NULL); + cJSON_Delete(params); + } + return KS_STATUS_SUCCESS; } diff --git a/libs/libblade/src/blade_session.c b/libs/libblade/src/blade_session.c index 700c66bab0..462c4713a4 100644 --- a/libs/libblade/src/blade_session.c +++ b/libs/libblade/src/blade_session.c @@ -49,7 +49,6 @@ struct blade_session_s { ks_q_t *sending; ks_q_t *receiving; - ks_hash_t *realms; ks_hash_t *routes; cJSON *properties; @@ -115,9 +114,6 @@ KS_DECLARE(ks_status_t) blade_session_create(blade_session_t **bsP, blade_handle ks_q_create(&bs->receiving, pool, 0); ks_assert(bs->receiving); - ks_hash_create(&bs->realms, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool); - ks_assert(bs->realms); - ks_hash_create(&bs->routes, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool); ks_assert(bs->routes); @@ -225,35 +221,6 @@ KS_DECLARE(blade_session_state_t) blade_session_state_get(blade_session_t *bs) return bs->state; } -KS_DECLARE(ks_status_t) blade_session_realm_add(blade_session_t *bs, const char *realm) -{ - char *key = NULL; - - ks_assert(bs); - ks_assert(realm); - - key = ks_pstrdup(ks_pool_get(bs), realm); - ks_hash_insert(bs->realms, (void *)key, (void *)KS_TRUE); - - return KS_STATUS_SUCCESS; -} - -KS_DECLARE(ks_status_t) blade_session_realm_remove(blade_session_t *bs, const char *realm) -{ - ks_assert(bs); - ks_assert(realm); - - ks_hash_remove(bs->realms, (void *)realm); - - return KS_STATUS_SUCCESS; -} - -KS_DECLARE(ks_hash_t *) blade_session_realms_get(blade_session_t *bs) -{ - ks_assert(bs); - return bs->realms; -} - KS_DECLARE(ks_status_t) blade_session_route_add(blade_session_t *bs, const char *nodeid) { char *key = NULL; diff --git a/libs/libblade/src/blade_sessionmgr.c b/libs/libblade/src/blade_sessionmgr.c index e231b2eb1e..5e13bc69a2 100644 --- a/libs/libblade/src/blade_sessionmgr.c +++ b/libs/libblade/src/blade_sessionmgr.c @@ -197,7 +197,6 @@ KS_DECLARE(ks_status_t) blade_sessionmgr_session_remove(blade_sessionmgr_t *bsmg if (blade_upstreammgr_localid_compare(blade_handle_upstreammgr_get(bsmgr->handle), id)) { blade_upstreammgr_localid_set(blade_handle_upstreammgr_get(bsmgr->handle), NULL); blade_upstreammgr_masterid_set(blade_handle_upstreammgr_get(bsmgr->handle), NULL); - blade_upstreammgr_realm_clear(blade_handle_upstreammgr_get(bsmgr->handle)); } blade_session_write_unlock(bs); diff --git a/libs/libblade/src/blade_stack.c b/libs/libblade/src/blade_stack.c index 315c4f7215..929c6cb592 100644 --- a/libs/libblade/src/blade_stack.c +++ b/libs/libblade/src/blade_stack.c @@ -157,12 +157,6 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP) ks_status_t blade_handle_config(blade_handle_t *bh, config_setting_t *config) { - config_setting_t *master = NULL; - config_setting_t *master_nodeid = NULL; - config_setting_t *master_realms = NULL; - const char *nodeid = NULL; - int32_t realms_length = 0; - ks_assert(bh); if (!config) return KS_STATUS_FAIL; @@ -171,30 +165,6 @@ ks_status_t blade_handle_config(blade_handle_t *bh, config_setting_t *config) return KS_STATUS_FAIL; } - master = config_setting_get_member(config, "master"); - if (master) { - master_nodeid = config_lookup_from(master, "nodeid"); - if (master_nodeid) { - if (config_setting_type(master_nodeid) != CONFIG_TYPE_STRING) return KS_STATUS_FAIL; - nodeid = config_setting_get_string(master_nodeid); - - blade_upstreammgr_localid_set(bh->upstreammgr, nodeid); - blade_upstreammgr_masterid_set(bh->upstreammgr, nodeid); - } - master_realms = config_lookup_from(master, "realms"); - if (master_realms) { - if (config_setting_type(master_realms) != CONFIG_TYPE_LIST) return KS_STATUS_FAIL; - realms_length = config_setting_length(master_realms); - if (realms_length > 0) { - for (int32_t index = 0; index < realms_length; ++index) { - const char *realm = config_setting_get_string_elem(master_realms, index); - if (!realm) return KS_STATUS_FAIL; - blade_upstreammgr_realm_add(bh->upstreammgr, realm); - } - } - } - } - return KS_STATUS_SUCCESS; } @@ -242,6 +212,8 @@ KS_DECLARE(ks_status_t) blade_handle_startup(blade_handle_t *bh, config_setting_ blade_transportmgr_startup(bh->transportmgr, config); + blade_mastermgr_startup(bh->mastermgr, config); + return KS_STATUS_SUCCESS; } @@ -249,6 +221,8 @@ KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh) { ks_assert(bh); + blade_mastermgr_shutdown(bh->mastermgr); + blade_transportmgr_shutdown(bh->transportmgr); blade_connectionmgr_shutdown(bh->connectionmgr); @@ -653,22 +627,22 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d // @todo switch on publish command, make the following code for add_protocol switch (command) { case BLADE_RPCPUBLISH_COMMAND_CONTROLLER_ADD: - blade_mastermgr_controller_add(bh->mastermgr, req_params_protocol, req_params_realm, req_params_requester_nodeid); + blade_mastermgr_realm_protocol_controller_add(bh->mastermgr, req_params_realm, req_params_protocol, req_params_requester_nodeid); if (req_params_channels) { cJSON *element = NULL; cJSON_ArrayForEach(element, req_params_channels) { - blade_mastermgr_channel_add(bh->mastermgr, req_params_protocol, req_params_realm, element->valuestring); + blade_mastermgr_realm_protocol_channel_add(bh->mastermgr, req_params_realm, req_params_protocol, element->valuestring); } } break; case BLADE_RPCPUBLISH_COMMAND_CONTROLLER_REMOVE: - blade_mastermgr_controller_remove(bh->mastermgr, req_params_protocol, req_params_realm, req_params_requester_nodeid); + blade_mastermgr_realm_protocol_controller_remove(bh->mastermgr, req_params_realm, req_params_protocol, req_params_requester_nodeid); break; case BLADE_RPCPUBLISH_COMMAND_CHANNEL_ADD: if (req_params_channels) { cJSON *element = NULL; cJSON_ArrayForEach(element, req_params_channels) { - blade_mastermgr_channel_add(bh->mastermgr, req_params_protocol, req_params_realm, element->valuestring); + blade_mastermgr_realm_protocol_channel_add(bh->mastermgr, req_params_realm, req_params_protocol, element->valuestring); } } break; @@ -676,7 +650,7 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d if (req_params_channels) { cJSON *element = NULL; cJSON_ArrayForEach(element, req_params_channels) { - blade_mastermgr_channel_remove(bh->mastermgr, req_params_protocol, req_params_realm, element->valuestring); + blade_mastermgr_realm_protocol_channel_remove(bh->mastermgr, req_params_realm, req_params_protocol, element->valuestring); } } break; @@ -889,7 +863,7 @@ ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void blade_rpc_response_raw_create(&res, &res_result, blade_rpc_request_messageid_get(brpcreq)); cJSON_ArrayForEach(channel, req_params_channels) { - if (blade_mastermgr_channel_authorize(bh->mastermgr, remove, req_params_protocol, req_params_realm, channel->valuestring, req_params_requester_nodeid, req_params_authorized_nodeid) == KS_STATUS_SUCCESS) { + if (blade_mastermgr_realm_protocol_channel_authorize(bh->mastermgr, remove, req_params_realm, req_params_protocol, channel->valuestring, req_params_requester_nodeid, req_params_authorized_nodeid) == KS_STATUS_SUCCESS) { if (remove) { if (!res_result_unauthorized_channels) res_result_unauthorized_channels = cJSON_CreateArray(); cJSON_AddItemToArray(res_result_unauthorized_channels, cJSON_CreateString(channel->valuestring)); @@ -1060,8 +1034,11 @@ ks_bool_t blade_rpclocate_request_handler(blade_rpc_request_t *brpcreq, void *da ks_log(KS_LOG_DEBUG, "Session (%s) locate request (%s to %s) processing\n", blade_session_id_get(bs), req_params_requester_nodeid, req_params_responder_nodeid); - bp = blade_mastermgr_protocol_lookup(bh->mastermgr, req_params_protocol, req_params_realm); - if (bp) res_result_controllers = blade_protocol_controller_pack(bp); + bp = blade_mastermgr_realm_protocol_lookup(bh->mastermgr, req_params_realm, req_params_protocol, KS_FALSE); + if (bp) { + res_result_controllers = blade_protocol_controller_pack(bp); + blade_protocol_read_unlock(bp); + } // build the actual response finally @@ -1630,7 +1607,7 @@ ks_bool_t blade_rpcsubscribe_request_handler(blade_rpc_request_t *brpcreq, void cJSON *channel = NULL; cJSON_ArrayForEach(channel, req_params_channels) { - if (blade_mastermgr_channel_verify(bh->mastermgr, req_params_protocol, req_params_realm, channel->valuestring, req_params_subscriber_nodeid)) { + if (blade_mastermgr_realm_protocol_channel_authorization_verify(bh->mastermgr, req_params_realm, req_params_protocol, channel->valuestring, req_params_subscriber_nodeid)) { blade_subscriptionmgr_subscriber_add(bh->subscriptionmgr, NULL, req_params_protocol, req_params_realm, channel->valuestring, req_params_subscriber_nodeid); if (!res_result_subscribe_channels) res_result_subscribe_channels = cJSON_CreateArray(); cJSON_AddItemToArray(res_result_subscribe_channels, cJSON_CreateString(channel->valuestring)); @@ -1926,6 +1903,66 @@ done: return ret; } +KS_DECLARE(const char *) blade_rpcbroadcast_request_realm_get(blade_rpc_request_t *brpcreq) +{ + cJSON *req = NULL; + const char *req_realm = NULL; + + ks_assert(brpcreq); + + req = blade_rpc_request_message_get(brpcreq); + ks_assert(req); + + req_realm = cJSON_GetObjectCstr(req, "realm"); + + return req_realm; +} + +KS_DECLARE(const char *) blade_rpcbroadcast_request_protocol_get(blade_rpc_request_t *brpcreq) +{ + cJSON *req = NULL; + const char *req_protocol = NULL; + + ks_assert(brpcreq); + + req = blade_rpc_request_message_get(brpcreq); + ks_assert(req); + + req_protocol = cJSON_GetObjectCstr(req, "protocol"); + + return req_protocol; +} + +KS_DECLARE(const char *) blade_rpcbroadcast_request_channel_get(blade_rpc_request_t *brpcreq) +{ + cJSON *req = NULL; + const char *req_channel = NULL; + + ks_assert(brpcreq); + + req = blade_rpc_request_message_get(brpcreq); + ks_assert(req); + + req_channel = cJSON_GetObjectCstr(req, "channel"); + + return req_channel; +} + +KS_DECLARE(const char *) blade_rpcbroadcast_request_event_get(blade_rpc_request_t *brpcreq) +{ + cJSON *req = NULL; + const char *req_event = NULL; + + ks_assert(brpcreq); + + req = blade_rpc_request_message_get(brpcreq); + ks_assert(req); + + req_event = cJSON_GetObjectCstr(req, "event"); + + return req_event; +} + KS_DECLARE(cJSON *) blade_rpcbroadcast_request_params_get(blade_rpc_request_t *brpcreq) { cJSON *req = NULL; @@ -1943,6 +1980,7 @@ KS_DECLARE(cJSON *) blade_rpcbroadcast_request_params_get(blade_rpc_request_t *b return req_params_params; } + /* For Emacs: * Local Variables: * mode:c diff --git a/libs/libblade/src/blade_transport_wss.c b/libs/libblade/src/blade_transport_wss.c index 90fac85dd8..db55ca4e44 100644 --- a/libs/libblade/src/blade_transport_wss.c +++ b/libs/libblade/src/blade_transport_wss.c @@ -213,6 +213,7 @@ ks_status_t blade_transport_wss_link_ssl_init(blade_transport_wss_link_t *btwssl cert = server ? btwssl->transport->endpoints_ssl_cert : btwssl->transport->ssl_cert; chain = server ? btwssl->transport->endpoints_ssl_chain : btwssl->transport->ssl_chain; + // @todo should actually error out if there is no key/cert/chain available, as SSL/TLS is meant to be mandatory if (key && cert) { btwssl->ssl = SSL_CTX_new(method); @@ -426,7 +427,7 @@ ks_status_t blade_transport_wss_onstartup(blade_transport_t *bt, config_setting_ btwss = (blade_transport_wss_t *)blade_transport_data_get(bt); if (blade_transport_wss_config(btwss, config) != KS_STATUS_SUCCESS) { - ks_log(KS_LOG_DEBUG, "blade_module_wss_config failed\n"); + ks_log(KS_LOG_DEBUG, "blade_transport_wss_config failed\n"); return KS_STATUS_FAIL; } @@ -826,7 +827,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_inbound(blade_ cJSON *json_res = NULL; cJSON *json_params = NULL; cJSON *json_result = NULL; - cJSON *json_result_realms = NULL; //cJSON *error = NULL; blade_session_t *bs = NULL; blade_handle_t *bh = NULL; @@ -837,8 +837,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_inbound(blade_ const char *nodeid = NULL; const char *master_nodeid = NULL; ks_time_t timeout; - ks_hash_iterator_t *it = NULL; - ks_hash_t *realms = NULL; ks_assert(bc); @@ -957,11 +955,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_inbound(blade_ // a "blade.register" is received the identity it carries affects these routes along with the sessionid of the downstream session it came through, and "blade.register" would also // result in the new identities being added as routes however new entire wildcard subrealm registration would require a special process for matching any identities from those subrealms blade_routemgr_route_add(blade_handle_routemgr_get(bh), nodeid, nodeid); - - // iterate and copy the realms ultimately provided by the master router node to the new downstream session, realms are obtained when establishing upstream sessions (see outbound handler), in - // the future this process can be adjusted based on authentication which is currently skipped, so for now if a master node provides more than a single realm then all provided realms will be - // acceptable for protocol publishing and passing to downstream sessions for their realms - blade_upstreammgr_realm_propagate(blade_handle_upstreammgr_get(bh), bs); } blade_rpc_response_raw_create(&json_res, &json_result, id); @@ -982,26 +975,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_inbound(blade_ cJSON_AddStringToObject(json_result, "master-nodeid", master_nodeid); ks_pool_free(&master_nodeid); - - // add the list of actual realms the local node will permit the remote node to register or route, this is the same list that the remote side would be adding to the handle with blade_handle_realm_add() - // and may contain additional subrealms that are explicitly registered by the remote node, this ensures upon reconnect that the same list of realms gets provided to the remote node to refresh - // the remote nodes local realms on the edge case that the session times out on the remote end while reconnecting - - json_result_realms = cJSON_CreateArray(); - cJSON_AddItemToObject(json_result, "realms", json_result_realms); - - realms = blade_session_realms_get(bs); - ks_hash_read_lock(realms); - for (it = ks_hash_first(realms, KS_UNLOCKED); it; it = ks_hash_next(&it)) { - void *key = NULL; - void *value = NULL; - - ks_hash_this(it, (const void **)&key, NULL, &value); - - cJSON_AddItemToArray(json_result_realms, cJSON_CreateString((const char *)key)); - } - ks_hash_read_unlock(realms); - // This starts the final process for associating the connection to the session, including for reconnecting to an existing session, this simply // associates the session to this connection, upon return the remainder of the association for the session to the connection is handled along // with making sure both this connection and the session state machines are in running states @@ -1041,8 +1014,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_outbound(blade const char *id = NULL; cJSON *json_error = NULL; cJSON *json_result = NULL; - cJSON *json_result_realms = NULL; - int json_result_realms_size = 0; const char *nodeid = NULL; const char *master_nodeid = NULL; blade_session_t *bs = NULL; @@ -1141,13 +1112,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_outbound(blade goto done; } - json_result_realms = cJSON_GetObjectItem(json_result, "realms"); - if (!json_result_realms || json_result_realms->type != cJSON_Array || (json_result_realms_size = cJSON_GetArraySize(json_result_realms)) <= 0) { - ks_log(KS_LOG_DEBUG, "Received message is missing 'realms'\n"); - ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT; - goto done; - } - // @todo validate uuid format by parsing, not currently available in uuid functions bs = blade_sessionmgr_session_lookup(blade_handle_sessionmgr_get(bh), nodeid); // bs comes out read locked if not null to prevent it being cleaned up before we are done @@ -1186,12 +1150,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_outbound(blade blade_sessionmgr_session_add(blade_handle_sessionmgr_get(bh), bs); blade_upstreammgr_masterid_set(blade_handle_upstreammgr_get(bh), master_nodeid); - - // iterate realms and register to handle as permitted realms for future registrations - for (int index = 0; index < json_result_realms_size; ++index) { - cJSON *elem = cJSON_GetArrayItem(json_result_realms, index); - blade_upstreammgr_realm_add(blade_handle_upstreammgr_get(bh), elem->valuestring); - } } blade_connection_session_set(bc, blade_session_id_get(bs)); diff --git a/libs/libblade/src/blade_upstreammgr.c b/libs/libblade/src/blade_upstreammgr.c index d7ba4bd9ec..bcdee57834 100644 --- a/libs/libblade/src/blade_upstreammgr.c +++ b/libs/libblade/src/blade_upstreammgr.c @@ -43,9 +43,6 @@ struct blade_upstreammgr_s { // master node id, provided by upstream "blade.connect" response const char *masterid; ks_rwl_t *masterid_rwl; - - // realms for new nodes, these originate from the master, and are provided by upstream session "blade.connect" response - ks_hash_t *realms; }; @@ -86,9 +83,6 @@ KS_DECLARE(ks_status_t) blade_upstreammgr_create(blade_upstreammgr_t **bumgrP, b ks_rwl_create(&bumgr->masterid_rwl, pool); ks_assert(bumgr->masterid_rwl); - ks_hash_create(&bumgr->realms, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool); - ks_assert(bumgr->realms); - ks_pool_set_cleanup(bumgr, NULL, blade_upstreammgr_cleanup); *bumgrP = bumgr; @@ -261,67 +255,6 @@ KS_DECLARE(ks_bool_t) blade_upstreammgr_masterlocal(blade_upstreammgr_t *bumgr) return ret; } -KS_DECLARE(ks_status_t) blade_upstreammgr_realm_add(blade_upstreammgr_t *bumgr, const char *realm) -{ - char *key = NULL; - - ks_assert(bumgr); - ks_assert(realm); - - key = ks_pstrdup(ks_pool_get(bumgr), realm); - ks_hash_insert(bumgr->realms, (void *)key, (void *)KS_TRUE); - - ks_log(KS_LOG_DEBUG, "Realm Added: %s\n", key); - - return KS_STATUS_SUCCESS; -} - -KS_DECLARE(ks_status_t) blade_upstreammgr_realm_remove(blade_upstreammgr_t *bumgr, const char *realm) -{ - ks_assert(bumgr); - ks_assert(realm); - - ks_hash_remove(bumgr->realms, (void *)realm); - - ks_log(KS_LOG_DEBUG, "Realm Removed: %s\n", realm); - - return KS_STATUS_SUCCESS; -} - -KS_DECLARE(ks_status_t) blade_upstreammgr_realm_clear(blade_upstreammgr_t *bumgr) -{ - ks_hash_iterator_t *it = NULL; - - ks_assert(bumgr); - - while ((it = ks_hash_first(bumgr->realms, KS_UNLOCKED))) { - void *key = NULL; - void *value = NULL; - ks_hash_this(it, (const void **)&key, NULL, &value); - ks_log(KS_LOG_DEBUG, "Realm Removed: %s\n", key); - ks_hash_remove(bumgr->realms, key); - } - - return KS_STATUS_SUCCESS; -} - -KS_DECLARE(ks_status_t) blade_upstreammgr_realm_propagate(blade_upstreammgr_t *bumgr, blade_session_t *bs) -{ - ks_assert(bumgr); - ks_assert(bs); - - ks_hash_read_lock(bumgr->realms); - for (ks_hash_iterator_t *it = ks_hash_first(bumgr->realms, KS_UNLOCKED); it; it = ks_hash_next(&it)) { - void *key = NULL; - void *value = NULL; - ks_hash_this(it, (const void **)&key, NULL, &value); - blade_session_realm_add(bs, (const char *)key); - } - ks_hash_read_unlock(bumgr->realms); - - return KS_STATUS_SUCCESS; -} - /* For Emacs: * Local Variables: * mode:c diff --git a/libs/libblade/src/include/blade.h b/libs/libblade/src/include/blade.h index 6c40661a78..eb5d7d222b 100644 --- a/libs/libblade/src/include/blade.h +++ b/libs/libblade/src/include/blade.h @@ -44,7 +44,9 @@ #include "blade_rpc.h" #include "blade_connection.h" #include "blade_session.h" +#include "blade_realm.h" #include "blade_protocol.h" +#include "blade_channel.h" #include "blade_subscription.h" #include "blade_tuple.h" diff --git a/libs/libblade/src/include/blade_module_master.h b/libs/libblade/src/include/blade_channel.h similarity index 66% rename from libs/libblade/src/include/blade_module_master.h rename to libs/libblade/src/include/blade_channel.h index ea896f270b..64885f6dd5 100644 --- a/libs/libblade/src/include/blade_module_master.h +++ b/libs/libblade/src/include/blade_channel.h @@ -1,23 +1,23 @@ /* * Copyright (c) 2017, Shane Bryldt * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -31,17 +31,21 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _BLADE_MODULE_MASTER_H_ -#define _BLADE_MODULE_MASTER_H_ +#ifndef _BLADE_CHANNEL_H_ +#define _BLADE_CHANNEL_H_ #include KS_BEGIN_EXTERN_C - -KS_DECLARE(ks_status_t) blade_module_master_create(blade_module_t **bmP, blade_handle_t *bh); - -KS_DECLARE(ks_status_t) blade_module_master_on_startup(blade_module_t *bm, config_setting_t *config); -KS_DECLARE(ks_status_t) blade_module_master_on_shutdown(blade_module_t *bm); - +KS_DECLARE(ks_status_t) blade_channel_create(blade_channel_t **bcP, ks_pool_t *pool, const char *name); +KS_DECLARE(ks_status_t) blade_channel_destroy(blade_channel_t **bcP); +KS_DECLARE(const char *) blade_channel_name_get(blade_channel_t *bc); +KS_DECLARE(ks_status_t) blade_channel_read_lock(blade_channel_t *bc); +KS_DECLARE(ks_status_t) blade_channel_read_unlock(blade_channel_t *bc); +KS_DECLARE(ks_status_t) blade_channel_write_lock(blade_channel_t *bc); +KS_DECLARE(ks_status_t) blade_channel_write_unlock(blade_channel_t *bc); +KS_DECLARE(ks_bool_t) blade_channel_authorization_verify(blade_channel_t *bc, const char *target); +KS_DECLARE(ks_status_t) blade_channel_authorization_add(blade_channel_t *bc, const char *target); +KS_DECLARE(ks_bool_t) blade_channel_authorization_remove(blade_channel_t *bc, const char *target); KS_END_EXTERN_C #endif diff --git a/libs/libblade/src/include/blade_mastermgr.h b/libs/libblade/src/include/blade_mastermgr.h index 50fd67cae2..12a97d220e 100644 --- a/libs/libblade/src/include/blade_mastermgr.h +++ b/libs/libblade/src/include/blade_mastermgr.h @@ -38,15 +38,19 @@ KS_BEGIN_EXTERN_C KS_DECLARE(ks_status_t) blade_mastermgr_create(blade_mastermgr_t **bmmgrP, blade_handle_t *bh); KS_DECLARE(ks_status_t) blade_mastermgr_destroy(blade_mastermgr_t **bmmgrP); +KS_DECLARE(ks_status_t) blade_mastermgr_startup(blade_mastermgr_t *bmmgr, config_setting_t *config); +KS_DECLARE(ks_status_t) blade_mastermgr_shutdown(blade_mastermgr_t *bmmgr); KS_DECLARE(blade_handle_t *) blade_mastermgr_handle_get(blade_mastermgr_t *bmmgr); KS_DECLARE(ks_status_t) blade_mastermgr_purge(blade_mastermgr_t *bmmgr, const char *nodeid); -KS_DECLARE(blade_protocol_t *) blade_mastermgr_protocol_lookup(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm); -KS_DECLARE(ks_status_t) blade_mastermgr_controller_add(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *controller); -KS_DECLARE(ks_status_t) blade_mastermgr_controller_remove(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *controller); -KS_DECLARE(ks_status_t) blade_mastermgr_channel_add(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *channel); -KS_DECLARE(ks_status_t) blade_mastermgr_channel_remove(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *channel); -KS_DECLARE(ks_status_t) blade_mastermgr_channel_authorize(blade_mastermgr_t *bmmgr, ks_bool_t remove, const char *protocol, const char *realm, const char *channel, const char *controller, const char *target); -KS_DECLARE(ks_bool_t) blade_mastermgr_channel_verify(blade_mastermgr_t *bmmgr, const char *protocol, const char *realm, const char *channel, const char *target); +KS_DECLARE(ks_status_t) blade_mastermgr_realm_add(blade_mastermgr_t *bmmgr, blade_realm_t *realm); +KS_DECLARE(ks_status_t) blade_mastermgr_realm_remove(blade_mastermgr_t *bmmgr, const char *realm); +KS_DECLARE(blade_protocol_t *) blade_mastermgr_realm_protocol_lookup(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, ks_bool_t writelocked); +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_controller_add(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *controller); +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_controller_remove(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *controller); +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_channel_add(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *channel); +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_channel_remove(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *channel); +KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_channel_authorize(blade_mastermgr_t *bmmgr, ks_bool_t remove, const char *realm, const char *protocol, const char *channel, const char *controller, const char *target); +KS_DECLARE(ks_bool_t) blade_mastermgr_realm_protocol_channel_authorization_verify(blade_mastermgr_t *bmmgr, const char *realm, const char *protocol, const char *channel, const char *target); KS_END_EXTERN_C #endif diff --git a/libs/libblade/src/include/blade_protocol.h b/libs/libblade/src/include/blade_protocol.h index 9a31b335b5..cdbf74ce53 100644 --- a/libs/libblade/src/include/blade_protocol.h +++ b/libs/libblade/src/include/blade_protocol.h @@ -36,19 +36,23 @@ #include KS_BEGIN_EXTERN_C -KS_DECLARE(ks_status_t) blade_protocol_create(blade_protocol_t **bpP, ks_pool_t *pool, const char *name, const char *realm); +KS_DECLARE(ks_status_t) blade_protocol_create(blade_protocol_t **bpP, ks_pool_t *pool, blade_realm_t *realm, const char *name); KS_DECLARE(ks_status_t) blade_protocol_destroy(blade_protocol_t **bpP); +KS_DECLARE(blade_realm_t *) blade_protocol_realm_get(blade_protocol_t *bp); KS_DECLARE(const char *) blade_protocol_name_get(blade_protocol_t *bp); -KS_DECLARE(const char *) blade_protocol_realm_get(blade_protocol_t *bp); +KS_DECLARE(ks_status_t) blade_protocol_read_lock(blade_protocol_t *bp); +KS_DECLARE(ks_status_t) blade_protocol_read_unlock(blade_protocol_t *bp); +KS_DECLARE(ks_status_t) blade_protocol_write_lock(blade_protocol_t *bp); +KS_DECLARE(ks_status_t) blade_protocol_write_unlock(blade_protocol_t *bp); KS_DECLARE(ks_bool_t) blade_protocol_purge(blade_protocol_t *bp, const char *nodeid); KS_DECLARE(cJSON *) blade_protocol_controller_pack(blade_protocol_t *bp); KS_DECLARE(ks_status_t) blade_protocol_controller_add(blade_protocol_t *bp, const char *nodeid); KS_DECLARE(ks_bool_t) blade_protocol_controller_remove(blade_protocol_t *bp, const char *nodeid); KS_DECLARE(ks_bool_t) blade_protocol_controller_available(blade_protocol_t *bp); -KS_DECLARE(ks_status_t) blade_protocol_channel_add(blade_protocol_t *bp, const char *name); -KS_DECLARE(ks_bool_t) blade_protocol_channel_remove(blade_protocol_t *bp, const char *name); -KS_DECLARE(ks_status_t) blade_protocol_channel_authorize(blade_protocol_t *bp, ks_bool_t remove, const char *channel, const char *controller, const char *target); -KS_DECLARE(ks_bool_t) blade_protocol_channel_verify(blade_protocol_t *bp, const char *channel, const char *target); +KS_DECLARE(blade_channel_t *) blade_protocol_channel_lookup(blade_protocol_t *bp, const char *channel, ks_bool_t writelocked); +KS_DECLARE(ks_bool_t) blade_protocol_controller_verify(blade_protocol_t *bp, const char *controller); +KS_DECLARE(ks_status_t) blade_protocol_channel_add(blade_protocol_t *bp, blade_channel_t *channel); +KS_DECLARE(ks_bool_t) blade_protocol_channel_remove(blade_protocol_t *bp, const char *channel); KS_END_EXTERN_C #endif diff --git a/libs/libblade/src/include/blade_realm.h b/libs/libblade/src/include/blade_realm.h new file mode 100644 index 0000000000..1e70f5c06c --- /dev/null +++ b/libs/libblade/src/include/blade_realm.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, Shane Bryldt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BLADE_REALM_H_ +#define _BLADE_REALM_H_ +#include + +KS_BEGIN_EXTERN_C +KS_DECLARE(ks_status_t) blade_realm_create(blade_realm_t **brP, ks_pool_t *pool, const char *name); +KS_DECLARE(ks_status_t) blade_realm_destroy(blade_realm_t **brP); +KS_DECLARE(const char *) blade_realm_name_get(blade_realm_t *br); +KS_DECLARE(ks_status_t) blade_realm_read_lock(blade_realm_t *br); +KS_DECLARE(ks_status_t) blade_realm_read_unlock(blade_realm_t *br); +KS_DECLARE(ks_status_t) blade_realm_write_lock(blade_realm_t *br); +KS_DECLARE(ks_status_t) blade_realm_write_unlock(blade_realm_t *br); +KS_DECLARE(ks_hash_iterator_t *) blade_realm_protocols_iterator(blade_realm_t *br, ks_locked_t locked); +KS_DECLARE(blade_protocol_t *) blade_realm_protocol_lookup(blade_realm_t *br, const char *protocol, ks_bool_t writelocked); +KS_DECLARE(ks_status_t) blade_realm_protocol_add(blade_realm_t *br, blade_protocol_t *protocol); +KS_DECLARE(ks_status_t) blade_realm_protocol_remove(blade_realm_t *br, const char *protocol); +KS_END_EXTERN_C + +#endif + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: + */ diff --git a/libs/libblade/src/include/blade_stack.h b/libs/libblade/src/include/blade_stack.h index f64326ffde..4e9c03438e 100644 --- a/libs/libblade/src/include/blade_stack.h +++ b/libs/libblade/src/include/blade_stack.h @@ -77,6 +77,10 @@ KS_DECLARE(ks_status_t) blade_handle_rpcsubscribe(blade_handle_t *bh, blade_rpcs KS_DECLARE(ks_status_t) blade_handle_rpcbroadcast(blade_handle_t *bh, const char *protocol, const char *realm, const char *channel, const char *event, cJSON *params, blade_rpc_response_callback_t callback, void *data); KS_DECLARE(cJSON *) blade_rpcbroadcast_request_params_get(blade_rpc_request_t *brpcreq); +KS_DECLARE(const char *) blade_rpcbroadcast_request_realm_get(blade_rpc_request_t *brpcreq); +KS_DECLARE(const char *) blade_rpcbroadcast_request_protocol_get(blade_rpc_request_t *brpcreq); +KS_DECLARE(const char *) blade_rpcbroadcast_request_channel_get(blade_rpc_request_t *brpcreq); +KS_DECLARE(const char *) blade_rpcbroadcast_request_event_get(blade_rpc_request_t *brpcreq); KS_END_EXTERN_C diff --git a/libs/libblade/src/include/blade_types.h b/libs/libblade/src/include/blade_types.h index d6bf895ff5..db1c0b3ed2 100644 --- a/libs/libblade/src/include/blade_types.h +++ b/libs/libblade/src/include/blade_types.h @@ -48,7 +48,9 @@ typedef struct blade_rpc_response_s blade_rpc_response_t; typedef struct blade_connection_s blade_connection_t; typedef struct blade_session_s blade_session_t; typedef struct blade_session_callbacks_s blade_session_callbacks_t; +typedef struct blade_realm_s blade_realm_t; typedef struct blade_protocol_s blade_protocol_t; +typedef struct blade_channel_s blade_channel_t; typedef struct blade_subscription_s blade_subscription_t; typedef struct blade_tuple_s blade_tuple_t; diff --git a/libs/libblade/src/include/blade_upstreammgr.h b/libs/libblade/src/include/blade_upstreammgr.h index a44dfe735a..d662560aff 100644 --- a/libs/libblade/src/include/blade_upstreammgr.h +++ b/libs/libblade/src/include/blade_upstreammgr.h @@ -48,11 +48,6 @@ KS_DECLARE(ks_status_t) blade_upstreammgr_masterid_set(blade_upstreammgr_t *bumg KS_DECLARE(ks_bool_t) blade_upstreammgr_masterid_compare(blade_upstreammgr_t *bumgr, const char *id); KS_DECLARE(ks_status_t) blade_upstreammgr_masterid_copy(blade_upstreammgr_t *bumgr, ks_pool_t *pool, const char **id); KS_DECLARE(ks_bool_t) blade_upstreammgr_masterlocal(blade_upstreammgr_t *bumgr); -//KS_DECLARE(ks_hash_t *) blade_upstreammgr_realm_lookup(blade_handle_t *bh); -KS_DECLARE(ks_status_t) blade_upstreammgr_realm_add(blade_upstreammgr_t *bumgr, const char *realm); -KS_DECLARE(ks_status_t) blade_upstreammgr_realm_remove(blade_upstreammgr_t *bumgr, const char *realm); -KS_DECLARE(ks_status_t) blade_upstreammgr_realm_clear(blade_upstreammgr_t *bumgr); -KS_DECLARE(ks_status_t) blade_upstreammgr_realm_propagate(blade_upstreammgr_t *bumgr, blade_session_t *bs); KS_END_EXTERN_C diff --git a/libs/libblade/test/testcon.c b/libs/libblade/test/testcon.c index 810ecb3481..3394576da9 100644 --- a/libs/libblade/test/testcon.c +++ b/libs/libblade/test/testcon.c @@ -18,11 +18,13 @@ struct command_def_s { void command_quit(blade_handle_t *bh, char *args); void command_channeladd(blade_handle_t *bh, char *args); void command_channelremove(blade_handle_t *bh, char *args); +void command_presence(blade_handle_t *bh, char *args); static const struct command_def_s command_defs[] = { { "quit", command_quit }, { "channeladd", command_channeladd }, { "channelremove", command_channelremove }, + { "presence", command_presence }, { NULL, NULL } }; @@ -323,6 +325,39 @@ ks_bool_t test_talk_request_handler(blade_rpc_request_t *brpcreq, void *data) return KS_FALSE; } +ks_bool_t test_presence_request_handler(blade_rpc_request_t *brpcreq, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + const char *realm = NULL; + const char *protocol = NULL; + const char *channel = NULL; + const char *event = NULL; + cJSON *params = NULL; + const char *nodeid = NULL; + + ks_assert(brpcreq); + ks_assert(data); + + bh = blade_rpc_request_handle_get(brpcreq); + ks_assert(bh); + + bs = blade_sessionmgr_session_lookup(blade_handle_sessionmgr_get(bh), blade_rpc_request_sessionid_get(brpcreq)); + ks_assert(bs); + + realm = blade_rpcbroadcast_request_realm_get(brpcreq); + protocol = blade_rpcbroadcast_request_protocol_get(brpcreq); + channel = blade_rpcbroadcast_request_channel_get(brpcreq); + event = blade_rpcbroadcast_request_event_get(brpcreq); + + params = blade_rpcbroadcast_request_params_get(brpcreq); + nodeid = cJSON_GetObjectCstr(params, "nodeid"); + + ks_log(KS_LOG_DEBUG, "Session (%s) presence (%s@%s/%s/%s for %s) request processing\n", blade_session_id_get(bs), protocol, realm, channel, event, nodeid); + + return KS_FALSE; +} + int main(int argc, char **argv) { @@ -525,6 +560,20 @@ void command_channelremove(blade_handle_t *bh, char *args) } } +void command_presence(blade_handle_t *bh, char *args) +{ + cJSON *channels = NULL; + + ks_assert(bh); + ks_assert(args); + + channels = cJSON_CreateArray(); + cJSON_AddItemToArray(channels, cJSON_CreateString("join")); + cJSON_AddItemToArray(channels, cJSON_CreateString("leave")); + + blade_handle_rpcsubscribe(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_ADD, "presence", "blade", channels, NULL, NULL, test_presence_request_handler, (void *)g_test); +} + /* For Emacs: * Local Variables: * mode:c