FS-10167: Temporary commit to retain changes before removing concept of realm/subrealm as per discussions, will revisit this concept later when a real use-case presents itself, tests will not operate correctly in this build as realms are incomplete prior to removal

This commit is contained in:
Shane Bryldt 2017-09-13 08:41:40 -06:00
parent 12fefdf79b
commit af69e2fb5b
22 changed files with 997 additions and 676 deletions

View File

@ -188,10 +188,12 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\blade.c" />
<ClCompile Include="src\blade_channel.c" />
<ClCompile Include="src\blade_connection.c" />
<ClCompile Include="src\blade_connectionmgr.c" />
<ClCompile Include="src\blade_identity.c" />
<ClCompile Include="src\blade_mastermgr.c" />
<ClCompile Include="src\blade_realm.c" />
<ClCompile Include="src\blade_routemgr.c" />
<ClCompile Include="src\blade_rpc.c" />
<ClCompile Include="src\blade_protocol.c" />
@ -210,10 +212,12 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\include\blade.h" />
<ClInclude Include="src\include\blade_channel.h" />
<ClInclude Include="src\include\blade_connection.h" />
<ClInclude Include="src\include\blade_connectionmgr.h" />
<ClInclude Include="src\include\blade_identity.h" />
<ClInclude Include="src\include\blade_mastermgr.h" />
<ClInclude Include="src\include\blade_realm.h" />
<ClInclude Include="src\include\blade_routemgr.h" />
<ClInclude Include="src\include\blade_rpc.h" />
<ClInclude Include="src\include\blade_protocol.h" />

View File

@ -75,6 +75,12 @@
<ClCompile Include="src\blade_tuple.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\blade_realm.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\blade_channel.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\include\unqlite.h">
@ -140,5 +146,11 @@
<ClInclude Include="src\include\blade_tuple.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\blade_realm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\blade_channel.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -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:
*/

View File

@ -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;
}

View File

@ -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:
*/

View File

@ -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:

View File

@ -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:
*/

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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"

View File

@ -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 <blade.h>
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

View File

@ -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

View File

@ -36,19 +36,23 @@
#include <blade.h>
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

View File

@ -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 <blade.h>
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:
*/

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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