FS-10167: Implemented identity registration and routing, removed subrealms to be revisited later, implemented public event channels and node presence, restructured some code and fixed a number of bugs.

This commit is contained in:
Shane Bryldt 2017-09-20 22:07:34 -06:00
parent dacca35a18
commit 43cb4e3468
38 changed files with 1396 additions and 1365 deletions

View File

@ -193,7 +193,6 @@
<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" />
@ -207,7 +206,6 @@
<ClCompile Include="src\blade_stack.c" />
<ClCompile Include="src\blade_transport.c" />
<ClCompile Include="src\blade_tuple.c" />
<ClCompile Include="src\blade_upstreammgr.c" />
<ClCompile Include="src\unqlite.c" />
</ItemGroup>
<ItemGroup>
@ -217,7 +215,6 @@
<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" />
@ -232,7 +229,6 @@
<ClInclude Include="src\include\blade_transport.h" />
<ClInclude Include="src\include\blade_tuple.h" />
<ClInclude Include="src\include\blade_types.h" />
<ClInclude Include="src\include\blade_upstreammgr.h" />
<ClInclude Include="src\include\unqlite.h" />
</ItemGroup>
<ItemGroup>

View File

@ -60,9 +60,6 @@
<ClCompile Include="src\blade_subscriptionmgr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\blade_upstreammgr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\blade_mastermgr.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -75,9 +72,6 @@
<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>
@ -131,9 +125,6 @@
<ClInclude Include="src\include\blade_subscriptionmgr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\blade_upstreammgr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\include\blade_mastermgr.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -146,9 +137,6 @@
<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>

View File

@ -35,6 +35,7 @@
struct blade_channel_s {
const char *name;
blade_channel_flags_t flags;
ks_rwl_t *lock;
ks_hash_t *authorizations;
};
@ -59,7 +60,7 @@ static void blade_channel_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t
}
}
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_create(blade_channel_t **bcP, ks_pool_t *pool, const char *name, blade_channel_flags_t flags)
{
blade_channel_t *bc = NULL;
@ -69,6 +70,7 @@ KS_DECLARE(ks_status_t) blade_channel_create(blade_channel_t **bcP, ks_pool_t *p
bc = ks_pool_alloc(pool, sizeof(blade_channel_t));
bc->name = ks_pstrdup(pool, name);
bc->flags = flags;
ks_rwl_create(&bc->lock, pool);
ks_assert(bc->lock);
@ -99,6 +101,12 @@ KS_DECLARE(const char *) blade_channel_name_get(blade_channel_t *bc)
return bc->name;
}
KS_DECLARE(blade_channel_flags_t) blade_channel_flags_get(blade_channel_t *bc)
{
ks_assert(bc);
return bc->flags;
}
KS_DECLARE(ks_status_t) blade_channel_read_lock(blade_channel_t *bc)
{
ks_assert(bc);

View File

@ -37,9 +37,13 @@ struct blade_identity_s {
const char *uri;
const char *components;
const char *name;
const char *domain;
const char *resource;
const char *scheme;
const char *user;
const char *host;
const char *port;
ks_port_t portnum;
const char *path;
ks_hash_t *parameters;
};
@ -89,10 +93,30 @@ KS_DECLARE(ks_status_t) blade_identity_destroy(blade_identity_t **biP)
return KS_STATUS_SUCCESS;
}
void blade_identity_reset(blade_identity_t *bi)
{
ks_assert(bi);
bi->scheme = NULL;
bi->user = NULL;
bi->host = NULL;
bi->port = NULL;
bi->portnum = 0;
bi->path = NULL;
if (bi->uri) {
ks_pool_free(&bi->uri);
ks_pool_free(&bi->components);
}
if (bi->parameters) ks_hash_destroy(&bi->parameters);
}
KS_DECLARE(ks_status_t) blade_identity_parse(blade_identity_t *bi, const char *uri)
{
ks_status_t ret = KS_STATUS_SUCCESS;
char *tmp = NULL;
char *tmp2 = NULL;
char terminator = '\0';
ks_pool_t *pool = NULL;
ks_assert(bi);
@ -102,59 +126,221 @@ KS_DECLARE(ks_status_t) blade_identity_parse(blade_identity_t *bi, const char *u
pool = ks_pool_get(bi);
if (bi->uri) {
ks_pool_free(&bi->uri);
ks_pool_free(&bi->components);
}
blade_identity_reset(bi);
bi->uri = ks_pstrdup(pool, uri);
bi->components = tmp = ks_pstrdup(pool, uri);
bi->name = tmp;
if (!(tmp = strchr(tmp, '@'))) return KS_STATUS_FAIL;
// Supported components with pseudo regex
// <scheme:[//]> [user@] <host> [:port] [/path] [;param1=value1] [;param2=value2]
// scheme is mandatory to simplify the parser for now, it must start with mandatory: <scheme>:
bi->scheme = tmp;
if (!(tmp = strchr(tmp, ':'))) {
ret = KS_STATUS_FAIL;
goto done;
}
// if found, null terminate scheme portion
*tmp++ = '\0';
// may have trailing '/' characters which are optional, this is not perfect it should probably only match a count of 0 or 2 explicitly
while (*tmp && *tmp == '/') ++tmp;
// must have more data to define at least a host
if (!*tmp) {
ret = KS_STATUS_FAIL;
goto done;
}
bi->domain = tmp2 = tmp;
if ((tmp = strchr(tmp, '/'))) {
*tmp++ = '\0';
bi->resource = tmp2 = tmp;
} else tmp = tmp2;
if (!(*bi->scheme)) {
ret = KS_STATUS_FAIL;
goto done;
}
if ((tmp = strchr(tmp, '?'))) {
*tmp++ = '\0';
// next component may be the user or the host, so it may start with optional: <user>@
// or it may skip to the host, which may be terminated by an optional port, optional path, optional parameters, or the end of the uri
// which means checking if an '@' appears before the next ':' for port, '/' for path, or ';' for parameters, if @ appears at all then it appears before end of the uri
// @todo need to account for host being encapsulated by '[' and ']' as in the case of an IPV6 host to distinguish from the port, but for simplicity allow any
// host to be encapsulated in which case if the string starts with a '[' here, then it MUST be the host and it MUST be terminated with the matching ']' rather than other
// optional component terminators
if (!(tmp2 = strpbrk(tmp, "@:/;"))) {
// none of the terminators are found, treat the remaining string as a host
bi->host = tmp;
goto done;
}
while (tmp) {
char *key = tmp;
char *val = NULL;
if (!(tmp = strchr(tmp, '='))) return KS_STATUS_FAIL;
*tmp++ = '\0';
val = tmp;
if ((tmp = strchr(tmp, '&'))) {
*tmp++ = '\0';
}
// grab the terminator and null terminate for the next component
terminator = *tmp2;
*tmp2++ = '\0';
if (!bi->parameters) {
ks_hash_create(&bi->parameters, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, pool);
ks_assert(bi->parameters);
}
ks_hash_insert(bi->parameters, key, val);
if (terminator == '@') {
// if the terminator was an '@', then we have a user component before the host
bi->user = tmp;
tmp = tmp2;
if (!(*bi->user)) {
ret = KS_STATUS_FAIL;
goto done;
}
// repeat the same as above, except without looking for '@', to find only the end of the host, parsing to the same point as above if user was not found
if (!(tmp2 = strpbrk(tmp, ":/;"))) {
// none of the terminators are found, treat the remaining string as a host
bi->host = tmp;
goto done;
}
// grab the terminator and null terminate for the next component
terminator = *tmp2;
*tmp2++ = '\0';
}
// at this point the user portion has been parsed if it exists, the host portion has been terminated, and there is still data remaining to parse
// @todo need to account for host being encapsulated by '[' and ']' as in the case of an IPV6 host to distinguish from the port, but for simplicity allow any
// host to be encapsulated in which case the terminator MUST be the closing ']'
bi->host = tmp;
tmp = tmp2;
if (!(*bi->host)) {
ret = KS_STATUS_FAIL;
goto done;
}
if (terminator == ':') {
// port terminator
bi->port = tmp;
// next component must be the port, which may be terminated by an optional path, optional parameters, or the end of the uri
// which means checking if a '/' for path, or ';' for parameters
if (!(tmp2 = strpbrk(tmp, "/;"))) {
// none of the terminators are found, treat the remaining string as a port
goto done;
}
terminator = *tmp2;
*tmp2++ = '\0';
tmp = tmp2;
if (!(*bi->port)) {
ret = KS_STATUS_FAIL;
goto done;
}
// @todo sscanf bi->port into bi->portnum and validate that it is a valid port number
}
if (terminator == '/') {
// path terminator
bi->path = tmp;
// next component must be the path, which may be terminated by optional parameters, or the end of the uri
// which means checking ';' for parameters
if (!(tmp2 = strpbrk(tmp, ";"))) {
// none of the terminators are found, treat the remaining string as a path
goto done;
}
terminator = *tmp2;
*tmp2++ = '\0';
tmp = tmp2;
if (!(*bi->path)) {
ret = KS_STATUS_FAIL;
goto done;
}
}
if (terminator == ';') {
// parameter terminator
do {
char *key = NULL;
char *value = NULL;
// next component must be the parameter key, which must be terminated by mandatory '=', end of the uri is an error
// which means checking '=' for key terminator
key = tmp;
if (!(tmp = strpbrk(tmp, "="))) {
ret = KS_STATUS_FAIL;
goto done;
}
*tmp++ = '\0';
// next component must be the parameter value, which may be terminated by another parameter terminator ';', or the end of the uri
// if it is the end of the uri, then the parameter loop will be exited
value = tmp;
if ((tmp = strpbrk(tmp, ";"))) {
*tmp++ = '\0';
}
// create th parameters hash if it does not already exist and add the parameter entry to it, note the key and value are both actually part
// of the duplicated uri for components and will be cleaned up with the single string so the hash must not free the key or value itself
if (!bi->parameters) ks_hash_create(&bi->parameters, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, pool);
ks_hash_insert(bi->parameters, (void *)key, (void *)value);
} while (tmp);
}
done:
if (ret != KS_STATUS_SUCCESS) blade_identity_reset(bi);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(const char *) blade_identity_uri(blade_identity_t *bi)
KS_DECLARE(const char *) blade_identity_uri_get(blade_identity_t *bi)
{
ks_assert(bi);
return bi->uri;
}
KS_DECLARE(const char *) blade_identity_parameter_get(blade_identity_t *bi, const char *key)
KS_DECLARE(const char *) blade_identity_scheme_get(blade_identity_t *bi)
{
ks_assert(bi);
return bi->scheme;
}
KS_DECLARE(const char *) blade_identity_user_get(blade_identity_t *bi)
{
ks_assert(bi);
return bi->user;
}
KS_DECLARE(const char *) blade_identity_host_get(blade_identity_t *bi)
{
ks_assert(bi);
return bi->host;
}
KS_DECLARE(const char *) blade_identity_port_get(blade_identity_t *bi)
{
ks_assert(bi);
return bi->port;
}
KS_DECLARE(ks_port_t) blade_identity_portnum_get(blade_identity_t *bi)
{
ks_assert(bi);
return bi->portnum;
}
KS_DECLARE(const char *) blade_identity_path_get(blade_identity_t *bi)
{
ks_assert(bi);
return bi->path;
}
KS_DECLARE(const char *) blade_identity_parameter_lookup(blade_identity_t *bi, const char *key)
{
ks_assert(bi);
ks_assert(key);
if (!bi->parameters) return NULL;
return (const char *)ks_hash_search(bi->parameters, (void *)key, KS_UNLOCKED);
}

View File

@ -36,10 +36,11 @@
struct blade_mastermgr_s {
blade_handle_t *handle;
// @todo use a blade_mastermgr_config_t to store configuration, inline variable, with sane defaults for as much configuration as is possible
// then reuse this same pattern across all the manager types that invoke startup configuration processing
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 *realms;
//ks_hash_t *protocols; // protocols that have been published with blade.publish, and the details to locate a protocol controller with blade.locate
// @todo how does "exclusive" play into the controllers, does "exclusive" mean only one provider can exist for a given protocol? what does non exclusive mean?
ks_hash_t *protocols;
};
@ -72,8 +73,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->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_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_pool_set_cleanup(bmmgr, NULL, blade_mastermgr_cleanup);
@ -154,20 +155,13 @@ KS_DECLARE(ks_status_t) blade_mastermgr_startup(blade_mastermgr_t *bmmgr, config
}
if (bmmgr->master_nodeid) {
blade_realm_t *br = NULL;
blade_routemgr_local_set(blade_handle_routemgr_get(bmmgr->handle), bmmgr->master_nodeid);
blade_routemgr_master_set(blade_handle_routemgr_get(bmmgr->handle), bmmgr->master_nodeid);
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);
blade_mastermgr_protocol_controller_add(bmmgr, "blade.presence", 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");
blade_mastermgr_protocol_channel_add(bmmgr, "blade.presence", "join", BLADE_CHANNEL_FLAGS_PUBLIC);
blade_mastermgr_protocol_channel_add(bmmgr, "blade.presence", "leave", BLADE_CHANNEL_FLAGS_PUBLIC);
}
return KS_STATUS_SUCCESS;
@ -188,265 +182,215 @@ KS_DECLARE(ks_status_t) blade_mastermgr_purge(blade_mastermgr_t *bmmgr, const ch
pool = ks_pool_get(bmmgr);
ks_hash_write_lock(bmmgr->realms);
ks_hash_write_lock(bmmgr->protocols);
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);
for (ks_hash_iterator_t *it = ks_hash_first(bmmgr->protocols, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
const char *protocol = NULL;
blade_protocol_t *bp = NULL;
ks_bool_t unlock = KS_TRUE;
blade_realm_write_lock(br);
ks_hash_this(it, (const void **)&protocol, NULL, (void **)&bp);
for (ks_hash_iterator_t *it2 = blade_realm_protocols_iterator(br, KS_UNLOCKED); it2; it2 = ks_hash_next(&it2)) {
blade_protocol_write_lock(bp);
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);
unlock = KS_FALSE;
}
else {
// @todo not the last controller, may need to propagate that the controller is no longer available?
}
}
if (unlock) blade_protocol_write_unlock(bp);
}
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_protocol_write_lock(bp);
blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(bmmgr->handle), BLADE_RPCBROADCAST_COMMAND_PROTOCOL_REMOVE, NULL, protocol, NULL, NULL, NULL, NULL, NULL);
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_log(KS_LOG_DEBUG, "Protocol Removed: %s\n", protocol);
blade_protocol_write_unlock(bp);
ks_hash_remove(bmmgr->protocols, (void *)protocol);
}
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_destroy(&cleanup);
}
ks_hash_write_unlock(bmmgr->realms);
ks_hash_write_unlock(bmmgr->protocols);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_mastermgr_realm_add(blade_mastermgr_t *bmmgr, blade_realm_t *realm)
KS_DECLARE(blade_protocol_t *) blade_mastermgr_protocol_lookup(blade_mastermgr_t *bmmgr, const char *protocol, ks_bool_t writelocked)
{
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;
ks_assert(bmmgr);
ks_assert(protocol);
ks_assert(realm);
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);
bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)protocol, KS_READLOCKED);
if (bp) {
if (writelocked) blade_protocol_write_lock(bp);
else blade_protocol_read_lock(bp);
}
ks_hash_read_unlock(bmmgr->protocols);
return bp;
}
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_protocol_controller_add(blade_mastermgr_t *bmmgr, 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;
ks_assert(bmmgr);
ks_assert(realm);
ks_assert(protocol);
ks_assert(controller);
pool = ks_pool_get(bmmgr);
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 *)protocol, 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, br, protocol);
if (bp) blade_protocol_write_lock(bp);
else {
blade_protocol_create(&bp, pool, protocol);
ks_assert(bp);
blade_protocol_write_lock(bp);
ks_log(KS_LOG_DEBUG, "Protocol Added: %s@%s\n", protocol, realm);
blade_realm_protocol_add(br, bp);
ks_log(KS_LOG_DEBUG, "Protocol Added: %s\n", protocol);
ks_hash_insert(bmmgr->protocols, (void *)ks_pstrdup(ks_pool_get(bmmgr), protocol), (void *)bp);
}
blade_protocol_controller_add(bp, controller);
ks_log(KS_LOG_DEBUG, "Protocol Controller Added: %s to %s\n", controller, protocol);
blade_protocol_write_unlock(bp);
done:
ks_hash_read_unlock(bmmgr->realms);
ks_hash_write_unlock(bmmgr->protocols);
return ret;
}
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_protocol_controller_remove(blade_mastermgr_t *bmmgr, 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;
ks_bool_t remove = KS_FALSE;
ks_assert(bmmgr);
ks_assert(realm);
ks_assert(protocol);
ks_assert(controller);
pool = ks_pool_get(bmmgr);
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_realm_protocol_lookup(br, protocol, KS_TRUE);
if (bp) {
if (blade_protocol_controller_remove(bp, controller)) {
if (!blade_protocol_controller_available(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_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);
}
done:
ks_hash_read_unlock(bmmgr->realms);
return ret;
}
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;
blade_channel_t *bc = NULL;
ks_assert(bmmgr);
ks_assert(realm);
ks_assert(protocol);
ks_assert(channel);
ks_hash_read_lock(bmmgr->realms);
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);
bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)protocol, KS_UNLOCKED);
if (!bp) {
ret = KS_STATUS_NOT_FOUND;
goto done;
}
blade_protocol_write_lock(bp);
if (blade_protocol_controller_remove(bp, controller)) {
ks_log(KS_LOG_DEBUG, "Protocol Controller Removed: %s from %s\n", controller, protocol);
if (!blade_protocol_controller_available(bp)) {
blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(bmmgr->handle), BLADE_RPCBROADCAST_COMMAND_PROTOCOL_REMOVE, NULL, protocol, NULL, NULL, NULL, NULL, NULL);
ks_log(KS_LOG_DEBUG, "Protocol Removed: %s\n", protocol);
remove = KS_TRUE;
} else {
// @todo not the last controller, may need to propagate when a specific controller becomes unavailable though
}
}
blade_protocol_write_unlock(bp);
if (remove) ks_hash_remove(bmmgr->protocols, (void *)protocol);
done:
ks_hash_write_unlock(bmmgr->protocols);
return ret;
}
KS_DECLARE(ks_status_t) blade_mastermgr_protocol_channel_add(blade_mastermgr_t *bmmgr, const char *protocol, const char *channel, blade_channel_flags_t flags)
{
ks_status_t ret = KS_STATUS_SUCCESS;
blade_protocol_t *bp = NULL;
blade_channel_t *bc = NULL;
ks_assert(bmmgr);
ks_assert(protocol);
ks_assert(channel);
ks_hash_read_lock(bmmgr->protocols);
bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)protocol, KS_UNLOCKED);
if (!bp) {
ret = KS_STATUS_NOT_FOUND;
goto done;
}
blade_protocol_write_lock(bp);
bc = blade_protocol_channel_lookup(bp, channel, KS_TRUE);
if (!bc) {
if (bc) {
ret = KS_STATUS_DUPLICATE_OPERATION;
goto done;
}
blade_channel_create(&bc, ks_pool_get(bc), channel);
blade_channel_create(&bc, ks_pool_get(bp), channel, flags);
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));
ks_log(KS_LOG_DEBUG, "Protocol Channel Added: %s to %s\n", blade_channel_name_get(bc), blade_protocol_name_get(bp));
}
done:
if (bc) blade_channel_write_unlock(bc);
if (bp) blade_protocol_write_unlock(bp);
ks_hash_read_unlock(bmmgr->realms);
ks_hash_read_unlock(bmmgr->protocols);
return ret;
}
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_protocol_channel_remove(blade_mastermgr_t *bmmgr, const char *protocol, const char *channel)
{
ks_status_t ret = KS_STATUS_SUCCESS;
blade_realm_t *br = NULL;
blade_protocol_t *bp = NULL;
blade_channel_t *bc = NULL;
ks_assert(bmmgr);
ks_assert(realm);
ks_assert(protocol);
ks_assert(channel);
ks_hash_read_lock(bmmgr->realms);
ks_hash_read_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_realm_protocol_lookup(br, protocol, KS_TRUE);
bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)protocol, KS_UNLOCKED);
if (!bp) {
ret = KS_STATUS_NOT_FOUND;
goto done;
}
blade_protocol_write_lock(bp);
bc = blade_protocol_channel_lookup(bp, channel, KS_TRUE);
if (!bc) {
ret = KS_STATUS_NOT_FOUND;
@ -454,47 +398,41 @@ KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_channel_remove(blade_mast
}
if (blade_protocol_channel_remove(bp, channel)) {
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_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(bmmgr->handle), BLADE_RPCBROADCAST_COMMAND_CHANNEL_REMOVE, NULL, protocol, channel, NULL, NULL, NULL, NULL);
ks_log(KS_LOG_DEBUG, "Protocol Channel Removed: %s from %s\n", blade_channel_name_get(bc), blade_protocol_name_get(bp));
blade_channel_write_unlock(bc);
blade_channel_destroy(&bc);
}
done:
if (bp) blade_protocol_write_unlock(bp);
ks_hash_read_unlock(bmmgr->realms);
ks_hash_read_unlock(bmmgr->protocols);
return ret;
}
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_status_t) blade_mastermgr_protocol_channel_authorize(blade_mastermgr_t *bmmgr, ks_bool_t remove, 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;
blade_channel_t *bc = NULL;
ks_assert(bmmgr);
ks_assert(realm);
ks_assert(protocol);
ks_assert(channel);
ks_assert(controller);
ks_assert(target);
ks_hash_read_lock(bmmgr->realms);
ks_hash_read_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_realm_protocol_lookup(br, protocol, KS_FALSE);
bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)protocol, KS_UNLOCKED);
if (!bp) {
ret = KS_STATUS_NOT_FOUND;
goto done;
}
blade_protocol_read_lock(bp);
if (!blade_protocol_controller_verify(bp, controller)) {
ret = KS_STATUS_NOT_ALLOWED;
goto done;
@ -508,63 +446,56 @@ KS_DECLARE(ks_status_t) blade_mastermgr_realm_protocol_channel_authorize(blade_m
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));
ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Removed: %s from protocol %s, channel %s\n", target, blade_protocol_name_get(bp), 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));
ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Added: %s to protocol %s, channel %s\n", target, blade_protocol_name_get(bp), blade_channel_name_get(bc));
}
}
done:
if (bc) blade_channel_write_unlock(bc);
if (bp) blade_protocol_read_unlock(bp);
ks_hash_read_unlock(bmmgr->realms);
ks_hash_read_unlock(bmmgr->protocols);
return ret;
}
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_DECLARE(ks_bool_t) blade_mastermgr_protocol_channel_authorization_verify(blade_mastermgr_t *bmmgr, 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;
blade_channel_t *bc = NULL;
ks_assert(bmmgr);
ks_assert(realm);
ks_assert(protocol);
ks_assert(channel);
ks_assert(target);
ks_hash_read_lock(bmmgr->realms);
ks_hash_read_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_realm_protocol_lookup(br, protocol, KS_FALSE);
bp = (blade_protocol_t *)ks_hash_search(bmmgr->protocols, (void *)protocol, KS_UNLOCKED);
if (!bp) {
ret = KS_STATUS_NOT_FOUND;
goto done;
}
blade_protocol_read_lock(bp);
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);
if ((blade_channel_flags_get(bc) & BLADE_CHANNEL_FLAGS_PUBLIC) == BLADE_CHANNEL_FLAGS_PUBLIC) ret = KS_TRUE;
else ret = blade_channel_authorization_verify(bc, target);
done:
if (bc) blade_channel_read_unlock(bc);
if (bp) blade_protocol_read_unlock(bp);
ks_hash_read_unlock(bmmgr->realms);
ks_hash_read_unlock(bmmgr->protocols);
return ret;
}

View File

@ -34,7 +34,6 @@
#include "blade.h"
struct blade_protocol_s {
blade_realm_t *realm;
const char *name;
ks_rwl_t *lock;
ks_hash_t *controllers;
@ -63,17 +62,15 @@ 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, blade_realm_t *realm, const char *name)
KS_DECLARE(ks_status_t) blade_protocol_create(blade_protocol_t **bpP, ks_pool_t *pool, const char *name)
{
blade_protocol_t *bp = NULL;
ks_assert(bpP);
ks_assert(pool);
ks_assert(realm);
ks_assert(name);
bp = ks_pool_alloc(pool, sizeof(blade_protocol_t));
bp->realm = realm;
bp->name = ks_pstrdup(pool, name);
ks_rwl_create(&bp->lock, pool);
@ -102,12 +99,6 @@ 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);
@ -140,6 +131,7 @@ 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_bool_t ret = KS_FALSE;
ks_assert(bp);
ks_assert(nodeid);
@ -147,17 +139,21 @@ KS_DECLARE(ks_bool_t) blade_protocol_purge(blade_protocol_t *bp, const char *nod
ks_hash_write_lock(bp->channels);
for (ks_hash_iterator_t *it = ks_hash_first(bp->channels, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
const char *key = NULL;
ks_hash_t *authorizations = NULL;
blade_channel_t *channel = NULL;
ks_hash_this(it, (const void **)&key, NULL, (void **)&authorizations);
ks_hash_this(it, (const void **)&key, NULL, (void **)&channel);
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, blade_realm_name_get(bp->realm), key);
if (blade_channel_authorization_remove(channel, nodeid)) {
ks_log(KS_LOG_DEBUG, "Protocol Channel Authorization Removed: %s from protocol %s, channel %s\n", nodeid, bp->name, key);
}
}
ks_hash_write_unlock(bp->channels);
return blade_protocol_controller_remove(bp, nodeid);
if ((ret = blade_protocol_controller_remove(bp, nodeid))) {
ks_log(KS_LOG_DEBUG, "Protocol Controller Removed: %s from %s\n", nodeid, bp->name);
}
return ret;
}
KS_DECLARE(cJSON *) blade_protocol_controller_pack(blade_protocol_t *bp)
@ -203,8 +199,6 @@ 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, blade_realm_name_get(bp->realm));
return KS_STATUS_SUCCESS;
}
@ -218,7 +212,6 @@ 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, blade_realm_name_get(bp->realm));
}
ks_hash_write_unlock(bp->controllers);

View File

@ -1,179 +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"
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

@ -36,7 +36,14 @@
struct blade_routemgr_s {
blade_handle_t *handle;
ks_hash_t *routes; // id, id
const char *local_nodeid;
ks_rwl_t *local_lock;
const char *master_nodeid;
ks_rwl_t *master_lock;
ks_hash_t *routes; // target nodeid, downstream router nodeid
ks_hash_t *identities; // identity, target nodeid
};
@ -69,10 +76,19 @@ KS_DECLARE(ks_status_t) blade_routemgr_create(blade_routemgr_t **brmgrP, blade_h
brmgr = ks_pool_alloc(pool, sizeof(blade_routemgr_t));
brmgr->handle = bh;
// @note can let removes free keys and values for routes, both are strings and allocated from the same pool as the hash itself
ks_rwl_create(&brmgr->local_lock, pool);
ks_assert(brmgr->local_lock);
ks_rwl_create(&brmgr->master_lock, pool);
ks_assert(brmgr->master_lock);
// @note can let removes free keys and values for routes and identity, both use keys and values that are strings allocated from the same pool as the hash itself
ks_hash_create(&brmgr->routes, 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(brmgr->routes);
ks_hash_create(&brmgr->identities, 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(brmgr->routes);
ks_pool_set_cleanup(brmgr, NULL, blade_routemgr_cleanup);
*brmgrP = brmgr;
@ -105,6 +121,206 @@ KS_DECLARE(blade_handle_t *) blade_routemgr_handle_get(blade_routemgr_t *brmgr)
return brmgr->handle;
}
KS_DECLARE(ks_status_t) blade_routemgr_local_set(blade_routemgr_t *brmgr, const char *nodeid)
{
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(brmgr);
ks_rwl_write_lock(brmgr->local_lock);
if (brmgr->local_nodeid) {
ret = KS_STATUS_DUPLICATE_OPERATION;
goto done;
}
if (nodeid) brmgr->local_nodeid = ks_pstrdup(ks_pool_get(brmgr), nodeid);
ks_log(KS_LOG_DEBUG, "Local NodeID: %s\n", nodeid);
done:
ks_rwl_write_unlock(brmgr->local_lock);
return ret;
}
KS_DECLARE(ks_bool_t) blade_routemgr_local_check(blade_routemgr_t *brmgr, const char *target)
{
ks_bool_t ret = KS_FALSE;
ks_assert(brmgr);
ks_assert(target);
ks_rwl_read_lock(brmgr->local_lock);
ret = !ks_safe_strcasecmp(brmgr->local_nodeid, target);
if (!ret) {
// @todo must parse target to an identity, and back to a properly formatted identity key
blade_identity_t *identity = NULL;
ks_pool_t *pool = ks_pool_get(brmgr);
blade_identity_create(&identity, pool);
if (blade_identity_parse(identity, target) == KS_STATUS_SUCCESS) {
char *key = ks_psprintf(pool, "%s@%s/%s", blade_identity_user_get(identity), blade_identity_host_get(identity), blade_identity_path_get(identity));
const char *value = (const char *)ks_hash_search(brmgr->identities, (void *)key, KS_READLOCKED);
if (value) ret = !ks_safe_strcasecmp(brmgr->local_nodeid, value);
ks_hash_read_unlock(brmgr->identities);
ks_pool_free(&key);
}
blade_identity_destroy(&identity);
}
ks_rwl_read_unlock(brmgr->local_lock);
return ret;
}
KS_DECLARE(ks_bool_t) blade_routemgr_local_copy(blade_routemgr_t *brmgr, const char **nodeid)
{
ks_bool_t ret = KS_FALSE;
ks_assert(brmgr);
ks_assert(nodeid);
*nodeid = NULL;
ks_rwl_read_lock(brmgr->local_lock);
if (brmgr->local_nodeid) {
ret = KS_TRUE;
*nodeid = ks_pstrdup(ks_pool_get(brmgr), brmgr->local_nodeid);
}
ks_rwl_read_unlock(brmgr->local_lock);
return ret;
}
KS_DECLARE(ks_bool_t) blade_routemgr_local_pack(blade_routemgr_t *brmgr, cJSON *json, const char *key)
{
ks_bool_t ret = KS_FALSE;
ks_assert(brmgr);
ks_assert(json);
ks_assert(key);
ks_rwl_read_lock(brmgr->local_lock);
if (brmgr->local_nodeid) {
ret = KS_TRUE;
cJSON_AddStringToObject(json, key, brmgr->local_nodeid);
}
ks_rwl_read_unlock(brmgr->local_lock);
return ret;
}
KS_DECLARE(blade_session_t *) blade_routemgr_upstream_lookup(blade_routemgr_t *brmgr)
{
blade_session_t *bs = NULL;
ks_assert(brmgr);
ks_rwl_read_lock(brmgr->local_lock);
if (brmgr->local_nodeid) bs = blade_sessionmgr_session_lookup(blade_handle_sessionmgr_get(brmgr->handle), brmgr->local_nodeid);
ks_rwl_read_unlock(brmgr->local_lock);
return bs;
}
KS_DECLARE(ks_status_t) blade_routemgr_master_set(blade_routemgr_t *brmgr, const char *nodeid)
{
ks_assert(brmgr);
ks_rwl_write_lock(brmgr->master_lock);
if (brmgr->master_nodeid) ks_pool_free(&brmgr->master_nodeid);
if (nodeid) brmgr->master_nodeid = ks_pstrdup(ks_pool_get(brmgr), nodeid);
ks_rwl_write_unlock(brmgr->master_lock);
ks_log(KS_LOG_DEBUG, "Master NodeID: %s\n", nodeid);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_bool_t) blade_routemgr_master_check(blade_routemgr_t *brmgr, const char *target)
{
ks_bool_t ret = KS_FALSE;
ks_assert(brmgr);
ks_assert(target);
ks_rwl_read_lock(brmgr->master_lock);
ret = ks_safe_strcasecmp(brmgr->master_nodeid, target) == 0;
// @todo may also need to check against master identities, there are a number of ways master identities
// could be propagated to ensure this check works for identities, but for now just assume that master cannot
// use identities for these checks which should generally only be done to validate certain blade CoreRPC's which
// expect the responder to be the master, and which get packed in the function below
// the following would only work on the master itself, where it registered it's own identities and thus has the
// identities in the identities mapping, other nodes do not see master identity registrations and cannot currently
// validate master identities
//if (!ret) {
// const char *nodeid = (const char *)ks_hash_search(brmgr->identities, (void *)target, KS_READLOCKED);
// ret = nodeid && !ks_safe_strcasecmp(nodeid, brmgr->master_nodeid);
// ks_hash_read_unlock(brmgr->identities);
//}
ks_rwl_read_unlock(brmgr->master_lock);
return ret;
}
KS_DECLARE(ks_bool_t) blade_routemgr_master_pack(blade_routemgr_t *brmgr, cJSON *json, const char *key)
{
ks_bool_t ret = KS_FALSE;
ks_assert(brmgr);
ks_assert(json);
ks_assert(key);
ks_rwl_read_lock(brmgr->master_lock);
if (brmgr->master_nodeid) {
ret = KS_TRUE;
cJSON_AddStringToObject(json, key, brmgr->master_nodeid);
// @todo may need to pack master identities into the json as well, for now just use nodeid only and
// assume master nodes have no identities, however this call is primarily used only to force certain
// blade CoreRPC's to route to the known master node, but is also used to pass to downstream nodes
// when they connect
}
ks_rwl_read_unlock(brmgr->master_lock);
return ret;
}
KS_DECLARE(ks_bool_t) blade_routemgr_master_local(blade_routemgr_t *brmgr)
{
ks_bool_t ret = KS_FALSE;
ks_assert(brmgr);
ks_rwl_read_lock(brmgr->master_lock);
ret = brmgr->master_nodeid && brmgr->local_nodeid && !ks_safe_strcasecmp(brmgr->master_nodeid, brmgr->local_nodeid);
//ret = brmgr->master_nodeid && brmgr->localid && !ks_safe_strcasecmp(brmgr->master_nodeid, brmgr->local_nodeid);
ks_rwl_read_unlock(brmgr->master_lock);
return ret;
}
KS_DECLARE(blade_session_t *) blade_routemgr_route_lookup(blade_routemgr_t *brmgr, const char *target)
{
blade_session_t *bs = NULL;
@ -114,12 +330,74 @@ KS_DECLARE(blade_session_t *) blade_routemgr_route_lookup(blade_routemgr_t *brmg
ks_assert(target);
router = (const char *)ks_hash_search(brmgr->routes, (void *)target, KS_READLOCKED);
if (!router) {
// @todo this is all really inefficient, but we need the string to be parsed and recombined to ensure correctness for key matching
blade_identity_t *identity = NULL;
ks_pool_t *pool = ks_pool_get(brmgr);
blade_identity_create(&identity, pool);
if (blade_identity_parse(identity, target) == KS_STATUS_SUCCESS) {
char *key = ks_psprintf(pool, "%s@%s/%s", blade_identity_user_get(identity), blade_identity_host_get(identity), blade_identity_path_get(identity));
router = (const char *)ks_hash_search(brmgr->identities, (void *)key, KS_READLOCKED);
ks_hash_read_unlock(brmgr->identities);
ks_pool_free(&key);
}
blade_identity_destroy(&identity);
}
if (router) bs = blade_sessionmgr_session_lookup(blade_handle_sessionmgr_get(brmgr->handle), router);
ks_hash_read_unlock(brmgr->routes);
return bs;
}
ks_status_t blade_routemgr_purge(blade_routemgr_t *brmgr, const char *target)
{
ks_hash_t* cleanup = NULL;
ks_assert(brmgr);
ks_assert(target);
// @note this approach is deliberately slower than it could be, as it ensures that if there is a race condition and another session has registered
// the same identity before a prior session times out, then the correct targetted random nodeid is matched to confirm the identity removal and will
// not remove if the target isn't what is expected
ks_hash_write_lock(brmgr->identities);
for (ks_hash_iterator_t *it = ks_hash_first(brmgr->identities, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
const char *key = NULL;
const char *value = NULL;
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
if (value && !ks_safe_strcasecmp(value, target)) {
if (!cleanup) ks_hash_create(&cleanup, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, ks_pool_get(brmgr));
ks_hash_insert(cleanup, (const void *)key, (void *)value);
}
}
if (cleanup) {
for (ks_hash_iterator_t *it = ks_hash_first(cleanup, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
const char *key = NULL;
const char *value = NULL;
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
ks_log(KS_LOG_DEBUG, "Identity Removed: %s through %s\n", key, value);
ks_hash_remove(brmgr->identities, (void *)key);
}
}
ks_hash_write_unlock(brmgr->identities);
if (cleanup) ks_hash_destroy(&cleanup);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_routemgr_route_add(blade_routemgr_t *brmgr, const char *target, const char *router)
{
ks_pool_t *pool = NULL;
@ -139,17 +417,16 @@ KS_DECLARE(ks_status_t) blade_routemgr_route_add(blade_routemgr_t *brmgr, const
ks_log(KS_LOG_DEBUG, "Route Added: %s through %s\n", key, value);
blade_handle_rpcregister(brmgr->handle, target, KS_FALSE, NULL, NULL);
blade_handle_rpcroute(brmgr->handle, target, KS_FALSE, NULL, NULL);
if (blade_upstreammgr_masterlocal(blade_handle_upstreammgr_get(brmgr->handle))) {
if (blade_routemgr_master_local(brmgr)) {
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);
blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(brmgr->handle), BLADE_RPCBROADCAST_COMMAND_EVENT, NULL, "blade.presence", "join", "joined", params, NULL, NULL);
cJSON_Delete(params);
}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_routemgr_route_remove(blade_routemgr_t *brmgr, const char *target)
@ -161,7 +438,7 @@ KS_DECLARE(ks_status_t) blade_routemgr_route_remove(blade_routemgr_t *brmgr, con
ks_log(KS_LOG_DEBUG, "Route Removed: %s\n", target);
blade_handle_rpcregister(brmgr->handle, target, KS_TRUE, NULL, NULL);
blade_handle_rpcroute(brmgr->handle, target, KS_TRUE, NULL, NULL);
blade_subscriptionmgr_purge(blade_handle_subscriptionmgr_get(brmgr->handle), target);
@ -172,16 +449,88 @@ 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))) {
blade_routemgr_purge(brmgr, target);
if (blade_routemgr_master_local(brmgr)) {
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);
blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(brmgr->handle), BLADE_RPCBROADCAST_COMMAND_EVENT, NULL, "blade.presence", "leave", "left", params, NULL, NULL);
cJSON_Delete(params);
}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_routemgr_identity_add(blade_routemgr_t *brmgr, blade_identity_t *identity, const char *target)
{
ks_pool_t *pool = NULL;
char *key = NULL;
char *value = NULL;
ks_assert(brmgr);
ks_assert(identity);
ks_assert(target);
pool = ks_pool_get(brmgr);
key = ks_psprintf(pool, "%s@%s/%s", blade_identity_user_get(identity), blade_identity_host_get(identity), blade_identity_path_get(identity));
value = ks_pstrdup(pool, target);
ks_hash_insert(brmgr->identities, (void *)key, (void *)value);
ks_log(KS_LOG_DEBUG, "Identity Added: %s through %s\n", key, value);
//if (blade_routemgr_master_local(blade_handle_routemgr_get(brmgr->handle))) {
// cJSON *params = cJSON_CreateObject();
// cJSON_AddStringToObject(params, "identity", blade_identity_uri_get(identity)); // full identity uri string
// cJSON_AddStringToObject(params, "nodeid", target);
// blade_subscriptionmgr_broadcast(blade_handle_subscriptionmgr_get(brmgr->handle), BLADE_RPCBROADCAST_COMMAND_EVENT, NULL, "blade.presence", "join", "joined", params, NULL, NULL);
// cJSON_Delete(params);
//}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_routemgr_identity_remove(blade_routemgr_t *brmgr, blade_identity_t *identity, const char *target)
{
ks_pool_t *pool = NULL;
char *key = NULL;
const char *value = NULL;
ks_assert(brmgr);
ks_assert(identity);
ks_assert(target);
pool = ks_pool_get(brmgr);
key = ks_psprintf(pool, "%s@%s/%s", blade_identity_user_get(identity), blade_identity_host_get(identity), blade_identity_path_get(identity));
// @note this approach is deliberately slower than it could be, as it ensures that if there is a race condition and another session has registered
// the same identity before a prior session times out, then the correct targetted random nodeid is matched to confirm the identity removal and will
// not remove if the target isn't what is expected
ks_hash_write_lock(brmgr->identities);
value = (const char *)ks_hash_search(brmgr->identities, (void *)key, KS_UNLOCKED);
if (value && !ks_safe_strcasecmp(value, target)) {
ks_hash_remove(brmgr->identities, (void *)key);
ks_log(KS_LOG_DEBUG, "Identity Removed: %s through %s\n", key, value);
}
ks_hash_write_unlock(brmgr->identities);
//if (blade_routemgr_master_local(blade_handle_routemgr_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, "blade.presence", "leave", "left", params, NULL, NULL);
// cJSON_Delete(params);
//}
return KS_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -38,7 +38,6 @@ struct blade_rpc_s {
const char *method;
const char *protocol;
const char *realm;
blade_rpc_request_callback_t callback;
void *data;
@ -84,7 +83,7 @@ static void blade_rpc_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t act
}
}
KS_DECLARE(ks_status_t) blade_rpc_create(blade_rpc_t **brpcP, blade_handle_t *bh, const char *method, const char *protocol, const char *realm, blade_rpc_request_callback_t callback, void *data)
KS_DECLARE(ks_status_t) blade_rpc_create(blade_rpc_t **brpcP, blade_handle_t *bh, const char *method, const char *protocol, blade_rpc_request_callback_t callback, void *data)
{
blade_rpc_t *brpc = NULL;
ks_pool_t *pool = NULL;
@ -101,7 +100,6 @@ KS_DECLARE(ks_status_t) blade_rpc_create(blade_rpc_t **brpcP, blade_handle_t *bh
brpc->handle = bh;
brpc->method = ks_pstrdup(pool, method);
if (protocol) brpc->protocol = ks_pstrdup(pool, protocol);
if (realm) brpc->realm = ks_pstrdup(pool, realm);
brpc->callback = callback;
brpc->data = data;
@ -151,13 +149,6 @@ KS_DECLARE(const char *) blade_rpc_protocol_get(blade_rpc_t *brpc)
return brpc->protocol;
}
KS_DECLARE(const char *) blade_rpc_realm_get(blade_rpc_t *brpc)
{
ks_assert(brpc);
return brpc->realm;
}
KS_DECLARE(blade_rpc_request_callback_t) blade_rpc_callback_get(blade_rpc_t *brpc)
{
ks_assert(brpc);

View File

@ -177,7 +177,7 @@ KS_DECLARE(ks_status_t) blade_rpcmgr_corerpc_remove(blade_rpcmgr_t *brpcmgr, bla
return KS_STATUS_SUCCESS;
}
KS_DECLARE(blade_rpc_t *) blade_rpcmgr_protocolrpc_lookup(blade_rpcmgr_t *brpcmgr, const char *method, const char *protocol, const char *realm)
KS_DECLARE(blade_rpc_t *) blade_rpcmgr_protocolrpc_lookup(blade_rpcmgr_t *brpcmgr, const char *method, const char *protocol)
{
blade_rpc_t *brpc = NULL;
char *key = NULL;
@ -185,9 +185,8 @@ KS_DECLARE(blade_rpc_t *) blade_rpcmgr_protocolrpc_lookup(blade_rpcmgr_t *brpcmg
ks_assert(brpcmgr);
ks_assert(method);
ks_assert(protocol);
ks_assert(realm);
key = ks_psprintf(ks_pool_get(brpcmgr), "%s@%s/%s", protocol, realm, method);
key = ks_psprintf(ks_pool_get(brpcmgr), "%s:%s", protocol, method);
brpc = ks_hash_search(brpcmgr->protocolrpcs, (void *)key, KS_READLOCKED);
// @todo if (brpc) blade_rpc_read_lock(brpc);
ks_hash_read_unlock(brpcmgr->protocolrpcs);
@ -201,7 +200,6 @@ KS_DECLARE(ks_status_t) blade_rpcmgr_protocolrpc_add(blade_rpcmgr_t *brpcmgr, bl
{
const char *method = NULL;
const char *protocol = NULL;
const char *realm = NULL;
char *key = NULL;
ks_assert(brpcmgr);
@ -213,10 +211,7 @@ KS_DECLARE(ks_status_t) blade_rpcmgr_protocolrpc_add(blade_rpcmgr_t *brpcmgr, bl
protocol = blade_rpc_protocol_get(brpc);
ks_assert(protocol);
realm = blade_rpc_realm_get(brpc);
ks_assert(realm);
key = ks_psprintf(ks_pool_get(brpcmgr), "%s@%s/%s", protocol, realm, method);
key = ks_psprintf(ks_pool_get(brpcmgr), "%s:%s", protocol, method);
ks_assert(key);
ks_hash_insert(brpcmgr->protocolrpcs, (void *)key, (void *)brpc);
@ -231,7 +226,6 @@ KS_DECLARE(ks_status_t) blade_rpcmgr_protocolrpc_remove(blade_rpcmgr_t *brpcmgr,
{
const char *method = NULL;
const char *protocol = NULL;
const char *realm = NULL;
char *key = NULL;
ks_assert(brpcmgr);
@ -243,10 +237,7 @@ KS_DECLARE(ks_status_t) blade_rpcmgr_protocolrpc_remove(blade_rpcmgr_t *brpcmgr,
protocol = blade_rpc_protocol_get(brpc);
ks_assert(protocol);
realm = blade_rpc_realm_get(brpc);
ks_assert(realm);
key = ks_psprintf(ks_pool_get(brpcmgr), "%s@%s/%s", protocol, realm, method);
key = ks_psprintf(ks_pool_get(brpcmgr), "%s:%s", protocol, method);
ks_assert(key);
ks_hash_remove(brpcmgr->protocolrpcs, (void *)key);

View File

@ -189,7 +189,7 @@ KS_DECLARE(ks_status_t) blade_session_shutdown(blade_session_t *bs)
}
ks_hash_read_unlock(bs->routes);
// this will also clear the local id, master id and realms in the handle if this is the upstream session
// this will also clear the local id, and master id in the handle if this is the upstream session
blade_sessionmgr_session_remove(blade_handle_sessionmgr_get(bs->handle), bs);
while (ks_q_trypop(bs->sending, (void **)&json) == KS_STATUS_SUCCESS && json) cJSON_Delete(json);
@ -641,15 +641,16 @@ ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
if (params) {
const char *params_requester_nodeid = cJSON_GetObjectCstr(params, "requester-nodeid");
const char *params_responder_nodeid = cJSON_GetObjectCstr(params, "responder-nodeid");
if (params_requester_nodeid && params_responder_nodeid && !blade_upstreammgr_localid_compare(blade_handle_upstreammgr_get(bh), params_responder_nodeid)) {
if (params_requester_nodeid && params_responder_nodeid && !blade_routemgr_local_check(blade_handle_routemgr_get(bh), params_responder_nodeid)) {
// not meant for local processing, continue with standard unicast routing for requests
blade_session_t *bs_router = blade_routemgr_route_lookup(blade_handle_routemgr_get(bh), params_responder_nodeid);
if (!bs_router) {
bs_router = blade_upstreammgr_session_get(blade_handle_upstreammgr_get(bh));
bs_router = blade_routemgr_upstream_lookup(blade_handle_routemgr_get(bh));
if (!bs_router) {
cJSON *res = NULL;
cJSON *res_error = NULL;
// @todo adjust error when this is master to be route unavailable
ks_log(KS_LOG_DEBUG, "Session (%s) request (%s => %s) but upstream session unavailable\n", blade_session_id_get(bs), params_requester_nodeid, params_responder_nodeid);
blade_rpc_error_raw_create(&res, &res_error, id, -32603, "Upstream session unavailable");
@ -714,11 +715,11 @@ ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
if (object) {
const char *object_requester_nodeid = cJSON_GetObjectCstr(object, "requester-nodeid");
const char *object_responder_nodeid = cJSON_GetObjectCstr(object, "responder-nodeid");
if (object_requester_nodeid && object_responder_nodeid && !blade_upstreammgr_localid_compare(blade_handle_upstreammgr_get(bh), object_requester_nodeid)) {
if (object_requester_nodeid && object_responder_nodeid && !blade_routemgr_local_check(blade_handle_routemgr_get(bh), object_requester_nodeid)) {
// not meant for local processing, continue with standard unicast routing for responses
blade_session_t *bs_router = blade_routemgr_route_lookup(blade_handle_routemgr_get(bh), object_requester_nodeid);
if (!bs_router) {
bs_router = blade_upstreammgr_session_get(blade_handle_upstreammgr_get(bh));
bs_router = blade_routemgr_upstream_lookup(blade_handle_routemgr_get(bh));
if (!bs_router) {
ks_log(KS_LOG_DEBUG, "Session (%s) response (%s <= %s) but upstream session unavailable\n", blade_session_id_get(bs), object_requester_nodeid, object_responder_nodeid);
return KS_STATUS_DISCONNECTED;

View File

@ -183,6 +183,7 @@ KS_DECLARE(ks_status_t) blade_sessionmgr_session_add(blade_sessionmgr_t *bsmgr,
KS_DECLARE(ks_status_t) blade_sessionmgr_session_remove(blade_sessionmgr_t *bsmgr, blade_session_t *bs)
{
const char *id = NULL;
blade_routemgr_t *routemgr = NULL;
ks_assert(bsmgr);
ks_assert(bs);
@ -194,9 +195,17 @@ KS_DECLARE(ks_status_t) blade_sessionmgr_session_remove(blade_sessionmgr_t *bsmg
ks_log(KS_LOG_DEBUG, "Session Removed: %s\n", id);
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);
routemgr = blade_handle_routemgr_get(bsmgr->handle);
if (blade_routemgr_local_check(routemgr, id)) {
blade_routemgr_local_set(routemgr, NULL);
blade_routemgr_master_set(routemgr, NULL);
// @todo this is the upstream session that has actually terminated, any downstream connections should also be terminated
// properly, such that the downstream clients will not attempt to reconnect with the same session id, but will instead
// reestablish new sessions and likewise terminate downstream sessions
// @todo this also reflects that downstream connections should not be accepted in the transport implementation until an
// upstream connection has been established, unless it is the master node which has no upstream session, plumbing to
// support this does not yet exist
}
blade_session_write_unlock(bs);

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,6 @@
struct blade_subscription_s {
const char *protocol;
const char *realm;
const char *channel;
ks_hash_t *subscribers;
@ -55,7 +54,6 @@ static void blade_subscription_cleanup(void *ptr, void *arg, ks_pool_cleanup_act
break;
case KS_MPCL_TEARDOWN:
if (bsub->protocol) ks_pool_free(&bsub->protocol);
if (bsub->realm) ks_pool_free(&bsub->subscribers);
if (bsub->channel) ks_pool_free(&bsub->channel);
if (bsub->subscribers) ks_hash_destroy(&bsub->subscribers);
break;
@ -64,19 +62,17 @@ static void blade_subscription_cleanup(void *ptr, void *arg, ks_pool_cleanup_act
}
}
KS_DECLARE(ks_status_t) blade_subscription_create(blade_subscription_t **bsubP, ks_pool_t *pool, const char *protocol, const char *realm, const char *channel)
KS_DECLARE(ks_status_t) blade_subscription_create(blade_subscription_t **bsubP, ks_pool_t *pool, const char *protocol, const char *channel)
{
blade_subscription_t *bsub = NULL;
ks_assert(bsubP);
ks_assert(pool);
ks_assert(protocol);
ks_assert(realm);
ks_assert(channel);
bsub = ks_pool_alloc(pool, sizeof(blade_subscription_t));
bsub->protocol = ks_pstrdup(pool, protocol);
bsub->realm = ks_pstrdup(pool, realm);
bsub->channel = ks_pstrdup(pool, channel);
ks_hash_create(&bsub->subscribers, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool);
@ -104,15 +100,6 @@ KS_DECLARE(const char *) blade_subscription_protocol_get(blade_subscription_t *b
ks_assert(bsub);
return bsub->protocol;
}
KS_DECLARE(const char *) blade_subscription_realm_get(blade_subscription_t *bsub)
{
ks_assert(bsub);
return bsub->realm;
}
KS_DECLARE(const char *) blade_subscription_channel_get(blade_subscription_t *bsub)
@ -120,7 +107,6 @@ KS_DECLARE(const char *) blade_subscription_channel_get(blade_subscription_t *bs
ks_assert(bsub);
return bsub->channel;
}
KS_DECLARE(ks_hash_t *) blade_subscription_subscribers_get(blade_subscription_t *bsub)
@ -128,7 +114,6 @@ KS_DECLARE(ks_hash_t *) blade_subscription_subscribers_get(blade_subscription_t
ks_assert(bsub);
return bsub->subscribers;
}
KS_DECLARE(ks_status_t) blade_subscription_subscribers_add(blade_subscription_t *bsub, const char *nodeid)

View File

@ -124,17 +124,16 @@ KS_DECLARE(blade_handle_t *) blade_subscriptionmgr_handle_get(blade_subscription
// return bs;
//}
KS_DECLARE(blade_subscription_t *) blade_subscriptionmgr_subscription_lookup(blade_subscriptionmgr_t *bsmgr, const char *protocol, const char *realm, const char *channel)
KS_DECLARE(blade_subscription_t *) blade_subscriptionmgr_subscription_lookup(blade_subscriptionmgr_t *bsmgr, const char *protocol, const char *channel)
{
blade_subscription_t *bsub = NULL;
char *key = NULL;
ks_assert(bsmgr);
ks_assert(protocol);
ks_assert(realm);
ks_assert(channel);
key = ks_psprintf(ks_pool_get(bsmgr), "%s@%s/%s", protocol, realm, channel);
key = ks_psprintf(ks_pool_get(bsmgr), "%s:%s", protocol, channel);
bsub = (blade_subscription_t *)ks_hash_search(bsmgr->subscriptions, (void *)key, KS_READLOCKED);
// @todo if (bsub) blade_subscription_read_lock(bsub);
@ -145,7 +144,7 @@ KS_DECLARE(blade_subscription_t *) blade_subscriptionmgr_subscription_lookup(bla
return bsub;
}
KS_DECLARE(ks_status_t) blade_subscriptionmgr_subscription_remove(blade_subscriptionmgr_t *bsmgr, const char *protocol, const char *realm, const char *channel)
KS_DECLARE(ks_status_t) blade_subscriptionmgr_subscription_remove(blade_subscriptionmgr_t *bsmgr, const char *protocol, const char *channel)
{
ks_pool_t *pool = NULL;
char *bsub_key = NULL;
@ -155,12 +154,11 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_subscription_remove(blade_subscrip
ks_assert(bsmgr);
ks_assert(protocol);
ks_assert(realm);
ks_assert(channel);
pool = ks_pool_get(bsmgr);
bsub_key = ks_psprintf(pool, "%s@%s/%s", protocol, realm, channel);
bsub_key = ks_psprintf(pool, "%s:%s", protocol, channel);
ks_hash_write_lock(bsmgr->subscriptions);
@ -177,7 +175,7 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_subscription_remove(blade_subscrip
subscriptions = (ks_hash_t *)ks_hash_search(bsmgr->subscriptions_cleanup, key, KS_UNLOCKED);
ks_log(KS_LOG_DEBUG, "Subscriber Removed: %s from %s\n", key, bsub_key);
ks_log(KS_LOG_DEBUG, "Subscriber Removed: %s from protocol %s, channel %s\n", key, protocol, channel);
ks_hash_remove(subscriptions, bsub_key);
if (ks_hash_count(subscriptions) == 0) {
@ -185,7 +183,7 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_subscription_remove(blade_subscrip
}
}
ks_log(KS_LOG_DEBUG, "Subscription Removed: %s\n", bsub_key);
ks_log(KS_LOG_DEBUG, "Subscription Removed: %s from %s\n", channel, protocol);
ks_hash_remove(bsmgr->subscriptions, (void *)bsub_key);
ks_hash_write_unlock(bsmgr->subscriptions);
@ -195,7 +193,7 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_subscription_remove(blade_subscrip
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_add(blade_subscriptionmgr_t *bsmgr, blade_subscription_t **bsubP, const char *protocol, const char *realm, const char *channel, const char *subscriber)
KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_add(blade_subscriptionmgr_t *bsmgr, blade_subscription_t **bsubP, const char *protocol, const char *channel, const char *subscriber)
{
ks_pool_t *pool = NULL;
char *key = NULL;
@ -205,20 +203,19 @@ KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_add(blade_subscriptionmgr
ks_assert(bsmgr);
ks_assert(protocol);
ks_assert(realm);
ks_assert(channel);
ks_assert(subscriber);
pool = ks_pool_get(bsmgr);
key = ks_psprintf(pool, "%s@%s/%s", protocol, realm, channel);
key = ks_psprintf(pool, "%s:%s", protocol, channel);
ks_hash_write_lock(bsmgr->subscriptions);
bsub = (blade_subscription_t *)ks_hash_search(bsmgr->subscriptions, (void *)key, KS_UNLOCKED);
if (!bsub) {
blade_subscription_create(&bsub, pool, protocol, realm, channel);
blade_subscription_create(&bsub, pool, protocol, channel);
ks_assert(bsub);
ks_hash_insert(bsmgr->subscriptions, (void *)ks_pstrdup(pool, key), (void *)bsub);
@ -230,7 +227,7 @@ KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_add(blade_subscriptionmgr
ks_hash_create(&bsub_cleanup, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool);
ks_assert(bsub_cleanup);
ks_log(KS_LOG_DEBUG, "Subscription Added: %s\n", key);
ks_log(KS_LOG_DEBUG, "Subscription Added: %s to %s\n", channel, protocol);
ks_hash_insert(bsmgr->subscriptions_cleanup, (void *)ks_pstrdup(pool, subscriber), (void *)bsub_cleanup);
}
ks_hash_insert(bsub_cleanup, (void *)ks_pstrdup(pool, key), (void *)KS_TRUE);
@ -239,7 +236,7 @@ KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_add(blade_subscriptionmgr
ks_hash_write_unlock(bsmgr->subscriptions);
ks_log(KS_LOG_DEBUG, "Subscriber Added: %s to %s\n", subscriber, key);
ks_log(KS_LOG_DEBUG, "Subscriber Added: %s to protocol %s, channel %s\n", subscriber, protocol, channel);
ks_pool_free(&key);
@ -248,7 +245,7 @@ KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_add(blade_subscriptionmgr
return propagate;
}
KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_remove(blade_subscriptionmgr_t *bsmgr, blade_subscription_t **bsubP, const char *protocol, const char *realm, const char *channel, const char *subscriber)
KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_remove(blade_subscriptionmgr_t *bsmgr, blade_subscription_t **bsubP, const char *protocol, const char *channel, const char *subscriber)
{
char *key = NULL;
blade_subscription_t *bsub = NULL;
@ -257,11 +254,10 @@ KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_remove(blade_subscription
ks_assert(bsmgr);
ks_assert(protocol);
ks_assert(realm);
ks_assert(channel);
ks_assert(subscriber);
key = ks_psprintf(ks_pool_get(bsmgr), "%s@%s/%s", protocol, realm, channel);
key = ks_psprintf(ks_pool_get(bsmgr), "%s:%s", protocol, channel);
ks_hash_write_lock(bsmgr->subscriptions);
@ -276,11 +272,11 @@ KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_remove(blade_subscription
ks_hash_remove(bsmgr->subscriptions_cleanup, (void *)subscriber);
}
ks_log(KS_LOG_DEBUG, "Subscriber Removed: %s from %s\n", subscriber, key);
ks_log(KS_LOG_DEBUG, "Subscriber Removed: %s from protocol %s, channel %s\n", subscriber, protocol, channel);
blade_subscription_subscribers_remove(bsub, subscriber);
if (ks_hash_count(blade_subscription_subscribers_get(bsub)) == 0) {
ks_log(KS_LOG_DEBUG, "Subscription Removed: %s\n", key);
ks_log(KS_LOG_DEBUG, "Subscription Removed: %s from %s\n", channel, protocol);
ks_hash_remove(bsmgr->subscriptions, (void *)key);
propagate = KS_TRUE;
}
@ -309,7 +305,6 @@ KS_DECLARE(void) blade_subscriptionmgr_purge(blade_subscriptionmgr_t *bsmgr, con
while (!unsubbed) {
ks_hash_t *subscriptions = NULL;
const char *protocol = NULL;
const char *realm = NULL;
const char *channel = NULL;
ks_hash_read_lock(bsmgr->subscriptions);
@ -330,22 +325,20 @@ KS_DECLARE(void) blade_subscriptionmgr_purge(blade_subscriptionmgr_t *bsmgr, con
// @note allocate these to avoid lifecycle issues when the last subscriber is removed causing the subscription to be removed
protocol = ks_pstrdup(pool, blade_subscription_protocol_get(bsub));
realm = ks_pstrdup(pool, blade_subscription_realm_get(bsub));
channel = ks_pstrdup(pool, blade_subscription_channel_get(bsub));
}
ks_hash_read_unlock(bsmgr->subscriptions);
if (!unsubbed) {
blade_subscriptionmgr_subscriber_remove(bsmgr, NULL, protocol, realm, channel, target);
blade_subscriptionmgr_subscriber_remove(bsmgr, NULL, protocol, channel, target);
ks_pool_free(&protocol);
ks_pool_free(&realm);
ks_pool_free(&channel);
}
}
}
KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t *bsmgr, blade_rpcbroadcast_command_t command, const char *excluded_nodeid, const char *protocol, const char *realm, const char *channel, const char *event, cJSON *params, blade_rpc_response_callback_t callback, void *data)
KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t *bsmgr, blade_rpcbroadcast_command_t command, const char *excluded_nodeid, const char *protocol, const char *channel, const char *event, cJSON *params, blade_rpc_response_callback_t callback, void *data)
{
ks_pool_t *pool = NULL;
const char *bsub_key = NULL;
@ -358,16 +351,16 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t
ks_assert(bsmgr);
ks_assert(protocol);
ks_assert(realm);
pool = ks_pool_get(bsmgr);
switch (command) {
case BLADE_RPCBROADCAST_COMMAND_EVENT:
ks_assert(channel);
ks_assert(event);
case BLADE_RPCBROADCAST_COMMAND_CHANNEL_REMOVE:
ks_assert(channel);
bsub_key = ks_psprintf(pool, "%s@%s/%s", protocol, realm, channel);
bsub_key = ks_psprintf(pool, "%s:%s", protocol, channel);
ks_hash_read_lock(bsmgr->subscriptions);
@ -386,7 +379,7 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t
if (excluded_nodeid && !ks_safe_strcasecmp(excluded_nodeid, (const char *)key)) continue;
// @todo broadcast producer is also a local subscriber... requires special consideration with no session to request through
if (blade_upstreammgr_localid_compare(blade_handle_upstreammgr_get(bsmgr->handle), (const char *)key)) continue;
if (blade_routemgr_local_check(blade_handle_routemgr_get(bsmgr->handle), (const char *)key)) continue;
bs = blade_routemgr_route_lookup(blade_handle_routemgr_get(bsmgr->handle), (const char *)key);
if (bs) {
@ -404,7 +397,7 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t
ks_hash_read_unlock(bsmgr->subscriptions);
break;
case BLADE_RPCBROADCAST_COMMAND_PROTOCOL_REMOVE:
bsub_key = ks_psprintf(pool, "%s@%s", protocol, realm);
bsub_key = ks_pstrdup(pool, protocol);
ks_hash_read_lock(bsmgr->subscriptions);
@ -430,7 +423,7 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t
if (excluded_nodeid && !ks_safe_strcasecmp(excluded_nodeid, (const char *)key2)) continue;
// @todo broadcast producer is also a local subscriber... requires special consideration with no session to request through
if (blade_upstreammgr_localid_compare(blade_handle_upstreammgr_get(bsmgr->handle), (const char *)key2)) continue;
if (blade_routemgr_local_check(blade_handle_routemgr_get(bsmgr->handle), (const char *)key2)) continue;
bs = blade_routemgr_route_lookup(blade_handle_routemgr_get(bsmgr->handle), (const char *)key2);
if (bs) {
@ -451,7 +444,7 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t
}
bs = blade_upstreammgr_session_get(blade_handle_upstreammgr_get(bsmgr->handle));
bs = blade_routemgr_upstream_lookup(blade_handle_routemgr_get(bsmgr->handle));
if (bs) {
if (!excluded_nodeid || ks_safe_strcasecmp(blade_session_id_get(bs), excluded_nodeid)) {
if (!routers) ks_hash_create(&routers, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, pool);
@ -467,7 +460,7 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t
ks_hash_this(it, (const void **)&key, NULL, &value);
blade_subscriptionmgr_subscription_remove(bsmgr, protocol, realm, (const char *)key);
blade_subscriptionmgr_subscription_remove(bsmgr, protocol, (const char *)key);
}
ks_hash_destroy(&channels);
}
@ -484,12 +477,11 @@ KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t
blade_rpc_request_raw_create(pool, &req, &req_params, NULL, "blade.broadcast");
cJSON_AddNumberToObject(req_params, "command", command);
cJSON_AddStringToObject(req_params, "protocol", protocol);
cJSON_AddStringToObject(req_params, "realm", realm);
if (channel) cJSON_AddStringToObject(req_params, "channel", channel);
if (event) cJSON_AddStringToObject(req_params, "event", event);
if (params) cJSON_AddItemToObject(req_params, "params", cJSON_Duplicate(params, 1));
ks_log(KS_LOG_DEBUG, "Broadcasting: %s through %s\n", bsub_key, blade_session_id_get(bs));
ks_log(KS_LOG_DEBUG, "Broadcasting: protocol %s, channel %s through %s\n", protocol, channel, blade_session_id_get(bs));
blade_session_send(bs, req, callback, data);

View File

@ -609,7 +609,7 @@ ks_status_t blade_transport_wss_onconnect(blade_connection_t **bcP, blade_transp
int family = AF_INET;
const char *ip = NULL;
const char *portstr = NULL;
ks_port_t port = 1234;
ks_port_t port = 2100;
blade_transport_wss_link_t *btwssl = NULL;
blade_connection_t *bc = NULL;
@ -621,19 +621,18 @@ ks_status_t blade_transport_wss_onconnect(blade_connection_t **bcP, blade_transp
*bcP = NULL;
ks_log(KS_LOG_DEBUG, "Connect Callback: %s\n", blade_identity_uri(target));
ks_log(KS_LOG_DEBUG, "Connect Callback: %s\n", blade_identity_uri_get(target));
// @todo completely rework all of this once more is known about connecting when an identity has no explicit transport details but this transport
// has been choosen anyway
ip = blade_identity_parameter_get(target, "host");
portstr = blade_identity_parameter_get(target, "port");
ip = blade_identity_host_get(target);
portstr = blade_identity_port_get(target);
if (!ip) {
// @todo: temporary, this should fall back on DNS SRV or whatever else can turn "a@b.com" into an ip (and port?) to connect to
// also need to deal with hostname lookup, so identities with wss transport need to have a host parameter that is an IP for the moment
ks_log(KS_LOG_DEBUG, "No host provided\n");
ret = KS_STATUS_FAIL;
goto done;
}
// @todo: this should detect IP's and fall back on DNS and/or SRV for hostname lookup, for the moment hosts must be IP's
// @todo wrap this code to get address family from string IP between IPV4 and IPV6, and put it in libks somewhere
{
@ -830,12 +829,10 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_inbound(blade_
//cJSON *error = NULL;
blade_session_t *bs = NULL;
blade_handle_t *bh = NULL;
ks_pool_t *pool = NULL;
const char *jsonrpc = NULL;
const char *id = NULL;
const char *method = NULL;
const char *nodeid = NULL;
const char *master_nodeid = NULL;
ks_time_t timeout;
ks_assert(bc);
@ -951,9 +948,9 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_inbound(blade_
// from having long running write locks when a session cleans up
blade_session_route_add(bs, nodeid);
// This is the main routing entry to make an identity routable through a session when a message is received for a given identity in this table, these allow to efficiently determine which session
// a message should pass through when it does not match the local node id from blade_upstreammgr_t, and must be matched with a call to blade_session_route_add() for cleanup, additionally when
// 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
// a message should pass through when it does not match the local node id from blade_routemgr_t, and must be matched with a call to blade_session_route_add() for cleanup, additionally when
// a "blade.route" is received the identity it carries affects these routes along with the sessionid of the downstream session it came through, and "blade.route" would also
// result in the new identities being added as routes however federation registration would require a special process to maintain proper routing
blade_routemgr_route_add(blade_handle_routemgr_get(bh), nodeid, nodeid);
}
@ -962,18 +959,12 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_inbound(blade_
cJSON_AddStringToObject(json_result, "nodeid", nodeid);
// @todo process automatic identity registration from remote SANS entries
pool = ks_pool_get(bh);
blade_upstreammgr_masterid_copy(blade_handle_upstreammgr_get(bh), pool, &master_nodeid);
if (!master_nodeid) {
if (!blade_routemgr_master_pack(blade_handle_routemgr_get(bh), json_result, "master-nodeid")) {
ks_log(KS_LOG_DEBUG, "Master nodeid unavailable\n");
blade_transport_wss_rpc_error_send(bc, id, -32602, "Master nodeid unavailable");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
cJSON_AddStringToObject(json_result, "master-nodeid", master_nodeid);
ks_pool_free(&master_nodeid);
// 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
@ -995,7 +986,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_inbound(blade_
if (json_req) cJSON_Delete(json_req);
if (json_res) cJSON_Delete(json_res);
return ret;
}
@ -1103,8 +1093,6 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_outbound(blade
goto done;
}
// @todo parse and process automatic identity registration coming from local SANS entries, but given back in the connect response in case there are any errors (IE: missing realm or duplicate identity)
master_nodeid = cJSON_GetObjectCstr(json_result, "master-nodeid");
if (!master_nodeid) {
ks_log(KS_LOG_DEBUG, "Received message 'result' is missing 'master-nodeid'\n");
@ -1137,7 +1125,7 @@ blade_connection_state_hook_t blade_transport_wss_onstate_startup_outbound(blade
// This is an outbound connection, thus it is always creating an upstream session, defined by the sessionid matching the local_nodeid in the handle
if (blade_upstreammgr_localid_set(blade_handle_upstreammgr_get(bh), nodeid) != KS_STATUS_SUCCESS) {
if (blade_routemgr_local_set(blade_handle_routemgr_get(bh), nodeid) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_DEBUG, "Session (%s) abandoned, upstream already available\n", blade_session_id_get(bs));
blade_session_read_unlock(bs);
blade_session_hangup(bs);
@ -1149,7 +1137,7 @@ 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);
blade_routemgr_master_set(blade_handle_routemgr_get(bh), master_nodeid);
}
blade_connection_session_set(bc, blade_session_id_get(bs));

View File

@ -1,267 +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"
struct blade_upstreammgr_s {
blade_handle_t *handle;
// local node id, can be used to get the upstream session, provided by upstream "blade.connect" response
const char *localid;
ks_rwl_t *localid_rwl;
// master node id, provided by upstream "blade.connect" response
const char *masterid;
ks_rwl_t *masterid_rwl;
};
static void blade_upstreammgr_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type)
{
//blade_upstreammgr_t *bumgr = (blade_upstreammgr_t *)ptr;
//ks_assert(brmgr);
switch (action) {
case KS_MPCL_ANNOUNCE:
break;
case KS_MPCL_TEARDOWN:
break;
case KS_MPCL_DESTROY:
break;
}
}
KS_DECLARE(ks_status_t) blade_upstreammgr_create(blade_upstreammgr_t **bumgrP, blade_handle_t *bh)
{
ks_pool_t *pool = NULL;
blade_upstreammgr_t *bumgr = NULL;
ks_assert(bumgrP);
ks_pool_open(&pool);
ks_assert(pool);
bumgr = ks_pool_alloc(pool, sizeof(blade_upstreammgr_t));
bumgr->handle = bh;
//ks_hash_create(&bumgr->routes, 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(bumgr->routes);
ks_rwl_create(&bumgr->localid_rwl, pool);
ks_assert(bumgr->localid_rwl);
ks_rwl_create(&bumgr->masterid_rwl, pool);
ks_assert(bumgr->masterid_rwl);
ks_pool_set_cleanup(bumgr, NULL, blade_upstreammgr_cleanup);
*bumgrP = bumgr;
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_upstreammgr_destroy(blade_upstreammgr_t **bumgrP)
{
blade_upstreammgr_t *bumgr = NULL;
ks_pool_t *pool;
ks_assert(bumgrP);
ks_assert(*bumgrP);
bumgr = *bumgrP;
*bumgrP = NULL;
pool = ks_pool_get(bumgr);
ks_pool_close(&pool);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(blade_handle_t *) blade_upstreammgr_handle_get(blade_upstreammgr_t *bumgr)
{
ks_assert(bumgr);
return bumgr->handle;
}
KS_DECLARE(ks_status_t) blade_upstreammgr_localid_set(blade_upstreammgr_t *bumgr, const char *id)
{
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(bumgr);
ks_rwl_write_lock(bumgr->localid_rwl);
if (bumgr->localid && id) {
ret = KS_STATUS_NOT_ALLOWED;
goto done;
}
if (!bumgr->localid && !id) {
ret = KS_STATUS_DISCONNECTED;
goto done;
}
if (bumgr->localid) ks_pool_free(&bumgr->localid);
if (id) bumgr->localid = ks_pstrdup(ks_pool_get(bumgr), id);
ks_log(KS_LOG_DEBUG, "LocalID: %s\n", id);
done:
ks_rwl_write_unlock(bumgr->localid_rwl);
return ret;
}
KS_DECLARE(ks_bool_t) blade_upstreammgr_localid_compare(blade_upstreammgr_t *bumgr, const char *id)
{
ks_bool_t ret = KS_FALSE;
ks_assert(bumgr);
ks_assert(id);
ks_rwl_read_lock(bumgr->localid_rwl);
ret = ks_safe_strcasecmp(bumgr->localid, id) == 0;
ks_rwl_read_unlock(bumgr->localid_rwl);
return ret;
}
KS_DECLARE(ks_status_t) blade_upstreammgr_localid_copy(blade_upstreammgr_t *bumgr, ks_pool_t *pool, const char **id)
{
ks_assert(bumgr);
ks_assert(pool);
ks_assert(id);
*id = NULL;
ks_rwl_read_lock(bumgr->localid_rwl);
if (bumgr->localid) *id = ks_pstrdup(pool, bumgr->localid);
ks_rwl_read_unlock(bumgr->localid_rwl);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_bool_t) blade_upstreammgr_session_established(blade_upstreammgr_t *bumgr)
{
ks_bool_t ret = KS_FALSE;
ks_assert(bumgr);
ks_rwl_read_lock(bumgr->localid_rwl);
ret = bumgr->localid != NULL;
ks_rwl_read_unlock(bumgr->localid_rwl);
return ret;
}
KS_DECLARE(blade_session_t *) blade_upstreammgr_session_get(blade_upstreammgr_t *bumgr)
{
blade_session_t *bs = NULL;
ks_assert(bumgr);
ks_rwl_read_lock(bumgr->localid_rwl);
if (bumgr->localid) bs = blade_sessionmgr_session_lookup(blade_handle_sessionmgr_get(bumgr->handle), bumgr->localid);
ks_rwl_read_unlock(bumgr->localid_rwl);
return bs;
}
KS_DECLARE(ks_status_t) blade_upstreammgr_masterid_set(blade_upstreammgr_t *bumgr, const char *id)
{
ks_status_t ret = KS_STATUS_SUCCESS;
ks_assert(bumgr);
ks_rwl_write_lock(bumgr->masterid_rwl);
if (bumgr->masterid) ks_pool_free(&bumgr->masterid);
if (id) bumgr->masterid = ks_pstrdup(ks_pool_get(bumgr), id);
ks_log(KS_LOG_DEBUG, "MasterID: %s\n", id);
ks_rwl_write_unlock(bumgr->masterid_rwl);
return ret;
}
KS_DECLARE(ks_bool_t) blade_upstreammgr_masterid_compare(blade_upstreammgr_t *bumgr, const char *id)
{
ks_bool_t ret = KS_FALSE;
ks_assert(bumgr);
ks_assert(id);
ks_rwl_read_lock(bumgr->masterid_rwl);
ret = ks_safe_strcasecmp(bumgr->masterid, id) == 0;
ks_rwl_read_unlock(bumgr->masterid_rwl);
return ret;
}
KS_DECLARE(ks_status_t) blade_upstreammgr_masterid_copy(blade_upstreammgr_t *bumgr, ks_pool_t *pool, const char **id)
{
ks_assert(bumgr);
ks_assert(pool);
ks_assert(id);
*id = NULL;
ks_rwl_read_lock(bumgr->masterid_rwl);
if (bumgr->masterid) *id = ks_pstrdup(pool, bumgr->masterid);
ks_rwl_read_unlock(bumgr->masterid_rwl);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_bool_t) blade_upstreammgr_masterlocal(blade_upstreammgr_t *bumgr)
{
ks_bool_t ret = KS_FALSE;
ks_assert(bumgr);
ks_rwl_read_lock(bumgr->masterid_rwl);
ks_rwl_read_lock(bumgr->localid_rwl);
ret = bumgr->masterid && bumgr->localid && !ks_safe_strcasecmp(bumgr->masterid, bumgr->localid);
ks_rwl_read_unlock(bumgr->localid_rwl);
ks_rwl_read_unlock(bumgr->masterid_rwl);
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

@ -44,7 +44,6 @@
#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"
@ -54,7 +53,6 @@
#include "blade_rpcmgr.h"
#include "blade_routemgr.h"
#include "blade_subscriptionmgr.h"
#include "blade_upstreammgr.h"
#include "blade_mastermgr.h"
#include "blade_connectionmgr.h"
#include "blade_sessionmgr.h"

View File

@ -36,9 +36,10 @@
#include <blade.h>
KS_BEGIN_EXTERN_C
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_create(blade_channel_t **bcP, ks_pool_t *pool, const char *name, blade_channel_flags_t flags);
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(blade_channel_flags_t) blade_channel_flags_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);

View File

@ -39,8 +39,14 @@ KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_identity_create(blade_identity_t **biP, ks_pool_t *pool);
KS_DECLARE(ks_status_t) blade_identity_destroy(blade_identity_t **biP);
KS_DECLARE(ks_status_t) blade_identity_parse(blade_identity_t *bi, const char *uri);
KS_DECLARE(const char *) blade_identity_uri(blade_identity_t *bi);
KS_DECLARE(const char *) blade_identity_parameter_get(blade_identity_t *bi, const char *key);
KS_DECLARE(const char *) blade_identity_uri_get(blade_identity_t *bi);
KS_DECLARE(const char *) blade_identity_scheme_get(blade_identity_t *bi);
KS_DECLARE(const char *) blade_identity_user_get(blade_identity_t *bi);
KS_DECLARE(const char *) blade_identity_host_get(blade_identity_t *bi);
KS_DECLARE(const char *) blade_identity_port_get(blade_identity_t *bi);
KS_DECLARE(ks_port_t) blade_identity_portnum_get(blade_identity_t *bi);
KS_DECLARE(const char *) blade_identity_path_get(blade_identity_t *bi);
KS_DECLARE(const char *) blade_identity_parameter_lookup(blade_identity_t *bi, const char *key);
KS_END_EXTERN_C
#endif

View File

@ -42,15 +42,13 @@ KS_DECLARE(ks_status_t) blade_mastermgr_startup(blade_mastermgr_t *bmmgr, 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(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_DECLARE(blade_protocol_t *) blade_mastermgr_protocol_lookup(blade_mastermgr_t *bmmgr, const char *protocol, ks_bool_t writelocked);
KS_DECLARE(ks_status_t) blade_mastermgr_protocol_controller_add(blade_mastermgr_t *bmmgr, const char *protocol, const char *controller);
KS_DECLARE(ks_status_t) blade_mastermgr_protocol_controller_remove(blade_mastermgr_t *bmmgr, const char *protocol, const char *controller);
KS_DECLARE(ks_status_t) blade_mastermgr_protocol_channel_add(blade_mastermgr_t *bmmgr, const char *protocol, const char *channel, blade_channel_flags_t flags);
KS_DECLARE(ks_status_t) blade_mastermgr_protocol_channel_remove(blade_mastermgr_t *bmmgr, const char *protocol, const char *channel);
KS_DECLARE(ks_status_t) blade_mastermgr_protocol_channel_authorize(blade_mastermgr_t *bmmgr, ks_bool_t remove, const char *protocol, const char *channel, const char *controller, const char *target);
KS_DECLARE(ks_bool_t) blade_mastermgr_protocol_channel_authorization_verify(blade_mastermgr_t *bmmgr, const char *protocol, const char *channel, const char *target);
KS_END_EXTERN_C
#endif

View File

@ -36,9 +36,8 @@
#include <blade.h>
KS_BEGIN_EXTERN_C
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_create(blade_protocol_t **bpP, ks_pool_t *pool, 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(ks_status_t) blade_protocol_read_lock(blade_protocol_t *bp);
KS_DECLARE(ks_status_t) blade_protocol_read_unlock(blade_protocol_t *bp);

View File

@ -1,63 +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.
*/
#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

@ -39,9 +39,20 @@ KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_routemgr_create(blade_routemgr_t **brmgrP, blade_handle_t *bh);
KS_DECLARE(ks_status_t) blade_routemgr_destroy(blade_routemgr_t **brmgrP);
KS_DECLARE(blade_handle_t *) blade_routemgr_handle_get(blade_routemgr_t *brmgr);
KS_DECLARE(ks_status_t) blade_routemgr_local_set(blade_routemgr_t *brmgr, const char *nodeid);
KS_DECLARE(ks_bool_t) blade_routemgr_local_check(blade_routemgr_t *brmgr, const char *target);
KS_DECLARE(ks_bool_t) blade_routemgr_local_copy(blade_routemgr_t *brmgr, const char **nodeid);
KS_DECLARE(ks_bool_t) blade_routemgr_local_pack(blade_routemgr_t *brmgr, cJSON *json, const char *key);
KS_DECLARE(blade_session_t *) blade_routemgr_upstream_lookup(blade_routemgr_t *brmgr);
KS_DECLARE(ks_status_t) blade_routemgr_master_set(blade_routemgr_t *brmgr, const char *nodeid);
KS_DECLARE(ks_bool_t) blade_routemgr_master_check(blade_routemgr_t *brmgr, const char *target);
KS_DECLARE(ks_bool_t) blade_routemgr_master_pack(blade_routemgr_t *brmgr, cJSON *json, const char *key);
KS_DECLARE(ks_bool_t) blade_routemgr_master_local(blade_routemgr_t *brmgr);
KS_DECLARE(blade_session_t *) blade_routemgr_route_lookup(blade_routemgr_t *brmgr, const char *target);
KS_DECLARE(ks_status_t) blade_routemgr_route_add(blade_routemgr_t *brmgr, const char *target, const char *router);
KS_DECLARE(ks_status_t) blade_routemgr_route_remove(blade_routemgr_t *brmgr, const char *target);
KS_DECLARE(ks_status_t) blade_routemgr_identity_add(blade_routemgr_t *brmgr, blade_identity_t *identity, const char *target);
KS_DECLARE(ks_status_t) blade_routemgr_identity_remove(blade_routemgr_t *brmgr, blade_identity_t *identity, const char *target);
KS_END_EXTERN_C
#endif

View File

@ -36,12 +36,11 @@
#include <blade.h>
KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_rpc_create(blade_rpc_t **brpcP, blade_handle_t *bh, const char *method, const char *protocol, const char *realm, blade_rpc_request_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_rpc_create(blade_rpc_t **brpcP, blade_handle_t *bh, const char *method, const char *protocol, blade_rpc_request_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_rpc_destroy(blade_rpc_t **brpcP);
KS_DECLARE(blade_handle_t *) blade_rpc_handle_get(blade_rpc_t *brpc);
KS_DECLARE(const char *) blade_rpc_method_get(blade_rpc_t *brpc);
KS_DECLARE(const char *) blade_rpc_protocol_get(blade_rpc_t *brpc);
KS_DECLARE(const char *) blade_rpc_realm_get(blade_rpc_t *brpc);
KS_DECLARE(blade_rpc_request_callback_t) blade_rpc_callback_get(blade_rpc_t *brpc);
KS_DECLARE(void *) blade_rpc_data_get(blade_rpc_t *brpc);

View File

@ -42,7 +42,7 @@ KS_DECLARE(blade_handle_t *) blade_rpcmgr_handle_get(blade_rpcmgr_t *brpcmgr);
KS_DECLARE(blade_rpc_t *) blade_rpcmgr_corerpc_lookup(blade_rpcmgr_t *brpcmgr, const char *method);
KS_DECLARE(ks_status_t) blade_rpcmgr_corerpc_add(blade_rpcmgr_t *brpcmgr, blade_rpc_t *brpc);
KS_DECLARE(ks_status_t) blade_rpcmgr_corerpc_remove(blade_rpcmgr_t *brpcmgr, blade_rpc_t *brpc);
KS_DECLARE(blade_rpc_t *) blade_rpcmgr_protocolrpc_lookup(blade_rpcmgr_t *brpcmgr, const char *method, const char *protocol, const char *realm);
KS_DECLARE(blade_rpc_t *) blade_rpcmgr_protocolrpc_lookup(blade_rpcmgr_t *brpcmgr, const char *method, const char *protocol);
KS_DECLARE(ks_status_t) blade_rpcmgr_protocolrpc_add(blade_rpcmgr_t *brpcmgr, blade_rpc_t *brpc);
KS_DECLARE(ks_status_t) blade_rpcmgr_protocolrpc_remove(blade_rpcmgr_t *brpcmgr, blade_rpc_t *brpc);
KS_DECLARE(blade_rpc_request_t *) blade_rpcmgr_request_lookup(blade_rpcmgr_t *brpcmgr, const char *id);

View File

@ -43,9 +43,6 @@ KS_DECLARE(ks_status_t) blade_session_shutdown(blade_session_t *bs);
KS_DECLARE(blade_handle_t *) blade_session_handle_get(blade_session_t *bs);
KS_DECLARE(const char *) blade_session_id_get(blade_session_t *bs);
KS_DECLARE(blade_session_state_t) blade_session_state_get(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_session_realm_add(blade_session_t *bs, const char *realm);
KS_DECLARE(ks_status_t) blade_session_realm_remove(blade_session_t *bs, const char *realm);
KS_DECLARE(ks_hash_t *) blade_session_realms_get(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_session_route_add(blade_session_t *bs, const char *nodeid);
KS_DECLARE(ks_status_t) blade_session_route_remove(blade_session_t *bs, const char *nodeid);
KS_DECLARE(cJSON *) blade_session_properties_get(blade_session_t *bs);

View File

@ -51,33 +51,33 @@ KS_DECLARE(blade_transportmgr_t *) blade_handle_transportmgr_get(blade_handle_t
KS_DECLARE(blade_rpcmgr_t *) blade_handle_rpcmgr_get(blade_handle_t *bh);
KS_DECLARE(blade_routemgr_t *) blade_handle_routemgr_get(blade_handle_t *bh);
KS_DECLARE(blade_subscriptionmgr_t *) blade_handle_subscriptionmgr_get(blade_handle_t *bh);
KS_DECLARE(blade_upstreammgr_t *) blade_handle_upstreammgr_get(blade_handle_t *bh);
KS_DECLARE(blade_mastermgr_t *) blade_handle_mastermgr_get(blade_handle_t *bh);
KS_DECLARE(blade_connectionmgr_t *) blade_handle_connectionmgr_get(blade_handle_t *bh);
KS_DECLARE(blade_sessionmgr_t *) blade_handle_sessionmgr_get(blade_handle_t *bh);
KS_DECLARE(ks_status_t) blade_handle_connect(blade_handle_t *bh, blade_connection_t **bcP, blade_identity_t *target, const char *session_id);
KS_DECLARE(ks_status_t) blade_handle_rpcregister(blade_handle_t *bh, const char *nodeid, ks_bool_t remove, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpcroute(blade_handle_t *bh, const char *nodeid, ks_bool_t remove, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpcpublish(blade_handle_t *bh, blade_rpcpublish_command_t command, const char *protocol, const char *realm, cJSON *channels, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpcregister(blade_handle_t *bh, const char *identity, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpcauthorize(blade_handle_t *bh, const char *nodeid, ks_bool_t remove, const char *protocol, const char *realm, cJSON *channels, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpcpublish(blade_handle_t *bh, blade_rpcpublish_command_t command, const char *protocol, cJSON *channels, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpclocate(blade_handle_t *bh, const char *protocol, const char *realm, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpcauthorize(blade_handle_t *bh, const char *nodeid, ks_bool_t remove, const char *protocol, cJSON *channels, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpcexecute(blade_handle_t *bh, const char *nodeid, const char *method, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpclocate(blade_handle_t *bh, const char *protocol, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_handle_rpcexecute(blade_handle_t *bh, const char *nodeid, const char *method, const char *protocol, cJSON *params, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(const char *) blade_rpcexecute_request_requester_nodeid_get(blade_rpc_request_t *brpcreq);
KS_DECLARE(const char *) blade_rpcexecute_request_responder_nodeid_get(blade_rpc_request_t *brpcreq);
KS_DECLARE(cJSON *) blade_rpcexecute_request_params_get(blade_rpc_request_t *brpcreq);
KS_DECLARE(cJSON *) blade_rpcexecute_response_result_get(blade_rpc_response_t *brpcres);
KS_DECLARE(void) blade_rpcexecute_response_send(blade_rpc_request_t *brpcreq, cJSON *result);
KS_DECLARE(ks_status_t) blade_handle_rpcsubscribe(blade_handle_t *bh, blade_rpcsubscribe_command_t command, const char *protocol, const char *realm, cJSON *channels, blade_rpc_response_callback_t callback, void *data, blade_rpc_request_callback_t channel_callback, void *channel_data);
KS_DECLARE(ks_status_t) blade_handle_rpcsubscribe(blade_handle_t *bh, blade_rpcsubscribe_command_t command, const char *protocol, cJSON *channels, blade_rpc_response_callback_t callback, void *data, blade_rpc_request_callback_t channel_callback, void *channel_data);
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(ks_status_t) blade_handle_rpcbroadcast(blade_handle_t *bh, const char *protocol, 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);

View File

@ -36,10 +36,9 @@
#include <blade.h>
KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_subscription_create(blade_subscription_t **bsubP, ks_pool_t *pool, const char *protocol, const char *realm, const char *channel);
KS_DECLARE(ks_status_t) blade_subscription_create(blade_subscription_t **bsubP, ks_pool_t *pool, const char *protocol, const char *channel);
KS_DECLARE(ks_status_t) blade_subscription_destroy(blade_subscription_t **bsubP);
KS_DECLARE(const char *) blade_subscription_protocol_get(blade_subscription_t *bsub);
KS_DECLARE(const char *) blade_subscription_realm_get(blade_subscription_t *bsub);
KS_DECLARE(const char *) blade_subscription_channel_get(blade_subscription_t *bsub);
KS_DECLARE(ks_hash_t *) blade_subscription_subscribers_get(blade_subscription_t *bsub);
KS_DECLARE(ks_status_t) blade_subscription_subscribers_add(blade_subscription_t *bsub, const char *nodeid);

View File

@ -39,12 +39,12 @@ KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_subscriptionmgr_create(blade_subscriptionmgr_t **bsmgrP, blade_handle_t *bh);
KS_DECLARE(ks_status_t) blade_subscriptionmgr_destroy(blade_subscriptionmgr_t **bsmgrP);
KS_DECLARE(blade_handle_t *) blade_subscriptionmgr_handle_get(blade_subscriptionmgr_t *bsmgr);
KS_DECLARE(blade_subscription_t *) blade_subscriptionmgr_subscription_lookup(blade_subscriptionmgr_t *bsmgr, const char *protocol, const char *realm, const char *channel);
KS_DECLARE(ks_status_t) blade_subscriptionmgr_subscription_remove(blade_subscriptionmgr_t *bsmgr, const char *protocol, const char *realm, const char *channel);
KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_add(blade_subscriptionmgr_t *bsmgr, blade_subscription_t **bsubP, const char *protocol, const char *realm, const char *channel, const char *subscriber);
KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_remove(blade_subscriptionmgr_t *bsmgr, blade_subscription_t **bsubP, const char *protocol, const char *realm, const char *channel, const char *subscriber);
KS_DECLARE(blade_subscription_t *) blade_subscriptionmgr_subscription_lookup(blade_subscriptionmgr_t *bsmgr, const char *protocol, const char *channel);
KS_DECLARE(ks_status_t) blade_subscriptionmgr_subscription_remove(blade_subscriptionmgr_t *bsmgr, const char *protocol, const char *channel);
KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_add(blade_subscriptionmgr_t *bsmgr, blade_subscription_t **bsubP, const char *protocol, const char *channel, const char *subscriber);
KS_DECLARE(ks_bool_t) blade_subscriptionmgr_subscriber_remove(blade_subscriptionmgr_t *bsmgr, blade_subscription_t **bsubP, const char *protocol, const char *channel, const char *subscriber);
KS_DECLARE(void) blade_subscriptionmgr_purge(blade_subscriptionmgr_t *bsmgr, const char *target);
KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t *bsmgr, blade_rpcbroadcast_command_t command, const char *excluded_nodeid, const char *protocol, const char *realm, const char *channel, const char *event, cJSON *params, blade_rpc_response_callback_t callback, void *data);
KS_DECLARE(ks_status_t) blade_subscriptionmgr_broadcast(blade_subscriptionmgr_t *bsmgr, blade_rpcbroadcast_command_t command, const char *excluded_nodeid, const char *protocol, const char *channel, const char *event, cJSON *params, blade_rpc_response_callback_t callback, void *data);
KS_END_EXTERN_C
#endif

View File

@ -48,7 +48,6 @@ 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;
@ -58,7 +57,6 @@ typedef struct blade_transportmgr_s blade_transportmgr_t;
typedef struct blade_rpcmgr_s blade_rpcmgr_t;
typedef struct blade_routemgr_s blade_routemgr_t;
typedef struct blade_subscriptionmgr_s blade_subscriptionmgr_t;
typedef struct blade_upstreammgr_s blade_upstreammgr_t;
typedef struct blade_mastermgr_s blade_mastermgr_t;
typedef struct blade_connectionmgr_s blade_connectionmgr_t;
typedef struct blade_sessionmgr_s blade_sessionmgr_t;
@ -106,7 +104,10 @@ typedef enum {
BLADE_SESSION_STATE_RUN,
} blade_session_state_t;
typedef enum {
BLADE_CHANNEL_FLAGS_NONE = 0 << 0,
BLADE_CHANNEL_FLAGS_PUBLIC = 1 << 0,
} blade_channel_flags_t;
typedef ks_status_t (*blade_transport_startup_callback_t)(blade_transport_t *bt, config_setting_t *config);

View File

@ -1,65 +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.
*/
#ifndef _BLADE_UPSTREAMMGR_H_
#define _BLADE_UPSTREAMMGR_H_
#include <blade.h>
KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_upstreammgr_create(blade_upstreammgr_t **bumgrP, blade_handle_t *bh);
KS_DECLARE(ks_status_t) blade_upstreammgr_destroy(blade_upstreammgr_t **bumgrP);
KS_DECLARE(blade_handle_t *) blade_upstreammgr_handle_get(blade_upstreammgr_t *bumgr);
KS_DECLARE(ks_status_t) blade_upstreammgr_localid_set(blade_upstreammgr_t *bumgr, const char *id);
KS_DECLARE(ks_bool_t) blade_upstreammgr_localid_compare(blade_upstreammgr_t *bumgr, const char *id);
KS_DECLARE(ks_status_t) blade_upstreammgr_localid_copy(blade_upstreammgr_t *bumgr, ks_pool_t *pool, const char **id);
KS_DECLARE(ks_bool_t) blade_upstreammgr_session_established(blade_upstreammgr_t *bumgr);
KS_DECLARE(blade_session_t *) blade_upstreammgr_session_get(blade_upstreammgr_t *bumgr);
KS_DECLARE(ks_status_t) blade_upstreammgr_masterid_set(blade_upstreammgr_t *bumgr, const char *id);
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_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

@ -1,9 +1,28 @@
#include "blade.h"
#define CONSOLE_INPUT_MAX 512
// @todo switch to wait condition once something is being done with the main thread during runtime
ks_bool_t g_shutdown = KS_FALSE;
void idle(blade_handle_t *bh);
void loop(blade_handle_t *bh);
void process_console_input(blade_handle_t *bh, char *line);
typedef void(*command_callback)(blade_handle_t *bh, char *args);
struct command_def_s {
const char *cmd;
command_callback callback;
};
void command_quit(blade_handle_t *bh, char *args);
static const struct command_def_s command_defs[] = {
{ "quit", command_quit },
{ NULL, NULL }
};
int main(int argc, char **argv)
{
@ -40,7 +59,7 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
idle(bh);
loop(bh);
blade_handle_destroy(&bh);
@ -51,13 +70,70 @@ int main(int argc, char **argv)
return 0;
}
void idle(blade_handle_t *bh)
void loop(blade_handle_t *bh)
{
char buf[CONSOLE_INPUT_MAX];
while (!g_shutdown) {
ks_sleep_ms(1000);
if (!fgets(buf, CONSOLE_INPUT_MAX, stdin)) break;
for (int index = 0; buf[index]; ++index) {
if (buf[index] == '\r' || buf[index] == '\n') {
buf[index] = '\0';
break;
}
}
process_console_input(bh, buf);
ks_sleep_ms(100);
}
}
void parse_argument(char **input, char **arg, char terminator)
{
char *tmp;
ks_assert(input);
ks_assert(*input);
ks_assert(arg);
tmp = *input;
*arg = tmp;
while (*tmp && *tmp != terminator) ++tmp;
if (*tmp == terminator) {
*tmp = '\0';
++tmp;
}
*input = tmp;
}
void process_console_input(blade_handle_t *bh, char *line)
{
char *args = line;
char *cmd = NULL;
ks_bool_t found = KS_FALSE;
parse_argument(&args, &cmd, ' ');
ks_log(KS_LOG_DEBUG, "Command: %s, Args: %s\n", cmd, args);
for (int32_t index = 0; command_defs[index].cmd; ++index) {
if (!strcmp(command_defs[index].cmd, cmd)) {
found = KS_TRUE;
command_defs[index].callback(bh, args);
}
}
if (!found) ks_log(KS_LOG_INFO, "Command '%s' unknown.\n", cmd);
}
void command_quit(blade_handle_t *bh, char *args)
{
//ks_assert(bh);
//ks_assert(args);
g_shutdown = KS_TRUE;
}
/* For Emacs:
* Local Variables:

View File

@ -66,7 +66,6 @@ ks_bool_t blade_locate_response_handler(blade_rpc_response_t *brpcres, void *dat
cJSON *res_result = NULL;
cJSON *res_result_controllers = NULL;
const char *res_result_protocol = NULL;
const char *res_result_realm = NULL;
cJSON *params = NULL;
ks_assert(brpcres);
@ -86,9 +85,6 @@ ks_bool_t blade_locate_response_handler(blade_rpc_response_t *brpcres, void *dat
res_result_protocol = cJSON_GetObjectCstr(res_result, "protocol");
ks_assert(res_result_protocol);
res_result_realm = cJSON_GetObjectCstr(res_result, "realm");
ks_assert(res_result_realm);
res_result_controllers = cJSON_GetObjectItem(res_result, "controllers");
ks_assert(res_result_controllers);
@ -97,7 +93,7 @@ ks_bool_t blade_locate_response_handler(blade_rpc_response_t *brpcres, void *dat
for (int index = 0; index < cJSON_GetArraySize(res_result_controllers); ++index) {
cJSON *elem = cJSON_GetArrayItem(res_result_controllers, index);
if (elem->type == cJSON_String) {
ks_log(KS_LOG_DEBUG, "Session (%s) blade.locate (%s@%s) provider (%s)\n", blade_session_id_get(bs), res_result_protocol, res_result_realm, elem->valuestring);
ks_log(KS_LOG_DEBUG, "Session (%s) blade.locate (%s) provider (%s)\n", blade_session_id_get(bs), res_result_protocol, elem->valuestring);
nodeid = elem->valuestring;
}
}
@ -106,7 +102,7 @@ ks_bool_t blade_locate_response_handler(blade_rpc_response_t *brpcres, void *dat
params = cJSON_CreateObject();
cJSON_AddStringToObject(params, "text", "hello world!");
blade_handle_rpcexecute(bh, nodeid, "test.echo", res_result_protocol, res_result_realm, params, test_echo_response_handler, NULL);
blade_handle_rpcexecute(bh, nodeid, "test.echo", res_result_protocol, params, test_echo_response_handler, NULL);
return KS_FALSE;
}
@ -285,7 +281,7 @@ void command_execute(blade_handle_t *bh, char *args)
ks_assert(bh);
ks_assert(args);
blade_handle_rpclocate(bh, "test", "mydomain.com", blade_locate_response_handler, NULL);
blade_handle_rpclocate(bh, "test", blade_locate_response_handler, NULL);
}
void command_subscribe(blade_handle_t *bh, char *args)
@ -297,7 +293,7 @@ void command_subscribe(blade_handle_t *bh, char *args)
channels = cJSON_CreateArray();
cJSON_AddItemToArray(channels, cJSON_CreateString("test"));
blade_handle_rpcsubscribe(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_ADD, "test", "mydomain.com", channels, blade_subscribe_response_handler, NULL, test_event_request_handler, NULL);
blade_handle_rpcsubscribe(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_ADD, "test", channels, blade_subscribe_response_handler, NULL, test_event_request_handler, NULL);
cJSON_Delete(channels);
}

View File

@ -240,11 +240,11 @@ void command_publish(blade_handle_t *bh, char *args)
ks_assert(bh);
ks_assert(args);
blade_rpc_create(&brpc, bh, "test.echo", "test", "mydomain.com", test_echo_request_handler, NULL);
blade_rpc_create(&brpc, bh, "test.echo", "test", test_echo_request_handler, NULL);
blade_rpcmgr_protocolrpc_add(blade_handle_rpcmgr_get(bh), brpc);
// @todo build up json-based method schema for each protocolrpc registered above, and pass into blade_handle_rpcpublish() to attach to the request, to be stored in the blade_protocol_t tracked by the master node
blade_handle_rpcpublish(bh, BLADE_RPCPUBLISH_COMMAND_CONTROLLER_ADD, "test", "mydomain.com", NULL, blade_publish_response_handler, NULL);
blade_handle_rpcpublish(bh, BLADE_RPCPUBLISH_COMMAND_CONTROLLER_ADD, "test", NULL, blade_publish_response_handler, NULL);
}
void command_broadcast(blade_handle_t *bh, char *args)
@ -252,7 +252,7 @@ void command_broadcast(blade_handle_t *bh, char *args)
ks_assert(bh);
ks_assert(args);
blade_handle_rpcbroadcast(bh, "test", "mydomain.com", "channel", "event", NULL, test_broadcast_response_handler, NULL);
blade_handle_rpcbroadcast(bh, "test", "channel", "event", NULL, test_broadcast_response_handler, NULL);
}

View File

@ -46,7 +46,6 @@ ks_bool_t test_locate_response_handler(blade_rpc_response_t *brpcres, void *data
cJSON *res_result = NULL;
cJSON *res_result_controllers = NULL;
const char *res_result_protocol = NULL;
const char *res_result_realm = NULL;
//cJSON *params = NULL;
ks_assert(brpcres);
@ -66,12 +65,9 @@ ks_bool_t test_locate_response_handler(blade_rpc_response_t *brpcres, void *data
res_result_protocol = cJSON_GetObjectCstr(res_result, "protocol");
ks_assert(res_result_protocol);
res_result_realm = cJSON_GetObjectCstr(res_result, "realm");
ks_assert(res_result_realm);
res_result_controllers = cJSON_GetObjectItem(res_result, "controllers");
ks_log(KS_LOG_DEBUG, "Session (%s) locate (%s@%s) response processing\n", blade_session_id_get(bs), res_result_protocol, res_result_realm);
ks_log(KS_LOG_DEBUG, "Session (%s) locate (%s) response processing\n", blade_session_id_get(bs), res_result_protocol);
if (res_result_controllers) {
for (int index = 0; index < cJSON_GetArraySize(res_result_controllers); ++index) {
@ -89,7 +85,7 @@ ks_bool_t test_locate_response_handler(blade_rpc_response_t *brpcres, void *data
g_testcon_nodeid = ks_pstrdup(ks_pool_get(bh), nodeid);
}
ks_log(KS_LOG_DEBUG, "Session (%s) locate (%s@%s) provider (%s)\n", blade_session_id_get(bs), res_result_protocol, res_result_realm, g_testcon_nodeid);
ks_log(KS_LOG_DEBUG, "Session (%s) locate (%s) provider (%s)\n", blade_session_id_get(bs), res_result_protocol, g_testcon_nodeid);
return KS_FALSE;
}
@ -273,7 +269,7 @@ int main(int argc, char **argv)
if (connected) {
// @todo use session state change callback to know when the session is ready and the realm(s) available from blade.connect
// @todo use session state change callback to know when the session is ready after blade.connect
ks_sleep_ms(3000);
}
}
@ -356,7 +352,7 @@ void command_locate(blade_handle_t *bh, char *args)
ks_assert(bh);
ks_assert(args);
blade_handle_rpclocate(bh, "test", "mydomain.com", test_locate_response_handler, NULL);
blade_handle_rpclocate(bh, "test", test_locate_response_handler, NULL);
}
void command_join(blade_handle_t *bh, char *args)
@ -372,7 +368,7 @@ void command_join(blade_handle_t *bh, char *args)
}
params = cJSON_CreateObject();
blade_handle_rpcexecute(bh, g_testcon_nodeid, "test.join", "test", "mydomain.com", params, test_join_response_handler, NULL);
blade_handle_rpcexecute(bh, g_testcon_nodeid, "test.join", "test", params, test_join_response_handler, NULL);
cJSON_Delete(params);
}
@ -388,7 +384,7 @@ void command_subscribe(blade_handle_t *bh, char *args)
channels = cJSON_CreateArray();
cJSON_AddItemToArray(channels, cJSON_CreateString("channel"));
if (args && args[0]) cJSON_AddItemToArray(channels, cJSON_CreateString(args));
blade_handle_rpcsubscribe(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_ADD, "test", "mydomain.com", channels, NULL, NULL, test_channel_handler, NULL);
blade_handle_rpcsubscribe(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_ADD, "test", channels, NULL, NULL, test_channel_handler, NULL);
cJSON_Delete(channels);
}
@ -404,7 +400,7 @@ void command_unsubscribe(blade_handle_t *bh, char *args)
channels = cJSON_CreateArray();
cJSON_AddItemToArray(channels, cJSON_CreateString("channel"));
if (args && args[0]) cJSON_AddItemToArray(channels, cJSON_CreateString(args));
blade_handle_rpcsubscribe(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_REMOVE, "test", "mydomain.com", channels, test_subscribe_response_handler, NULL, test_channel_handler, NULL);
blade_handle_rpcsubscribe(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_REMOVE, "test", channels, test_subscribe_response_handler, NULL, test_channel_handler, NULL);
cJSON_Delete(channels);
}
@ -421,7 +417,7 @@ void command_leave(blade_handle_t *bh, char *args)
}
params = cJSON_CreateObject();
blade_handle_rpcexecute(bh, g_testcon_nodeid, "test.leave", "test", "mydomain.com", params, test_leave_response_handler, NULL);
blade_handle_rpcexecute(bh, g_testcon_nodeid, "test.leave", "test", params, test_leave_response_handler, NULL);
cJSON_Delete(params);
}
@ -443,7 +439,8 @@ void command_talk(blade_handle_t *bh, char *args)
params = cJSON_CreateObject();
cJSON_AddStringToObject(params, "text", args);
blade_handle_rpcexecute(bh, g_testcon_nodeid, "test.talk", "test", "mydomain.com", params, test_talk_response_handler, NULL);
//blade_handle_rpcexecute(bh, g_testcon_nodeid, "test.talk", "test", params, test_talk_response_handler, NULL);
blade_handle_rpcexecute(bh, "blade:testcon@freeswitch.com", "test.talk", "test", params, test_talk_response_handler, NULL);
cJSON_Delete(params);
}

View File

@ -16,15 +16,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);
void command_identity(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 },
{ "identity", command_identity },
{ NULL, NULL }
};
@ -175,7 +173,7 @@ ks_bool_t test_join_request_handler(blade_rpc_request_t *brpcreq, void *data)
cJSON_AddItemToArray(channels, cJSON_CreateString((const char *)key));
}
blade_handle_rpcauthorize(bh, requester_nodeid, KS_FALSE, "test", "mydomain.com", channels, NULL, NULL);
blade_handle_rpcauthorize(bh, requester_nodeid, KS_FALSE, "test", channels, NULL, NULL);
cJSON_Delete(channels);
@ -193,7 +191,7 @@ ks_bool_t test_join_request_handler(blade_rpc_request_t *brpcreq, void *data)
cJSON_AddStringToObject(params, "joiner-nodeid", requester_nodeid);
blade_handle_rpcbroadcast(bh, "test", "mydomain.com", "channel", "join", params, NULL, NULL);
blade_handle_rpcbroadcast(bh, "test", "channel", "join", params, NULL, NULL);
cJSON_Delete(params);
@ -245,7 +243,7 @@ ks_bool_t test_leave_request_handler(blade_rpc_request_t *brpcreq, void *data)
cJSON_AddItemToArray(channels, cJSON_CreateString((const char *)key));
}
blade_handle_rpcauthorize(bh, requester_nodeid, KS_TRUE, "test", "mydomain.com", channels, NULL, NULL);
blade_handle_rpcauthorize(bh, requester_nodeid, KS_TRUE, "test", channels, NULL, NULL);
cJSON_Delete(channels);
@ -263,7 +261,7 @@ ks_bool_t test_leave_request_handler(blade_rpc_request_t *brpcreq, void *data)
cJSON_AddStringToObject(params, "leaver-nodeid", requester_nodeid);
blade_handle_rpcbroadcast(bh, "test", "mydomain.com", "channel", "leave", params, NULL, NULL);
blade_handle_rpcbroadcast(bh, "test", "channel", "leave", params, NULL, NULL);
cJSON_Delete(params);
@ -318,7 +316,7 @@ ks_bool_t test_talk_request_handler(blade_rpc_request_t *brpcreq, void *data)
cJSON_AddStringToObject(params, "talker-nodeid", requester_nodeid);
blade_handle_rpcbroadcast(bh, "test", "mydomain.com", "channel", "talk", params, NULL, NULL);
blade_handle_rpcbroadcast(bh, "test", "channel", "talk", params, NULL, NULL);
cJSON_Delete(params);
@ -329,7 +327,6 @@ 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;
@ -345,7 +342,6 @@ ks_bool_t test_presence_request_handler(blade_rpc_request_t *brpcreq, void *data
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);
@ -353,7 +349,27 @@ ks_bool_t test_presence_request_handler(blade_rpc_request_t *brpcreq, void *data
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);
ks_log(KS_LOG_DEBUG, "Session (%s) presence (protocol %s, channel %s, event %s for %s) request processing\n", blade_session_id_get(bs), protocol, channel, event, nodeid);
return KS_FALSE;
}
ks_bool_t test_register_response_handler(blade_rpc_response_t *brpcres, void *data)
{
blade_handle_t *bh = NULL;
blade_session_t *bs = NULL;
ks_assert(brpcres);
bh = blade_rpc_response_handle_get(brpcres);
ks_assert(bh);
bs = blade_sessionmgr_session_lookup(blade_handle_sessionmgr_get(bh), blade_rpc_response_sessionid_get(brpcres));
ks_assert(bs);
ks_log(KS_LOG_DEBUG, "Session (%s) register response processing\n", blade_session_id_get(bs));
blade_session_read_unlock(bs);
return KS_FALSE;
}
@ -418,23 +434,27 @@ int main(int argc, char **argv)
if (connected) {
cJSON *channels = NULL;
cJSON *entry = NULL;
// @todo use session state change callback to know when the session is ready and the realm(s) available from blade.connect, this hack temporarily ensures it's ready before trying to publish upstream
// @todo use session state change callback to know when the session is ready after blade.connect, this hack temporarily ensures it's ready before trying to publish upstream
ks_sleep_ms(3000);
blade_rpc_create(&brpc, bh, "test.join", "test", "mydomain.com", test_join_request_handler, (void *)g_test);
blade_rpc_create(&brpc, bh, "test.join", "test", test_join_request_handler, (void *)g_test);
blade_rpcmgr_protocolrpc_add(blade_handle_rpcmgr_get(bh), brpc);
blade_rpc_create(&brpc, bh, "test.leave", "test", "mydomain.com", test_leave_request_handler, (void *)g_test);
blade_rpc_create(&brpc, bh, "test.leave", "test", test_leave_request_handler, (void *)g_test);
blade_rpcmgr_protocolrpc_add(blade_handle_rpcmgr_get(bh), brpc);
blade_rpc_create(&brpc, bh, "test.talk", "test", "mydomain.com", test_talk_request_handler, (void *)g_test);
blade_rpc_create(&brpc, bh, "test.talk", "test", test_talk_request_handler, (void *)g_test);
blade_rpcmgr_protocolrpc_add(blade_handle_rpcmgr_get(bh), brpc);
channels = cJSON_CreateArray();
cJSON_AddItemToArray(channels, cJSON_CreateString("channel"));
entry = cJSON_CreateObject();
cJSON_AddStringToObject(entry, "name", "channel");
cJSON_AddNumberToObject(entry, "flags", BLADE_CHANNEL_FLAGS_NONE);
cJSON_AddItemToArray(channels, entry);
blade_handle_rpcpublish(bh, BLADE_RPCPUBLISH_COMMAND_CONTROLLER_ADD, "test", "mydomain.com", channels, test_publish_response_handler, (void *)g_test);
blade_handle_rpcpublish(bh, BLADE_RPCPUBLISH_COMMAND_CONTROLLER_ADD, "test", channels, test_publish_response_handler, (void *)g_test);
cJSON_Delete(channels);
}
@ -515,51 +535,6 @@ void command_quit(blade_handle_t *bh, char *args)
g_shutdown = KS_TRUE;
}
void command_channeladd(blade_handle_t *bh, char *args)
{
cJSON *channels = NULL;
ks_assert(bh);
ks_assert(args);
if (!args[0]) {
ks_log(KS_LOG_INFO, "Requires channel argument");
return;
}
ks_hash_insert(g_test->channels, (void *)ks_pstrdup(g_test->pool, args), (void *)KS_TRUE);
channels = cJSON_CreateArray();
cJSON_AddItemToArray(channels, cJSON_CreateString(args));
blade_handle_rpcpublish(bh, BLADE_RPCPUBLISH_COMMAND_CHANNEL_ADD, "test", "mydomain.com", channels, test_publish_response_handler, (void *)g_test);
cJSON_Delete(channels);
}
void command_channelremove(blade_handle_t *bh, char *args)
{
cJSON *channels = NULL;
ks_assert(bh);
ks_assert(args);
if (!args[0]) {
ks_log(KS_LOG_INFO, "Requires channel argument");
return;
}
if (ks_hash_remove(g_test->channels, (void *)args)) {
channels = cJSON_CreateArray();
cJSON_AddItemToArray(channels, cJSON_CreateString(args));
blade_handle_rpcpublish(bh, BLADE_RPCPUBLISH_COMMAND_CHANNEL_REMOVE, "test", "mydomain.com", channels, test_publish_response_handler, (void *)g_test);
cJSON_Delete(channels);
}
}
void command_presence(blade_handle_t *bh, char *args)
{
cJSON *channels = NULL;
@ -571,7 +546,15 @@ void command_presence(blade_handle_t *bh, char *args)
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);
blade_handle_rpcsubscribe(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_ADD, "blade.presence", channels, NULL, NULL, test_presence_request_handler, (void *)g_test);
}
void command_identity(blade_handle_t *bh, char *args)
{
ks_assert(bh);
ks_assert(args);
blade_handle_rpcregister(bh, "blade:testcon@freeswitch.com", test_register_response_handler, NULL);
}
/* For Emacs:

View File

@ -109,6 +109,7 @@ KS_DECLARE(void) ks_ssl_destroy_ssl_locks(void)
#ifdef _WINDOWS
SSL_COMP_free_compression_methods();
#endif
ERR_free_strings();
EVP_cleanup();
}