diff --git a/libs/libblade/libblade.vcxproj b/libs/libblade/libblade.vcxproj index 8cb58199b1..33a9493001 100644 --- a/libs/libblade/libblade.vcxproj +++ b/libs/libblade/libblade.vcxproj @@ -193,7 +193,6 @@ - @@ -207,7 +206,6 @@ - @@ -217,7 +215,6 @@ - @@ -232,7 +229,6 @@ - diff --git a/libs/libblade/libblade.vcxproj.filters b/libs/libblade/libblade.vcxproj.filters index f3392d90c6..c8d2468fe3 100644 --- a/libs/libblade/libblade.vcxproj.filters +++ b/libs/libblade/libblade.vcxproj.filters @@ -60,9 +60,6 @@ Source Files - - Source Files - Source Files @@ -75,9 +72,6 @@ Source Files - - Source Files - Source Files @@ -131,9 +125,6 @@ Header Files - - Header Files - Header Files @@ -146,9 +137,6 @@ Header Files - - Header Files - Header Files diff --git a/libs/libblade/src/blade_channel.c b/libs/libblade/src/blade_channel.c index 419d9e89ca..c976563803 100644 --- a/libs/libblade/src/blade_channel.c +++ b/libs/libblade/src/blade_channel.c @@ -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); diff --git a/libs/libblade/src/blade_identity.c b/libs/libblade/src/blade_identity.c index 49254b9071..582f047a3b 100644 --- a/libs/libblade/src/blade_identity.c +++ b/libs/libblade/src/blade_identity.c @@ -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 + // [user@] [:port] [/path] [;param1=value1] [;param2=value2] + + // scheme is mandatory to simplify the parser for now, it must start with mandatory: : + 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: @ + // 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); } diff --git a/libs/libblade/src/blade_mastermgr.c b/libs/libblade/src/blade_mastermgr.c index 61337c98e8..8316216fe8 100644 --- a/libs/libblade/src/blade_mastermgr.c +++ b/libs/libblade/src/blade_mastermgr.c @@ -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; } diff --git a/libs/libblade/src/blade_protocol.c b/libs/libblade/src/blade_protocol.c index 79efbf1895..d27840166c 100644 --- a/libs/libblade/src/blade_protocol.c +++ b/libs/libblade/src/blade_protocol.c @@ -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); diff --git a/libs/libblade/src/blade_realm.c b/libs/libblade/src/blade_realm.c deleted file mode 100644 index 149b57e66e..0000000000 --- a/libs/libblade/src/blade_realm.c +++ /dev/null @@ -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: - */ diff --git a/libs/libblade/src/blade_routemgr.c b/libs/libblade/src/blade_routemgr.c index 277908a599..3b1eeb4cf9 100644 --- a/libs/libblade/src/blade_routemgr.c +++ b/libs/libblade/src/blade_routemgr.c @@ -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 diff --git a/libs/libblade/src/blade_rpc.c b/libs/libblade/src/blade_rpc.c index 51a5251645..9e92fbc016 100644 --- a/libs/libblade/src/blade_rpc.c +++ b/libs/libblade/src/blade_rpc.c @@ -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); diff --git a/libs/libblade/src/blade_rpcmgr.c b/libs/libblade/src/blade_rpcmgr.c index 101128ddba..a8014388be 100644 --- a/libs/libblade/src/blade_rpcmgr.c +++ b/libs/libblade/src/blade_rpcmgr.c @@ -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); diff --git a/libs/libblade/src/blade_session.c b/libs/libblade/src/blade_session.c index 462c4713a4..99626209e2 100644 --- a/libs/libblade/src/blade_session.c +++ b/libs/libblade/src/blade_session.c @@ -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; diff --git a/libs/libblade/src/blade_sessionmgr.c b/libs/libblade/src/blade_sessionmgr.c index 5e13bc69a2..593317c37d 100644 --- a/libs/libblade/src/blade_sessionmgr.c +++ b/libs/libblade/src/blade_sessionmgr.c @@ -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); diff --git a/libs/libblade/src/blade_stack.c b/libs/libblade/src/blade_stack.c index 929c6cb592..a3bfecbf40 100644 --- a/libs/libblade/src/blade_stack.c +++ b/libs/libblade/src/blade_stack.c @@ -40,13 +40,14 @@ struct blade_handle_s { blade_rpcmgr_t *rpcmgr; blade_routemgr_t *routemgr; blade_subscriptionmgr_t *subscriptionmgr; - blade_upstreammgr_t *upstreammgr; blade_mastermgr_t *mastermgr; blade_connectionmgr_t *connectionmgr; blade_sessionmgr_t *sessionmgr; }; +ks_bool_t blade_rpcroute_request_handler(blade_rpc_request_t *brpcreq, void *data); ks_bool_t blade_rpcregister_request_handler(blade_rpc_request_t *brpcreq, void *data); +ks_bool_t blade_rpcregister_response_handler(blade_rpc_response_t *brpcres, void *data); ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *data); ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void *data); ks_bool_t blade_rpclocate_request_handler(blade_rpc_request_t *brpcreq, void *data); @@ -70,7 +71,6 @@ static void blade_handle_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t blade_rpcmgr_destroy(&bh->rpcmgr); blade_routemgr_destroy(&bh->routemgr); blade_subscriptionmgr_destroy(&bh->subscriptionmgr); - blade_upstreammgr_destroy(&bh->upstreammgr); blade_mastermgr_destroy(&bh->mastermgr); blade_connectionmgr_destroy(&bh->connectionmgr); blade_sessionmgr_destroy(&bh->sessionmgr); @@ -111,9 +111,6 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP) blade_subscriptionmgr_create(&bh->subscriptionmgr, bh); ks_assert(bh->subscriptionmgr); - blade_upstreammgr_create(&bh->upstreammgr, bh); - ks_assert(bh->upstreammgr); - blade_mastermgr_create(&bh->mastermgr, bh); ks_assert(bh->mastermgr); @@ -180,33 +177,36 @@ KS_DECLARE(ks_status_t) blade_handle_startup(blade_handle_t *bh, config_setting_ return KS_STATUS_FAIL; } - // register internal transport for secure websockets + // internal transport for secure websockets blade_transport_wss_create(&bt, bh); ks_assert(bt); blade_transportmgr_default_set(bh->transportmgr, bt); blade_transportmgr_transport_add(bh->transportmgr, bt); - // register internal core rpcs for blade.xxx - blade_rpc_create(&brpc, bh, "blade.register", NULL, NULL, blade_rpcregister_request_handler, NULL); + // internal core rpcs for blade.xxx + blade_rpc_create(&brpc, bh, "blade.route", NULL, blade_rpcroute_request_handler, NULL); blade_rpcmgr_corerpc_add(bh->rpcmgr, brpc); - blade_rpc_create(&brpc, bh, "blade.publish", NULL, NULL, blade_rpcpublish_request_handler, NULL); + blade_rpc_create(&brpc, bh, "blade.register", NULL, blade_rpcregister_request_handler, NULL); blade_rpcmgr_corerpc_add(bh->rpcmgr, brpc); - blade_rpc_create(&brpc, bh, "blade.authorize", NULL, NULL, blade_rpcauthorize_request_handler, NULL); + blade_rpc_create(&brpc, bh, "blade.publish", NULL, blade_rpcpublish_request_handler, NULL); blade_rpcmgr_corerpc_add(bh->rpcmgr, brpc); - blade_rpc_create(&brpc, bh, "blade.locate", NULL, NULL, blade_rpclocate_request_handler, NULL); + blade_rpc_create(&brpc, bh, "blade.authorize", NULL, blade_rpcauthorize_request_handler, NULL); blade_rpcmgr_corerpc_add(bh->rpcmgr, brpc); - blade_rpc_create(&brpc, bh, "blade.execute", NULL, NULL, blade_rpcexecute_request_handler, NULL); + blade_rpc_create(&brpc, bh, "blade.locate", NULL, blade_rpclocate_request_handler, NULL); blade_rpcmgr_corerpc_add(bh->rpcmgr, brpc); - blade_rpc_create(&brpc, bh, "blade.subscribe", NULL, NULL, blade_rpcsubscribe_request_handler, NULL); + blade_rpc_create(&brpc, bh, "blade.execute", NULL, blade_rpcexecute_request_handler, NULL); blade_rpcmgr_corerpc_add(bh->rpcmgr, brpc); - blade_rpc_create(&brpc, bh, "blade.broadcast", NULL, NULL, blade_rpcbroadcast_request_handler, NULL); + blade_rpc_create(&brpc, bh, "blade.subscribe", NULL, blade_rpcsubscribe_request_handler, NULL); + blade_rpcmgr_corerpc_add(bh->rpcmgr, brpc); + + blade_rpc_create(&brpc, bh, "blade.broadcast", NULL, blade_rpcbroadcast_request_handler, NULL); blade_rpcmgr_corerpc_add(bh->rpcmgr, brpc); @@ -262,12 +262,6 @@ KS_DECLARE(blade_subscriptionmgr_t *) blade_handle_subscriptionmgr_get(blade_han return bh->subscriptionmgr; } -KS_DECLARE(blade_upstreammgr_t *) blade_handle_upstreammgr_get(blade_handle_t *bh) -{ - ks_assert(bh); - return bh->upstreammgr; -} - KS_DECLARE(blade_mastermgr_t *) blade_handle_mastermgr_get(blade_handle_t *bh) { ks_assert(bh); @@ -290,16 +284,20 @@ 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_status_t ret = KS_STATUS_SUCCESS; + blade_session_t *bs = NULL; blade_transport_t *bt = NULL; blade_transport_callbacks_t *callbacks = NULL; ks_assert(bh); ks_assert(target); - // @todo mini state machine to deal with upstream establishment to avoid attempting multiple upstream connects at the same time - if (blade_upstreammgr_session_established(bh->upstreammgr)) return KS_STATUS_DUPLICATE_OPERATION; + // @todo mini state machine to deal with upstream establishment to avoid attempting multiple upstream connects at the same time? + if ((bs = blade_routemgr_upstream_lookup(bh->routemgr))) { + blade_session_read_unlock(bs); + return KS_STATUS_DUPLICATE_OPERATION; + } - bt = blade_transportmgr_transport_lookup(bh->transportmgr, blade_identity_parameter_get(target, "transport"), KS_TRUE); + bt = blade_transportmgr_transport_lookup(bh->transportmgr, blade_identity_parameter_lookup(target, "transport"), KS_TRUE); ks_assert(bt); callbacks = blade_transport_callbacks_get(bt); @@ -313,23 +311,32 @@ KS_DECLARE(ks_status_t) blade_handle_connect(blade_handle_t *bh, blade_connectio // BLADE PROTOCOL HANDLERS -// @todo revisit all error sending. JSONRPC "error" should only be used for json parsing errors, change the rest to internal errors for each of the corerpcs +// @todo revisit all error sending. JSONRPC "error" should only be used for missing and invalid parameter errors, change the rest to internal errors for each of the corerpcs // @todo all higher level errors should be handled by each of the calls internally so that a normal result response can be sent with an error block inside the result // which is important for implementation of blade.execute where errors can be relayed back to the requester properly +typedef struct blade_rpcregister_data_s blade_rpcregister_data_t; +struct blade_rpcregister_data_s { + blade_rpc_response_callback_t original_callback; + void *original_data; + const char *original_requestid; +}; + typedef struct blade_rpcsubscribe_data_s blade_rpcsubscribe_data_t; struct blade_rpcsubscribe_data_s { blade_rpc_response_callback_t original_callback; void *original_data; + const char *original_requestid; blade_rpc_request_callback_t channel_callback; void *channel_data; - const char *relayed_messageid; }; -ks_status_t blade_handle_rpcsubscribe_raw(blade_handle_t *bh, blade_rpcsubscribe_command_t command, const char *protocol, const char *realm, cJSON *channels, const char *subscriber, ks_bool_t downstream, blade_rpc_response_callback_t callback, blade_rpcsubscribe_data_t *data); +ks_status_t blade_handle_rpcregister_raw(blade_handle_t *bh, const char *identity, const char *nodeid, blade_rpc_response_callback_t callback, blade_rpcregister_data_t *data); +ks_status_t blade_handle_rpcsubscribe_raw(blade_handle_t *bh, blade_rpcsubscribe_command_t command, const char *protocol, cJSON *channels, const char *subscriber, ks_bool_t downstream, blade_rpc_response_callback_t callback, blade_rpcsubscribe_data_t *data); -// blade.register request generator -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) + +// blade.route request generator +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_status_t ret = KS_STATUS_SUCCESS; blade_session_t *bs = NULL; @@ -340,7 +347,8 @@ KS_DECLARE(ks_status_t) blade_handle_rpcregister(blade_handle_t *bh, const char ks_assert(bh); ks_assert(nodeid); - if (!(bs = blade_upstreammgr_session_get(bh->upstreammgr))) { + + if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { ret = KS_STATUS_DISCONNECTED; goto done; } @@ -348,13 +356,13 @@ KS_DECLARE(ks_status_t) blade_handle_rpcregister(blade_handle_t *bh, const char pool = ks_pool_get(bh); ks_assert(pool); - blade_rpc_request_raw_create(pool, &req, &req_params, NULL, "blade.register"); + blade_rpc_request_raw_create(pool, &req, &req_params, NULL, "blade.route"); // fill in the req_params cJSON_AddStringToObject(req_params, "nodeid", nodeid); if (remove) cJSON_AddTrueToObject(req_params, "remove"); - ks_log(KS_LOG_DEBUG, "Session (%s) register request (%s %s) started\n", blade_session_id_get(bs), remove ? "removing" : "adding", nodeid); + ks_log(KS_LOG_DEBUG, "Session (%s) route request (%s %s) started\n", blade_session_id_get(bs), remove ? "removing" : "adding", nodeid); ret = blade_session_send(bs, req, callback, data); @@ -365,8 +373,8 @@ done: return ret; } -// blade.register request handler -ks_bool_t blade_rpcregister_request_handler(blade_rpc_request_t *brpcreq, void *data) +// blade.route request handler +ks_bool_t blade_rpcroute_request_handler(blade_rpc_request_t *brpcreq, void *data) { blade_handle_t *bh = NULL; blade_session_t *bs = NULL; @@ -391,7 +399,7 @@ ks_bool_t blade_rpcregister_request_handler(blade_rpc_request_t *brpcreq, void * req_params = cJSON_GetObjectItem(req, "params"); if (!req_params) { - ks_log(KS_LOG_DEBUG, "Session (%s) register request missing 'params' object\n", blade_session_id_get(bs)); + ks_log(KS_LOG_DEBUG, "Session (%s) route request missing 'params' object\n", blade_session_id_get(bs)); blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params object"); blade_session_send(bs, res, NULL, NULL); goto done; @@ -399,7 +407,7 @@ ks_bool_t blade_rpcregister_request_handler(blade_rpc_request_t *brpcreq, void * req_params_nodeid = cJSON_GetObjectCstr(req_params, "nodeid"); if (!req_params_nodeid) { - ks_log(KS_LOG_DEBUG, "Session (%s) register request missing 'nodeid'\n", blade_session_id_get(bs)); + ks_log(KS_LOG_DEBUG, "Session (%s) route request missing 'nodeid'\n", blade_session_id_get(bs)); blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params nodeid"); blade_session_send(bs, res, NULL, NULL); goto done; @@ -407,7 +415,7 @@ ks_bool_t blade_rpcregister_request_handler(blade_rpc_request_t *brpcreq, void * req_params_remove = cJSON_GetObjectItem(req_params, "remove"); remove = req_params_remove && req_params_remove->type == cJSON_True; - ks_log(KS_LOG_DEBUG, "Session (%s) register request (%s %s) processing\n", blade_session_id_get(bs), remove ? "removing" : "adding", req_params_nodeid); + ks_log(KS_LOG_DEBUG, "Session (%s) route request (%s %s) processing\n", blade_session_id_get(bs), remove ? "removing" : "adding", req_params_nodeid); if (remove) { blade_session_route_remove(bs, req_params_nodeid); @@ -429,22 +437,70 @@ done: } -// blade.publish request generator -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) +static void blade_rpcregister_data_cleanup(void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type) +{ + blade_rpcregister_data_t *brpcrd = (blade_rpcregister_data_t *)ptr; + + ks_assert(brpcrd); + + switch (action) { + case KS_MPCL_ANNOUNCE: + break; + case KS_MPCL_TEARDOWN: + if (brpcrd->original_requestid) ks_pool_free(&brpcrd->original_requestid); + break; + case KS_MPCL_DESTROY: + break; + } +} + +// blade.register request generator +KS_DECLARE(ks_status_t) blade_handle_rpcregister(blade_handle_t *bh, const char *identity, blade_rpc_response_callback_t callback, void *data) +{ + ks_status_t ret = KS_STATUS_SUCCESS; + blade_session_t *bs = NULL; + const char *localid = NULL; + blade_rpcregister_data_t *temp_data = NULL; + + ks_assert(bh); + ks_assert(identity); + + if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { + ret = KS_STATUS_DISCONNECTED; + goto done; + } + + temp_data = (blade_rpcregister_data_t *)ks_pool_alloc(ks_pool_get(bh), sizeof(blade_rpcregister_data_t)); + temp_data->original_callback = callback; + temp_data->original_data = data; + ks_pool_set_cleanup(temp_data, NULL, blade_rpcregister_data_cleanup); + + blade_routemgr_local_copy(bh->routemgr, &localid); + + ret = blade_handle_rpcregister_raw(bh, identity, localid, blade_rpcregister_response_handler, temp_data); + + ks_pool_free(&localid); + + ks_log(KS_LOG_DEBUG, "Session (%s) register request (%s) started\n", blade_session_id_get(bs), identity); + +done: + if (bs) blade_session_read_unlock(bs); + + return ret; +} + +ks_status_t blade_handle_rpcregister_raw(blade_handle_t *bh, const char *identity, const char *nodeid, blade_rpc_response_callback_t callback, blade_rpcregister_data_t *data) { ks_status_t ret = KS_STATUS_SUCCESS; blade_session_t *bs = NULL; ks_pool_t *pool = NULL; cJSON *req = NULL; cJSON *req_params = NULL; - const char *id = NULL; ks_assert(bh); - ks_assert(protocol); - ks_assert(realm); + ks_assert(identity); - // @todo consideration for the Master trying to publish a protocol, with no upstream - if (!(bs = blade_upstreammgr_session_get(bh->upstreammgr))) { + if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { ret = KS_STATUS_DISCONNECTED; goto done; } @@ -452,6 +508,209 @@ KS_DECLARE(ks_status_t) blade_handle_rpcpublish(blade_handle_t *bh, blade_rpcpub pool = ks_pool_get(bh); ks_assert(pool); + blade_rpc_request_raw_create(pool, &req, &req_params, NULL, "blade.register"); + + // fill in the req_params + cJSON_AddStringToObject(req_params, "identity", identity); + cJSON_AddStringToObject(req_params, "nodeid", nodeid); + + ret = blade_session_send(bs, req, callback, data); + +done: + if (req) cJSON_Delete(req); + if (bs) blade_session_read_unlock(bs); + + return ret; +} + +// blade.register request handler +ks_bool_t blade_rpcregister_request_handler(blade_rpc_request_t *brpcreq, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + ks_pool_t *pool = NULL; + cJSON *req = NULL; + cJSON *req_params = NULL; + const char *req_params_identity = NULL; + const char *req_params_nodeid = NULL; + cJSON *res = NULL; + cJSON *res_result = NULL; + blade_identity_t *identity = NULL; + + ks_assert(brpcreq); + + bh = blade_rpc_request_handle_get(brpcreq); + ks_assert(bh); + + pool = ks_pool_get(bh); + ks_assert(pool); + + bs = blade_sessionmgr_session_lookup(blade_handle_sessionmgr_get(bh), blade_rpc_request_sessionid_get(brpcreq)); + ks_assert(bs); + + req = blade_rpc_request_message_get(brpcreq); + ks_assert(req); + + req_params = cJSON_GetObjectItem(req, "params"); + if (!req_params) { + ks_log(KS_LOG_DEBUG, "Session (%s) register request missing 'params' object\n", blade_session_id_get(bs)); + blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params object"); + blade_session_send(bs, res, NULL, NULL); + goto done; + } + + req_params_identity = cJSON_GetObjectCstr(req_params, "identity"); + if (!req_params_identity) { + ks_log(KS_LOG_DEBUG, "Session (%s) register request missing 'identity'\n", blade_session_id_get(bs)); + blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params identity"); + blade_session_send(bs, res, NULL, NULL); + goto done; + } + + blade_identity_create(&identity, pool); + if (blade_identity_parse(identity, req_params_identity) != KS_STATUS_SUCCESS) { + ks_log(KS_LOG_DEBUG, "Session (%s) register request invalid 'identity'\n", blade_session_id_get(bs)); + blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Invalid params identity"); + blade_session_send(bs, res, NULL, NULL); + goto done; + } + + req_params_nodeid = cJSON_GetObjectCstr(req_params, "nodeid"); + if (!req_params_nodeid) { + ks_log(KS_LOG_DEBUG, "Session (%s) register request missing 'nodeid'\n", blade_session_id_get(bs)); + blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params nodeid"); + blade_session_send(bs, res, NULL, NULL); + goto done; + } + + ks_log(KS_LOG_DEBUG, "Session (%s) register request (%s for %s) processing\n", blade_session_id_get(bs), req_params_identity, req_params_nodeid); + + if (blade_routemgr_master_local(blade_handle_routemgr_get(bh))) { + // @todo add identity mapping to nodeid, normally handled in the response handler + blade_routemgr_identity_add(bh->routemgr, identity, req_params_nodeid); + + // @todo this is the masters chance to do any additional validation on the identity registration, just trust it for now + blade_rpc_response_raw_create(&res, &res_result, blade_rpc_request_messageid_get(brpcreq)); + + cJSON_AddStringToObject(res_result, "identity", req_params_identity); + cJSON_AddStringToObject(res_result, "nodeid", req_params_nodeid); + + // request was just received on a session that is already read locked, so we can assume the response goes back on the same session without further lookup + blade_session_send(bs, res, NULL, NULL); + } else { + blade_rpcregister_data_t *temp_data = (blade_rpcregister_data_t *)ks_pool_alloc(pool, sizeof(blade_rpcregister_data_t)); + temp_data->original_requestid = ks_pstrdup(pool, blade_rpc_request_messageid_get(brpcreq)); + ks_pool_set_cleanup(temp_data, NULL, blade_rpcregister_data_cleanup); + + blade_handle_rpcregister_raw(bh, req_params_identity, req_params_nodeid, blade_rpcregister_response_handler, temp_data); + } + +done: + if (identity) blade_identity_destroy(&identity); + if (res) cJSON_Delete(res); + if (bs) blade_session_read_unlock(bs); + + return KS_FALSE; +} + +// blade.register response handler +ks_bool_t blade_rpcregister_response_handler(blade_rpc_response_t *brpcres, void *data) +{ + ks_bool_t ret = KS_FALSE; + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + blade_rpcregister_data_t *temp_data = NULL; + cJSON *res = NULL; + cJSON *res_result = NULL; + const char *res_result_identity = NULL; + const char *res_result_nodeid = NULL; + blade_identity_t *identity = NULL; + + ks_assert(brpcres); + + bh = blade_rpc_response_handle_get(brpcres); + ks_assert(bh); + + bs = blade_sessionmgr_session_lookup(bh->sessionmgr, blade_rpc_response_sessionid_get(brpcres)); + ks_assert(bs); + + temp_data = (blade_rpcregister_data_t *)data; + + res = blade_rpc_response_message_get(brpcres); + ks_assert(res); + + res_result = cJSON_GetObjectItem(res, "result"); + if (!res_result) { + ks_log(KS_LOG_DEBUG, "Session (%s) register response missing 'result' object\n", blade_session_id_get(bs)); + goto done; + } + + res_result_identity = cJSON_GetObjectCstr(res_result, "identity"); + if (!res_result_identity) { + ks_log(KS_LOG_DEBUG, "Session (%s) register response missing 'identity'\n", blade_session_id_get(bs)); + goto done; + } + + blade_identity_create(&identity, ks_pool_get(bh)); + + if (blade_identity_parse(identity, res_result_identity) != KS_STATUS_SUCCESS) { + ks_log(KS_LOG_DEBUG, "Session (%s) register response invalid 'identity'\n", blade_session_id_get(bs)); + goto done; + } + + res_result_nodeid = cJSON_GetObjectCstr(res_result, "nodeid"); + if (!res_result_nodeid) { + ks_log(KS_LOG_DEBUG, "Session (%s) register response missing 'nodeid'\n", blade_session_id_get(bs)); + goto done; + } + + blade_routemgr_identity_add(bh->routemgr, identity, res_result_nodeid); + + // @note this should only happen on the last response, received by the registering node + if (temp_data && temp_data->original_callback) ret = temp_data->original_callback(brpcres, temp_data->original_data); + + if (temp_data && temp_data->original_requestid) { + blade_session_t *relay = NULL; + if (!(relay = blade_routemgr_route_lookup(bh->routemgr, res_result_nodeid))) { + goto done; + } + + blade_rpc_response_raw_create(&res, &res_result, temp_data->original_requestid); + + cJSON_AddStringToObject(res_result, "identity", res_result_identity); + cJSON_AddStringToObject(res_result, "nodeid", res_result_nodeid); + + blade_session_send(relay, res, NULL, NULL); + + cJSON_Delete(res); + + blade_session_read_unlock(relay); + } + +done: + if (temp_data) ks_pool_free(&temp_data); + if (identity) blade_identity_destroy(&identity); + blade_session_read_unlock(bs); + return ret; +} + +// blade.publish request generator +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_status_t ret = KS_STATUS_SUCCESS; + blade_session_t *bs = NULL; + cJSON *req = NULL; + cJSON *req_params = NULL; + + ks_assert(bh); + ks_assert(protocol); + + // @todo consideration for the Master trying to publish a protocol, with no upstream + if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { + ret = KS_STATUS_DISCONNECTED; + goto done; + } + // @todo validate command and parameters switch (command) { case BLADE_RPCPUBLISH_COMMAND_CONTROLLER_ADD: @@ -472,23 +731,17 @@ KS_DECLARE(ks_status_t) blade_handle_rpcpublish(blade_handle_t *bh, blade_rpcpub } // create the response - blade_rpc_request_raw_create(pool, &req, &req_params, NULL, "blade.publish"); + blade_rpc_request_raw_create(ks_pool_get(bh), &req, &req_params, NULL, "blade.publish"); cJSON_AddNumberToObject(req_params, "command", command); cJSON_AddStringToObject(req_params, "protocol", protocol); - cJSON_AddStringToObject(req_params, "realm", realm); - blade_upstreammgr_localid_copy(bh->upstreammgr, pool, &id); - ks_assert(id); + blade_routemgr_local_pack(bh->routemgr, req_params, "requester-nodeid"); - cJSON_AddStringToObject(req_params, "requester-nodeid", id); - ks_pool_free(&id); - - blade_upstreammgr_masterid_copy(bh->upstreammgr, pool, &id); - ks_assert(id); - - cJSON_AddStringToObject(req_params, "responder-nodeid", id); - ks_pool_free(&id); + if (!blade_routemgr_master_pack(bh->routemgr, req_params, "responder-nodeid")) { + ret = KS_STATUS_DISCONNECTED; + goto done; + } if (channels) cJSON_AddItemToObject(req_params, "channels", cJSON_Duplicate(channels, 1)); @@ -513,12 +766,14 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d cJSON *req = NULL; cJSON *req_params = NULL; cJSON *req_params_channels = NULL; + cJSON *req_params_channels_element = NULL; + cJSON *req_params_channels_element_flags = NULL; cJSON *req_params_command = NULL; blade_rpcpublish_command_t command = BLADE_RPCPUBLISH_COMMAND_NONE; const char *req_params_protocol = NULL; - const char *req_params_realm = NULL; const char *req_params_requester_nodeid = NULL; const char *req_params_responder_nodeid = NULL; + const char *req_params_channels_element_name = NULL; cJSON *res = NULL; cJSON *res_result = NULL; @@ -565,16 +820,6 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d goto done; } - req_params_realm = cJSON_GetObjectCstr(req_params, "realm"); - if (!req_params_realm) { - ks_log(KS_LOG_DEBUG, "Session (%s) publish request missing 'realm'\n", blade_session_id_get(bs)); - blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params realm"); - blade_session_send(bs, res, NULL, NULL); - goto done; - } - - // @todo confirm the realm is permitted for the session, this gets complicated with subdomains, skipping for now - req_params_requester_nodeid = cJSON_GetObjectCstr(req_params, "requester-nodeid"); if (!req_params_requester_nodeid) { ks_log(KS_LOG_DEBUG, "Session (%s) publish request missing 'requester-nodeid'\n", blade_session_id_get(bs)); @@ -591,7 +836,7 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d goto done; } - if (!blade_upstreammgr_masterid_compare(bh->upstreammgr, req_params_responder_nodeid)) { + if (!blade_routemgr_master_check(bh->routemgr, req_params_responder_nodeid)) { ks_log(KS_LOG_DEBUG, "Session (%s) publish request invalid 'responder-nodeid' (%s)\n", blade_session_id_get(bs), req_params_responder_nodeid); blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Invalid params responder-nodeid"); blade_session_send(bs, res, NULL, NULL); @@ -603,8 +848,6 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d req_params_channels = cJSON_GetObjectItem(req_params, "channels"); if (req_params_channels) { - cJSON *element = NULL; - if (req_params_channels->type != cJSON_Array) { ks_log(KS_LOG_DEBUG, "Session (%s) publish request invalid 'channels' type, expected array\n", blade_session_id_get(bs)); blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Invalid params channels"); @@ -612,13 +855,29 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d goto done; } - cJSON_ArrayForEach(element, req_params_channels) { - if (element->type != cJSON_String) { - ks_log(KS_LOG_DEBUG, "Session (%s) publish request invalid 'channels' element type, expected string\n", blade_session_id_get(bs)); + cJSON_ArrayForEach(req_params_channels_element, req_params_channels) { + if (req_params_channels_element->type != cJSON_Object) { + ks_log(KS_LOG_DEBUG, "Session (%s) publish request invalid 'channels' element type, expected object\n", blade_session_id_get(bs)); blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Invalid params channels"); blade_session_send(bs, res, NULL, NULL); goto done; } + + req_params_channels_element_name = cJSON_GetObjectCstr(req_params_channels_element, "name"); + if (!req_params_channels_element_name) { + ks_log(KS_LOG_DEBUG, "Session (%s) publish request missing 'channels' element name\n", blade_session_id_get(bs)); + blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params channels element name"); + blade_session_send(bs, res, NULL, NULL); + goto done; + } + + req_params_channels_element_flags = cJSON_GetObjectItem(req_params_channels_element, "flags"); + if (req_params_channels_element_flags && req_params_channels_element_flags->type != cJSON_Number) { + ks_log(KS_LOG_DEBUG, "Session (%s) publish request invalid 'channels' element flags type, expected number\n", blade_session_id_get(bs)); + blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Invalid params channels element flags type"); + blade_session_send(bs, res, NULL, NULL); + goto done; + } } } @@ -627,30 +886,33 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d // @todo switch on publish command, make the following code for add_protocol switch (command) { case BLADE_RPCPUBLISH_COMMAND_CONTROLLER_ADD: - blade_mastermgr_realm_protocol_controller_add(bh->mastermgr, req_params_realm, req_params_protocol, req_params_requester_nodeid); + blade_mastermgr_protocol_controller_add(bh->mastermgr, req_params_protocol, req_params_requester_nodeid); if (req_params_channels) { - cJSON *element = NULL; - cJSON_ArrayForEach(element, req_params_channels) { - blade_mastermgr_realm_protocol_channel_add(bh->mastermgr, req_params_realm, req_params_protocol, element->valuestring); + cJSON_ArrayForEach(req_params_channels_element, req_params_channels) { + req_params_channels_element_name = cJSON_GetObjectCstr(req_params_channels_element, "name"); + req_params_channels_element_flags = cJSON_GetObjectItem(req_params_channels_element, "flags"); + + blade_mastermgr_protocol_channel_add(bh->mastermgr, req_params_protocol, req_params_channels_element_name, (blade_channel_flags_t)req_params_channels_element_flags->valueint); } } break; case BLADE_RPCPUBLISH_COMMAND_CONTROLLER_REMOVE: - blade_mastermgr_realm_protocol_controller_remove(bh->mastermgr, req_params_realm, req_params_protocol, req_params_requester_nodeid); + blade_mastermgr_protocol_controller_remove(bh->mastermgr, req_params_protocol, req_params_requester_nodeid); break; case BLADE_RPCPUBLISH_COMMAND_CHANNEL_ADD: if (req_params_channels) { - cJSON *element = NULL; - cJSON_ArrayForEach(element, req_params_channels) { - blade_mastermgr_realm_protocol_channel_add(bh->mastermgr, req_params_realm, req_params_protocol, element->valuestring); + cJSON_ArrayForEach(req_params_channels_element, req_params_channels) { + req_params_channels_element_name = cJSON_GetObjectCstr(req_params_channels_element, "name"); + req_params_channels_element_flags = cJSON_GetObjectItem(req_params_channels_element, "flags"); + blade_mastermgr_protocol_channel_add(bh->mastermgr, req_params_protocol, req_params_channels_element_name, (blade_channel_flags_t)req_params_channels_element_flags->valueint); } } break; case BLADE_RPCPUBLISH_COMMAND_CHANNEL_REMOVE: if (req_params_channels) { - cJSON *element = NULL; - cJSON_ArrayForEach(element, req_params_channels) { - blade_mastermgr_realm_protocol_channel_remove(bh->mastermgr, req_params_realm, req_params_protocol, element->valuestring); + cJSON_ArrayForEach(req_params_channels_element, req_params_channels) { + req_params_channels_element_name = cJSON_GetObjectCstr(req_params_channels_element, "name"); + blade_mastermgr_protocol_channel_remove(bh->mastermgr, req_params_protocol, req_params_channels_element_name); } } break; @@ -663,7 +925,6 @@ ks_bool_t blade_rpcpublish_request_handler(blade_rpc_request_t *brpcreq, void *d blade_rpc_response_raw_create(&res, &res_result, blade_rpc_request_messageid_get(brpcreq)); cJSON_AddStringToObject(res_result, "protocol", req_params_protocol); - cJSON_AddStringToObject(res_result, "realm", req_params_realm); cJSON_AddStringToObject(res_result, "requester-nodeid", req_params_requester_nodeid); cJSON_AddStringToObject(res_result, "responder-nodeid", req_params_responder_nodeid); // @todo include a list of channels that failed to be added or removed if applicable? @@ -681,49 +942,37 @@ done: // blade.authorize request generator -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_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_status_t ret = KS_STATUS_SUCCESS; blade_session_t *bs = NULL; - ks_pool_t *pool = NULL; cJSON *req = NULL; cJSON *req_params = NULL; - const char *id = NULL; ks_assert(bh); ks_assert(nodeid); ks_assert(protocol); - ks_assert(realm); ks_assert(channels); // @todo consideration for the Master trying to publish a protocol, with no upstream - if (!(bs = blade_upstreammgr_session_get(bh->upstreammgr))) { + if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { ret = KS_STATUS_DISCONNECTED; goto done; } - pool = ks_pool_get(bh); - ks_assert(pool); - - blade_rpc_request_raw_create(pool, &req, &req_params, NULL, "blade.authorize"); + blade_rpc_request_raw_create(ks_pool_get(bh), &req, &req_params, NULL, "blade.authorize"); // fill in the req_params cJSON_AddStringToObject(req_params, "protocol", protocol); - cJSON_AddStringToObject(req_params, "realm", realm); if (remove) cJSON_AddTrueToObject(req_params, "remove"); cJSON_AddStringToObject(req_params, "authorized-nodeid", nodeid); - blade_upstreammgr_localid_copy(bh->upstreammgr, pool, &id); - ks_assert(id); + blade_routemgr_local_pack(bh->routemgr, req_params, "requester-nodeid"); - cJSON_AddStringToObject(req_params, "requester-nodeid", id); - ks_pool_free(&id); - - blade_upstreammgr_masterid_copy(bh->upstreammgr, pool, &id); - ks_assert(id); - - cJSON_AddStringToObject(req_params, "responder-nodeid", id); - ks_pool_free(&id); + if (!blade_routemgr_master_pack(bh->routemgr, req_params, "responder-nodeid")) { + ret = KS_STATUS_DISCONNECTED; + goto done; + } cJSON_AddItemToObject(req_params, "channels", cJSON_Duplicate(channels, 1)); @@ -752,7 +1001,6 @@ ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void cJSON *channel = NULL; ks_bool_t remove = KS_FALSE; const char *req_params_protocol = NULL; - const char *req_params_realm = NULL; const char *req_params_authorized_nodeid = NULL; const char *req_params_requester_nodeid = NULL; const char *req_params_responder_nodeid = NULL; @@ -789,14 +1037,6 @@ ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void goto done; } - req_params_realm = cJSON_GetObjectCstr(req_params, "realm"); - if (!req_params_realm) { - ks_log(KS_LOG_DEBUG, "Session (%s) authorize request missing 'realm'\n", blade_session_id_get(bs)); - blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params realm"); - blade_session_send(bs, res, NULL, NULL); - goto done; - } - req_params_remove = cJSON_GetObjectItem(req_params, "remove"); if (req_params_remove && req_params_remove->type == cJSON_True) remove = KS_TRUE; @@ -808,8 +1048,6 @@ ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void goto done; } - // @todo confirm the realm is permitted for the session, this gets complicated with subdomains, skipping for now - req_params_requester_nodeid = cJSON_GetObjectCstr(req_params, "requester-nodeid"); if (!req_params_requester_nodeid) { ks_log(KS_LOG_DEBUG, "Session (%s) authorize request missing 'requester-nodeid'\n", blade_session_id_get(bs)); @@ -850,7 +1088,7 @@ ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void } } - if (!blade_upstreammgr_masterid_compare(bh->upstreammgr, req_params_responder_nodeid)) { + if (!blade_routemgr_master_check(bh->routemgr, req_params_responder_nodeid)) { ks_log(KS_LOG_DEBUG, "Session (%s) authorize request invalid 'responder-nodeid' (%s)\n", blade_session_id_get(bs), req_params_responder_nodeid); blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Invalid params responder-nodeid"); blade_session_send(bs, res, NULL, NULL); @@ -863,7 +1101,7 @@ ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void blade_rpc_response_raw_create(&res, &res_result, blade_rpc_request_messageid_get(brpcreq)); cJSON_ArrayForEach(channel, req_params_channels) { - if (blade_mastermgr_realm_protocol_channel_authorize(bh->mastermgr, remove, req_params_realm, req_params_protocol, channel->valuestring, req_params_requester_nodeid, req_params_authorized_nodeid) == KS_STATUS_SUCCESS) { + if (blade_mastermgr_protocol_channel_authorize(bh->mastermgr, remove, req_params_protocol, channel->valuestring, req_params_requester_nodeid, req_params_authorized_nodeid) == KS_STATUS_SUCCESS) { if (remove) { if (!res_result_unauthorized_channels) res_result_unauthorized_channels = cJSON_CreateArray(); cJSON_AddItemToArray(res_result_unauthorized_channels, cJSON_CreateString(channel->valuestring)); @@ -878,7 +1116,6 @@ ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void } cJSON_AddStringToObject(res_result, "protocol", req_params_protocol); - cJSON_AddStringToObject(res_result, "realm", req_params_realm); cJSON_AddStringToObject(res_result, "authorized-nodeid", req_params_authorized_nodeid); cJSON_AddStringToObject(res_result, "requester-nodeid", req_params_requester_nodeid); cJSON_AddStringToObject(res_result, "responder-nodeid", req_params_responder_nodeid); @@ -890,7 +1127,7 @@ ks_bool_t blade_rpcauthorize_request_handler(blade_rpc_request_t *brpcreq, void blade_session_send(bs, res, NULL, NULL); if (res_result_unauthorized_channels) { - blade_handle_rpcsubscribe_raw(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_REMOVE, req_params_protocol, req_params_realm, res_result_unauthorized_channels, req_params_authorized_nodeid, KS_TRUE, NULL, NULL); + blade_handle_rpcsubscribe_raw(bh, BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_REMOVE, req_params_protocol, res_result_unauthorized_channels, req_params_authorized_nodeid, KS_TRUE, NULL, NULL); } done: @@ -906,44 +1143,32 @@ done: // @todo discuss system to support caching locate results, and internally subscribing to receive event updates related to protocols which have been located // to ensure local caches remain synced when protocol controllers change, but this requires additional filters for event propagating to avoid broadcasting // every protocol update to everyone which may actually be a better way than an explicit locate request -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_rpclocate(blade_handle_t *bh, const char *protocol, blade_rpc_response_callback_t callback, void *data) { ks_status_t ret = KS_STATUS_SUCCESS; blade_session_t *bs = NULL; - ks_pool_t *pool = NULL; cJSON *req = NULL; cJSON *req_params = NULL; - const char *id = NULL; ks_assert(bh); ks_assert(protocol); - ks_assert(realm); - if (!(bs = blade_upstreammgr_session_get(bh->upstreammgr))) { + if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { ret = KS_STATUS_DISCONNECTED; goto done; } - pool = ks_pool_get(bh); - ks_assert(pool); - - blade_rpc_request_raw_create(pool, &req, &req_params, NULL, "blade.locate"); + blade_rpc_request_raw_create(ks_pool_get(bh), &req, &req_params, NULL, "blade.locate"); // fill in the req_params cJSON_AddStringToObject(req_params, "protocol", protocol); - cJSON_AddStringToObject(req_params, "realm", realm); - blade_upstreammgr_localid_copy(bh->upstreammgr, pool, &id); - ks_assert(id); + blade_routemgr_local_pack(bh->routemgr, req_params, "requester-nodeid"); - cJSON_AddStringToObject(req_params, "requester-nodeid", id); - ks_pool_free(&id); - - blade_upstreammgr_masterid_copy(bh->upstreammgr, pool, &id); - ks_assert(id); - - cJSON_AddStringToObject(req_params, "responder-nodeid", id); - ks_pool_free(&id); + if (!blade_routemgr_master_pack(bh->routemgr, req_params, "responder-nodeid")) { + ret = KS_STATUS_DISCONNECTED; + goto done; + } ks_log(KS_LOG_DEBUG, "Session (%s) locate request started\n", blade_session_id_get(bs)); @@ -964,7 +1189,6 @@ ks_bool_t blade_rpclocate_request_handler(blade_rpc_request_t *brpcreq, void *da cJSON *req = NULL; cJSON *req_params = NULL; const char *req_params_protocol = NULL; - const char *req_params_realm = NULL; const char *req_params_requester_nodeid = NULL; const char *req_params_responder_nodeid = NULL; cJSON *res = NULL; @@ -999,16 +1223,6 @@ ks_bool_t blade_rpclocate_request_handler(blade_rpc_request_t *brpcreq, void *da goto done; } - req_params_realm = cJSON_GetObjectCstr(req_params, "realm"); - if (!req_params_realm) { - ks_log(KS_LOG_DEBUG, "Session (%s) locate request missing 'realm'\n", blade_session_id_get(bs)); - blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params realm"); - blade_session_send(bs, res, NULL, NULL); - goto done; - } - - // @todo confirm the realm is permitted for the session, this gets complicated with subdomains, skipping for now - req_params_requester_nodeid = cJSON_GetObjectCstr(req_params, "requester-nodeid"); if (!req_params_requester_nodeid) { ks_log(KS_LOG_DEBUG, "Session (%s) locate request missing 'requester-nodeid'\n", blade_session_id_get(bs)); @@ -1025,7 +1239,7 @@ ks_bool_t blade_rpclocate_request_handler(blade_rpc_request_t *brpcreq, void *da goto done; } - if (!blade_upstreammgr_masterid_compare(bh->upstreammgr, req_params_responder_nodeid)) { + if (!blade_routemgr_master_check(bh->routemgr, req_params_responder_nodeid)) { ks_log(KS_LOG_DEBUG, "Session (%s) locate request invalid 'responder-nodeid' (%s)\n", blade_session_id_get(bs), req_params_responder_nodeid); blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Invalid params responder-nodeid"); blade_session_send(bs, res, NULL, NULL); @@ -1034,7 +1248,7 @@ ks_bool_t blade_rpclocate_request_handler(blade_rpc_request_t *brpcreq, void *da ks_log(KS_LOG_DEBUG, "Session (%s) locate request (%s to %s) processing\n", blade_session_id_get(bs), req_params_requester_nodeid, req_params_responder_nodeid); - bp = blade_mastermgr_realm_protocol_lookup(bh->mastermgr, req_params_realm, req_params_protocol, KS_FALSE); + bp = blade_mastermgr_protocol_lookup(bh->mastermgr, req_params_protocol, KS_FALSE); if (bp) { res_result_controllers = blade_protocol_controller_pack(bp); blade_protocol_read_unlock(bp); @@ -1045,7 +1259,6 @@ ks_bool_t blade_rpclocate_request_handler(blade_rpc_request_t *brpcreq, void *da blade_rpc_response_raw_create(&res, &res_result, blade_rpc_request_messageid_get(brpcreq)); cJSON_AddStringToObject(res_result, "protocol", req_params_protocol); - cJSON_AddStringToObject(res_result, "realm", req_params_realm); cJSON_AddStringToObject(res_result, "requester-nodeid", req_params_requester_nodeid); cJSON_AddStringToObject(res_result, "responder-nodeid", req_params_responder_nodeid); if (res_result_controllers) cJSON_AddItemToObject(res_result, "controllers", res_result_controllers); @@ -1063,42 +1276,31 @@ done: // blade.execute request generator -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_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_status_t ret = KS_STATUS_SUCCESS; blade_session_t *bs = NULL; - ks_pool_t *pool = NULL; cJSON *req = NULL; cJSON *req_params = NULL; - const char *localid = NULL; ks_assert(bh); ks_assert(nodeid); ks_assert(method); ks_assert(protocol); - ks_assert(realm); if (!(bs = blade_routemgr_route_lookup(blade_handle_routemgr_get(bh), nodeid))) { - if (!(bs = blade_upstreammgr_session_get(bh->upstreammgr))) { + if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { ret = KS_STATUS_DISCONNECTED; goto done; } } - pool = ks_pool_get(bh); - ks_assert(pool); - - blade_rpc_request_raw_create(pool, &req, &req_params, NULL, "blade.execute"); + blade_rpc_request_raw_create(ks_pool_get(bh), &req, &req_params, NULL, "blade.execute"); cJSON_AddStringToObject(req_params, "method", method); cJSON_AddStringToObject(req_params, "protocol", protocol); - cJSON_AddStringToObject(req_params, "realm", realm); - blade_upstreammgr_localid_copy(bh->upstreammgr, pool, &localid); - ks_assert(localid); - - cJSON_AddStringToObject(req_params, "requester-nodeid", localid); - ks_pool_free(&localid); + blade_routemgr_local_pack(bh->routemgr, req_params, "requester-nodeid"); cJSON_AddStringToObject(req_params, "responder-nodeid", nodeid); @@ -1125,7 +1327,6 @@ ks_bool_t blade_rpcexecute_request_handler(blade_rpc_request_t *brpcreq, void *d cJSON *req_params = NULL; const char *req_params_method = NULL; const char *req_params_protocol = NULL; - const char *req_params_realm = NULL; const char *req_params_requester_nodeid = NULL; const char *req_params_responder_nodeid = NULL; blade_rpc_t *brpc = NULL; @@ -1167,16 +1368,6 @@ ks_bool_t blade_rpcexecute_request_handler(blade_rpc_request_t *brpcreq, void *d goto done; } - req_params_realm = cJSON_GetObjectCstr(req_params, "realm"); - if (!req_params_realm) { - ks_log(KS_LOG_DEBUG, "Session (%s) execute request missing 'realm'\n", blade_session_id_get(bs)); - blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params realm"); - blade_session_send(bs, res, NULL, NULL); - goto done; - } - - // @todo confirm the realm is permitted for the session, this gets complicated with subdomains, skipping for now - req_params_requester_nodeid = cJSON_GetObjectCstr(req_params, "requester-nodeid"); if (!req_params_requester_nodeid) { ks_log(KS_LOG_DEBUG, "Session (%s) execute request missing 'requester-nodeid'\n", blade_session_id_get(bs)); @@ -1197,7 +1388,7 @@ ks_bool_t blade_rpcexecute_request_handler(blade_rpc_request_t *brpcreq, void *d // @todo pull out nested params block if it exists and check against schema later, so blade_rpc_t should be able to carry a schema with it, even though blade.xxx may not associate one - brpc = blade_rpcmgr_protocolrpc_lookup(blade_handle_rpcmgr_get(bh), req_params_method, req_params_protocol, req_params_realm); + brpc = blade_rpcmgr_protocolrpc_lookup(blade_handle_rpcmgr_get(bh), req_params_method, req_params_protocol); if (!brpc) { ks_log(KS_LOG_DEBUG, "Session (%s) execute request unknown method\n", blade_session_id_get(bs)); blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Unknown params method"); @@ -1295,7 +1486,6 @@ KS_DECLARE(void) blade_rpcexecute_response_send(blade_rpc_request_t *brpcreq, cJ cJSON *req_params = NULL; //const char *req_params_method = NULL; const char *req_params_protocol = NULL; - const char *req_params_realm = NULL; const char *req_params_requester_nodeid = NULL; const char *req_params_responder_nodeid = NULL; cJSON *res = NULL; @@ -1318,9 +1508,6 @@ KS_DECLARE(void) blade_rpcexecute_response_send(blade_rpc_request_t *brpcreq, cJ req_params_protocol = cJSON_GetObjectCstr(req_params, "protocol"); ks_assert(req_params_protocol); - req_params_realm = cJSON_GetObjectCstr(req_params, "realm"); - ks_assert(req_params_realm); - req_params_requester_nodeid = cJSON_GetObjectCstr(req_params, "requester-nodeid"); ks_assert(req_params_requester_nodeid); @@ -1331,7 +1518,6 @@ KS_DECLARE(void) blade_rpcexecute_response_send(blade_rpc_request_t *brpcreq, cJ blade_rpc_response_raw_create(&res, &res_result, blade_rpc_request_messageid_get(brpcreq)); cJSON_AddStringToObject(res_result, "protocol", req_params_protocol); - cJSON_AddStringToObject(res_result, "realm", req_params_realm); cJSON_AddStringToObject(res_result, "requester-nodeid", req_params_requester_nodeid); cJSON_AddStringToObject(res_result, "responder-nodeid", req_params_responder_nodeid); if (result) cJSON_AddItemToObject(res_result, "result", cJSON_Duplicate(result, 1)); @@ -1355,7 +1541,7 @@ static void blade_rpcsubscribe_data_cleanup(void *ptr, void *arg, ks_pool_cleanu case KS_MPCL_ANNOUNCE: break; case KS_MPCL_TEARDOWN: - if (brpcsd->relayed_messageid) ks_pool_free(&brpcsd->relayed_messageid); + if (brpcsd->original_requestid) ks_pool_free(&brpcsd->original_requestid); break; case KS_MPCL_DESTROY: break; @@ -1366,7 +1552,6 @@ static void blade_rpcsubscribe_data_cleanup(void *ptr, void *arg, ks_pool_cleanu 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, @@ -1374,38 +1559,33 @@ KS_DECLARE(ks_status_t) blade_handle_rpcsubscribe(blade_handle_t *bh, void *channel_data) { ks_status_t ret = KS_STATUS_SUCCESS; - ks_pool_t *pool = NULL; blade_session_t *bs = NULL; const char *localid = NULL; blade_rpcsubscribe_data_t *temp_data = NULL; ks_assert(bh); ks_assert(protocol); - ks_assert(realm); ks_assert(channels); - pool = ks_pool_get(bh); - ks_assert(pool); - // @note this is always produced by a subscriber, and sent upstream, master will only use the internal raw call - if (!(bs = blade_upstreammgr_session_get(bh->upstreammgr))) { + if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { ret = KS_STATUS_DISCONNECTED; goto done; } - blade_upstreammgr_localid_copy(bh->upstreammgr, ks_pool_get(bh), &localid); + blade_routemgr_local_copy(bh->routemgr, &localid); ks_assert(localid); // @note since this is allocated in the handle's pool, if the handle is shutdown during a pending request, then the data // memory will be cleaned up with the handle, otherwise should be cleaned up in the response callback - temp_data = (blade_rpcsubscribe_data_t *)ks_pool_alloc(pool, sizeof(blade_rpcsubscribe_data_t)); + temp_data = (blade_rpcsubscribe_data_t *)ks_pool_alloc(ks_pool_get(bh), sizeof(blade_rpcsubscribe_data_t)); temp_data->original_callback = callback; temp_data->original_data = data; temp_data->channel_callback = channel_callback; temp_data->channel_data = channel_data; ks_pool_set_cleanup(temp_data, NULL, blade_rpcsubscribe_data_cleanup); - ret = blade_handle_rpcsubscribe_raw(bh, command, protocol, realm, channels, localid, KS_FALSE, blade_rpcsubscribe_response_handler, temp_data); + ret = blade_handle_rpcsubscribe_raw(bh, command, protocol, channels, localid, KS_FALSE, blade_rpcsubscribe_response_handler, temp_data); ks_pool_free(&localid); @@ -1418,7 +1598,6 @@ done: ks_status_t blade_handle_rpcsubscribe_raw(blade_handle_t *bh, blade_rpcsubscribe_command_t command, const char *protocol, - const char *realm, cJSON *channels, const char *subscriber, ks_bool_t downstream, @@ -1433,7 +1612,6 @@ ks_status_t blade_handle_rpcsubscribe_raw(blade_handle_t *bh, ks_assert(bh); ks_assert(protocol); - ks_assert(realm); ks_assert(channels); ks_assert(subscriber); @@ -1448,7 +1626,7 @@ ks_status_t blade_handle_rpcsubscribe_raw(blade_handle_t *bh, goto done; } } - else if (!(bs = blade_upstreammgr_session_get(bh->upstreammgr))) { + else if (!(bs = blade_routemgr_upstream_lookup(bh->routemgr))) { ret = KS_STATUS_DISCONNECTED; goto done; } @@ -1459,7 +1637,7 @@ ks_status_t blade_handle_rpcsubscribe_raw(blade_handle_t *bh, if (command == BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_REMOVE) { cJSON *channel = NULL; cJSON_ArrayForEach(channel, channels) { - blade_subscriptionmgr_subscriber_remove(bh->subscriptionmgr, NULL, protocol, realm, channel->valuestring, subscriber); + blade_subscriptionmgr_subscriber_remove(bh->subscriptionmgr, NULL, protocol, channel->valuestring, subscriber); } } @@ -1467,7 +1645,6 @@ ks_status_t blade_handle_rpcsubscribe_raw(blade_handle_t *bh, cJSON_AddNumberToObject(req_params, "command", command); cJSON_AddStringToObject(req_params, "protocol", protocol); - cJSON_AddStringToObject(req_params, "realm", realm); cJSON_AddStringToObject(req_params, "subscriber-nodeid", subscriber); if (downstream) cJSON_AddTrueToObject(req_params, "downstream"); cJSON_AddItemToObject(req_params, "channels", cJSON_Duplicate(channels, 1)); @@ -1494,7 +1671,6 @@ ks_bool_t blade_rpcsubscribe_request_handler(blade_rpc_request_t *brpcreq, void cJSON *req_params_command = NULL; blade_rpcsubscribe_command_t command = BLADE_RPCSUBSCRIBE_COMMAND_NONE; const char *req_params_protocol = NULL; - const char *req_params_realm = NULL; const char *req_params_subscriber_nodeid = NULL; cJSON *req_params_downstream = NULL; ks_bool_t downstream = KS_FALSE; @@ -1549,14 +1725,6 @@ ks_bool_t blade_rpcsubscribe_request_handler(blade_rpc_request_t *brpcreq, void goto done; } - req_params_realm = cJSON_GetObjectCstr(req_params, "realm"); - if (!req_params_realm) { - ks_log(KS_LOG_DEBUG, "Session (%s) subscribe request missing 'realm'\n", blade_session_id_get(bs)); - blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params realm"); - blade_session_send(bs, res, NULL, NULL); - goto done; - } - req_params_subscriber_nodeid = cJSON_GetObjectCstr(req_params, "subscriber-nodeid"); if (!req_params_subscriber_nodeid) { ks_log(KS_LOG_DEBUG, "Session (%s) subscribe request missing 'subscriber-nodeid'\n", blade_session_id_get(bs)); @@ -1579,26 +1747,23 @@ ks_bool_t blade_rpcsubscribe_request_handler(blade_rpc_request_t *brpcreq, void goto done; } - // @todo confirm the realm is permitted for the session, this gets complicated with subdomains, skipping for now - ks_log(KS_LOG_DEBUG, "Session (%s) subscribe request processing\n", blade_session_id_get(bs)); - masterlocal = blade_upstreammgr_masterlocal(blade_handle_upstreammgr_get(bh)); + masterlocal = blade_routemgr_master_local(blade_handle_routemgr_get(bh)); - if (masterlocal || blade_upstreammgr_localid_compare(blade_handle_upstreammgr_get(bh), req_params_subscriber_nodeid)) { + if (masterlocal || blade_routemgr_local_check(blade_handle_routemgr_get(bh), req_params_subscriber_nodeid)) { // @note This is normally handled by blade_handle_rpcsubscribe_raw() to ensure authorization removals are processed during the request path // including on the node they start on, whether that is the master or the subscriber if (command == BLADE_RPCSUBSCRIBE_COMMAND_SUBSCRIBER_REMOVE) { cJSON *channel = NULL; cJSON_ArrayForEach(channel, req_params_channels) { - blade_subscriptionmgr_subscriber_remove(bh->subscriptionmgr, NULL, req_params_protocol, req_params_realm, channel->valuestring, req_params_subscriber_nodeid); + blade_subscriptionmgr_subscriber_remove(bh->subscriptionmgr, NULL, req_params_protocol, channel->valuestring, req_params_subscriber_nodeid); } } blade_rpc_response_raw_create(&res, &res_result, blade_rpc_request_messageid_get(brpcreq)); cJSON_AddStringToObject(res_result, "protocol", req_params_protocol); - cJSON_AddStringToObject(res_result, "realm", req_params_realm); cJSON_AddStringToObject(res_result, "subscriber-nodeid", req_params_subscriber_nodeid); if (downstream) cJSON_AddTrueToObject(res_result, "downstream"); @@ -1607,8 +1772,8 @@ ks_bool_t blade_rpcsubscribe_request_handler(blade_rpc_request_t *brpcreq, void cJSON *channel = NULL; cJSON_ArrayForEach(channel, req_params_channels) { - if (blade_mastermgr_realm_protocol_channel_authorization_verify(bh->mastermgr, req_params_realm, req_params_protocol, channel->valuestring, req_params_subscriber_nodeid)) { - blade_subscriptionmgr_subscriber_add(bh->subscriptionmgr, NULL, req_params_protocol, req_params_realm, channel->valuestring, req_params_subscriber_nodeid); + if (blade_mastermgr_protocol_channel_authorization_verify(bh->mastermgr, req_params_protocol, channel->valuestring, req_params_subscriber_nodeid)) { + blade_subscriptionmgr_subscriber_add(bh->subscriptionmgr, NULL, req_params_protocol, channel->valuestring, req_params_subscriber_nodeid); if (!res_result_subscribe_channels) res_result_subscribe_channels = cJSON_CreateArray(); cJSON_AddItemToArray(res_result_subscribe_channels, cJSON_CreateString(channel->valuestring)); } else { @@ -1627,10 +1792,10 @@ ks_bool_t blade_rpcsubscribe_request_handler(blade_rpc_request_t *brpcreq, void blade_session_send(bs, res, NULL, NULL); } else { blade_rpcsubscribe_data_t *temp_data = (blade_rpcsubscribe_data_t *)ks_pool_alloc(pool, sizeof(blade_rpcsubscribe_data_t)); - temp_data->relayed_messageid = ks_pstrdup(pool, blade_rpc_request_messageid_get(brpcreq)); + temp_data->original_requestid = ks_pstrdup(pool, blade_rpc_request_messageid_get(brpcreq)); ks_pool_set_cleanup(temp_data, NULL, blade_rpcsubscribe_data_cleanup); - blade_handle_rpcsubscribe_raw(bh, command, req_params_protocol, req_params_realm, req_params_channels, req_params_subscriber_nodeid, downstream, blade_rpcsubscribe_response_handler, temp_data); + blade_handle_rpcsubscribe_raw(bh, command, req_params_protocol, req_params_channels, req_params_subscriber_nodeid, downstream, blade_rpcsubscribe_response_handler, temp_data); } done: @@ -1651,7 +1816,6 @@ ks_bool_t blade_rpcsubscribe_response_handler(blade_rpc_response_t *brpcres, voi cJSON *res = NULL; cJSON *res_result = NULL; const char *res_result_protocol = NULL; - const char *res_result_realm = NULL; const char *res_result_subscriber_nodeid = NULL; cJSON *res_result_downstream = NULL; ks_bool_t downstream = KS_FALSE; @@ -1677,7 +1841,7 @@ ks_bool_t blade_rpcsubscribe_response_handler(blade_rpc_response_t *brpcres, voi goto done; } - // @todo the following 3 fields, protocol, realm, and subscriber-nodeid may not be required to carry in the response as they could be + // @todo the following 2 fields, protocol, and subscriber-nodeid may not be required to carry in the response as they could be // obtained from the original request tied to the response, change this later res_result_protocol = cJSON_GetObjectCstr(res_result, "protocol"); if (!res_result_protocol) { @@ -1685,12 +1849,6 @@ ks_bool_t blade_rpcsubscribe_response_handler(blade_rpc_response_t *brpcres, voi goto done; } - res_result_realm = cJSON_GetObjectCstr(res_result, "realm"); - if (!res_result_realm) { - ks_log(KS_LOG_DEBUG, "Session (%s) subscribe response missing 'realm'\n", blade_session_id_get(bs)); - goto done; - } - res_result_subscriber_nodeid = cJSON_GetObjectCstr(res_result, "subscriber-nodeid"); if (!res_result_subscriber_nodeid) { ks_log(KS_LOG_DEBUG, "Session (%s) subscribe response missing 'subscriber-nodeid'\n", blade_session_id_get(bs)); @@ -1710,7 +1868,7 @@ ks_bool_t blade_rpcsubscribe_response_handler(blade_rpc_response_t *brpcres, voi blade_subscription_t *bsub = NULL; cJSON_ArrayForEach(channel, res_result_subscribe_channels) { - blade_subscriptionmgr_subscriber_add(bh->subscriptionmgr, &bsub, res_result_protocol, res_result_realm, channel->valuestring, res_result_subscriber_nodeid); + blade_subscriptionmgr_subscriber_add(bh->subscriptionmgr, &bsub, res_result_protocol, channel->valuestring, res_result_subscriber_nodeid); // @note these will only get assigned on the last response, received by the subscriber if (temp_data && temp_data->channel_callback) blade_subscription_callback_set(bsub, temp_data->channel_callback); if (temp_data && temp_data->channel_data) blade_subscription_callback_data_set(bsub, temp_data->channel_data); @@ -1720,10 +1878,10 @@ ks_bool_t blade_rpcsubscribe_response_handler(blade_rpc_response_t *brpcres, voi // @note this will only happen on the last response, received by the subscriber if (temp_data && temp_data->original_callback) ret = temp_data->original_callback(brpcres, temp_data->original_data); - if (temp_data && temp_data->relayed_messageid) { + if (temp_data && temp_data->original_requestid) { blade_session_t *relay = NULL; if (downstream) { - if (!(relay = blade_upstreammgr_session_get(bh->upstreammgr))) { + if (!(relay = blade_routemgr_upstream_lookup(bh->routemgr))) { goto done; } } else { @@ -1732,10 +1890,9 @@ ks_bool_t blade_rpcsubscribe_response_handler(blade_rpc_response_t *brpcres, voi } } - blade_rpc_response_raw_create(&res, &res_result, temp_data->relayed_messageid); + blade_rpc_response_raw_create(&res, &res_result, temp_data->original_requestid); cJSON_AddStringToObject(res_result, "protocol", res_result_protocol); - cJSON_AddStringToObject(res_result, "realm", res_result_realm); cJSON_AddStringToObject(res_result, "subscriber-nodeid", res_result_subscriber_nodeid); if (downstream) cJSON_AddTrueToObject(res_result, "downstream"); if (res_result_subscribe_channels) cJSON_AddItemToObject(res_result, "subscribe-channels", cJSON_Duplicate(res_result_subscribe_channels, 1)); @@ -1756,15 +1913,14 @@ done: // blade.broadcast request generator -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_status_t ret = KS_STATUS_SUCCESS; ks_assert(bh); ks_assert(protocol); - ks_assert(realm); - ret = blade_subscriptionmgr_broadcast(bh->subscriptionmgr, BLADE_RPCBROADCAST_COMMAND_EVENT, NULL, protocol, realm, channel, event, params, callback, data); + ret = blade_subscriptionmgr_broadcast(bh->subscriptionmgr, BLADE_RPCBROADCAST_COMMAND_EVENT, NULL, protocol, channel, event, params, callback, data); // @todo must check if the local node is also subscribed to receive the event, this is a special edge case which has some extra considerations // if the local node is subscribed to receive the event, it should be received here as a special case, otherwise the broadcast request handler @@ -1786,7 +1942,6 @@ ks_bool_t blade_rpcbroadcast_request_handler(blade_rpc_request_t *brpcreq, void cJSON *req_params_command = NULL; blade_rpcbroadcast_command_t command = BLADE_RPCBROADCAST_COMMAND_NONE; const char *req_params_protocol = NULL; - const char *req_params_realm = NULL; const char *req_params_channel = NULL; const char *req_params_event = NULL; cJSON *req_params_params = NULL; @@ -1822,14 +1977,6 @@ ks_bool_t blade_rpcbroadcast_request_handler(blade_rpc_request_t *brpcreq, void goto done; } - req_params_realm = cJSON_GetObjectCstr(req_params, "realm"); - if (!req_params_realm) { - ks_log(KS_LOG_DEBUG, "Session (%s) broadcast request missing 'realm'\n", blade_session_id_get(bs)); - blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params realm"); - blade_session_send(bs, res, NULL, NULL); - goto done; - } - req_params_command = cJSON_GetObjectItem(req_params, "command"); if (!req_params_command) { ks_log(KS_LOG_DEBUG, "Session (%s) broadcast request missing 'command'\n", blade_session_id_get(bs)); @@ -1862,17 +2009,14 @@ ks_bool_t blade_rpcbroadcast_request_handler(blade_rpc_request_t *brpcreq, void req_params_params = cJSON_GetObjectItem(req_params, "params"); - blade_subscriptionmgr_broadcast(bh->subscriptionmgr, command, blade_session_id_get(bs), req_params_protocol, req_params_realm, req_params_channel, req_params_event, req_params_params, NULL, NULL); + blade_subscriptionmgr_broadcast(bh->subscriptionmgr, command, blade_session_id_get(bs), req_params_protocol, req_params_channel, req_params_event, req_params_params, NULL, NULL); if (command == BLADE_RPCBROADCAST_COMMAND_EVENT) { - bsub = blade_subscriptionmgr_subscription_lookup(bh->subscriptionmgr, req_params_protocol, req_params_realm, req_params_channel); + bsub = blade_subscriptionmgr_subscription_lookup(bh->subscriptionmgr, req_params_protocol, req_params_channel); if (bsub) { const char *localid = NULL; - ks_pool_t *pool = NULL; - pool = ks_pool_get(bh); - - blade_upstreammgr_localid_copy(bh->upstreammgr, pool, &localid); + blade_routemgr_local_copy(bh->routemgr, &localid); ks_assert(localid); if (ks_hash_search(blade_subscription_subscribers_get(bsub), (void *)localid, KS_UNLOCKED)) { @@ -1888,7 +2032,6 @@ ks_bool_t blade_rpcbroadcast_request_handler(blade_rpc_request_t *brpcreq, void // @todo this is not neccessary, can obtain this from the original request cJSON_AddStringToObject(res_result, "protocol", req_params_protocol); - cJSON_AddStringToObject(res_result, "realm", req_params_realm); if (req_params_channel) cJSON_AddStringToObject(res_result, "channel", req_params_channel); if (req_params_event) cJSON_AddStringToObject(res_result, "event", req_params_event); @@ -1903,64 +2046,56 @@ done: return ret; } -KS_DECLARE(const char *) blade_rpcbroadcast_request_realm_get(blade_rpc_request_t *brpcreq) -{ - cJSON *req = NULL; - const char *req_realm = NULL; - - ks_assert(brpcreq); - - req = blade_rpc_request_message_get(brpcreq); - ks_assert(req); - - req_realm = cJSON_GetObjectCstr(req, "realm"); - - return req_realm; -} KS_DECLARE(const char *) blade_rpcbroadcast_request_protocol_get(blade_rpc_request_t *brpcreq) { cJSON *req = NULL; - const char *req_protocol = NULL; + cJSON *req_params = NULL; + const char *req_params_protocol = NULL; ks_assert(brpcreq); req = blade_rpc_request_message_get(brpcreq); ks_assert(req); - req_protocol = cJSON_GetObjectCstr(req, "protocol"); + req_params = cJSON_GetObjectItem(req, "params"); + if (req_params) req_params_protocol = cJSON_GetObjectCstr(req_params, "protocol"); - return req_protocol; + return req_params_protocol; } KS_DECLARE(const char *) blade_rpcbroadcast_request_channel_get(blade_rpc_request_t *brpcreq) { cJSON *req = NULL; - const char *req_channel = NULL; + cJSON *req_params = NULL; + const char *req_params_channel = NULL; ks_assert(brpcreq); req = blade_rpc_request_message_get(brpcreq); ks_assert(req); - req_channel = cJSON_GetObjectCstr(req, "channel"); + req_params = cJSON_GetObjectItem(req, "params"); + if (req_params) req_params_channel = cJSON_GetObjectCstr(req_params, "channel"); - return req_channel; + return req_params_channel; } KS_DECLARE(const char *) blade_rpcbroadcast_request_event_get(blade_rpc_request_t *brpcreq) { cJSON *req = NULL; - const char *req_event = NULL; + cJSON *req_params = NULL; + const char *req_params_event = NULL; ks_assert(brpcreq); req = blade_rpc_request_message_get(brpcreq); ks_assert(req); - req_event = cJSON_GetObjectCstr(req, "event"); + req_params = cJSON_GetObjectItem(req, "params"); + if (req_params) req_params_event = cJSON_GetObjectCstr(req_params, "event"); - return req_event; + return req_params_event; } KS_DECLARE(cJSON *) blade_rpcbroadcast_request_params_get(blade_rpc_request_t *brpcreq) diff --git a/libs/libblade/src/blade_subscription.c b/libs/libblade/src/blade_subscription.c index 153551e771..19c6fdd5d1 100644 --- a/libs/libblade/src/blade_subscription.c +++ b/libs/libblade/src/blade_subscription.c @@ -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) diff --git a/libs/libblade/src/blade_subscriptionmgr.c b/libs/libblade/src/blade_subscriptionmgr.c index e09dabfaa0..64105239cd 100644 --- a/libs/libblade/src/blade_subscriptionmgr.c +++ b/libs/libblade/src/blade_subscriptionmgr.c @@ -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); diff --git a/libs/libblade/src/blade_transport_wss.c b/libs/libblade/src/blade_transport_wss.c index db55ca4e44..ea123f4a0e 100644 --- a/libs/libblade/src/blade_transport_wss.c +++ b/libs/libblade/src/blade_transport_wss.c @@ -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)); diff --git a/libs/libblade/src/blade_upstreammgr.c b/libs/libblade/src/blade_upstreammgr.c deleted file mode 100644 index bcdee57834..0000000000 --- a/libs/libblade/src/blade_upstreammgr.c +++ /dev/null @@ -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: - */ diff --git a/libs/libblade/src/include/blade.h b/libs/libblade/src/include/blade.h index eb5d7d222b..b47ace6153 100644 --- a/libs/libblade/src/include/blade.h +++ b/libs/libblade/src/include/blade.h @@ -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" diff --git a/libs/libblade/src/include/blade_channel.h b/libs/libblade/src/include/blade_channel.h index 64885f6dd5..660748dd36 100644 --- a/libs/libblade/src/include/blade_channel.h +++ b/libs/libblade/src/include/blade_channel.h @@ -36,9 +36,10 @@ #include 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); diff --git a/libs/libblade/src/include/blade_identity.h b/libs/libblade/src/include/blade_identity.h index 8d8329459e..bdef1d203e 100644 --- a/libs/libblade/src/include/blade_identity.h +++ b/libs/libblade/src/include/blade_identity.h @@ -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 diff --git a/libs/libblade/src/include/blade_mastermgr.h b/libs/libblade/src/include/blade_mastermgr.h index 12a97d220e..11242aee9a 100644 --- a/libs/libblade/src/include/blade_mastermgr.h +++ b/libs/libblade/src/include/blade_mastermgr.h @@ -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 diff --git a/libs/libblade/src/include/blade_protocol.h b/libs/libblade/src/include/blade_protocol.h index cdbf74ce53..bb59a1da63 100644 --- a/libs/libblade/src/include/blade_protocol.h +++ b/libs/libblade/src/include/blade_protocol.h @@ -36,9 +36,8 @@ #include 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); diff --git a/libs/libblade/src/include/blade_realm.h b/libs/libblade/src/include/blade_realm.h deleted file mode 100644 index 1e70f5c06c..0000000000 --- a/libs/libblade/src/include/blade_realm.h +++ /dev/null @@ -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 - -KS_BEGIN_EXTERN_C -KS_DECLARE(ks_status_t) blade_realm_create(blade_realm_t **brP, ks_pool_t *pool, const char *name); -KS_DECLARE(ks_status_t) blade_realm_destroy(blade_realm_t **brP); -KS_DECLARE(const char *) blade_realm_name_get(blade_realm_t *br); -KS_DECLARE(ks_status_t) blade_realm_read_lock(blade_realm_t *br); -KS_DECLARE(ks_status_t) blade_realm_read_unlock(blade_realm_t *br); -KS_DECLARE(ks_status_t) blade_realm_write_lock(blade_realm_t *br); -KS_DECLARE(ks_status_t) blade_realm_write_unlock(blade_realm_t *br); -KS_DECLARE(ks_hash_iterator_t *) blade_realm_protocols_iterator(blade_realm_t *br, ks_locked_t locked); -KS_DECLARE(blade_protocol_t *) blade_realm_protocol_lookup(blade_realm_t *br, const char *protocol, ks_bool_t writelocked); -KS_DECLARE(ks_status_t) blade_realm_protocol_add(blade_realm_t *br, blade_protocol_t *protocol); -KS_DECLARE(ks_status_t) blade_realm_protocol_remove(blade_realm_t *br, const char *protocol); -KS_END_EXTERN_C - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libblade/src/include/blade_routemgr.h b/libs/libblade/src/include/blade_routemgr.h index 9f7830a020..c75426c183 100644 --- a/libs/libblade/src/include/blade_routemgr.h +++ b/libs/libblade/src/include/blade_routemgr.h @@ -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 diff --git a/libs/libblade/src/include/blade_rpc.h b/libs/libblade/src/include/blade_rpc.h index a966088af4..69e83344b2 100644 --- a/libs/libblade/src/include/blade_rpc.h +++ b/libs/libblade/src/include/blade_rpc.h @@ -36,12 +36,11 @@ #include 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); diff --git a/libs/libblade/src/include/blade_rpcmgr.h b/libs/libblade/src/include/blade_rpcmgr.h index b45fb6439f..2d93189812 100644 --- a/libs/libblade/src/include/blade_rpcmgr.h +++ b/libs/libblade/src/include/blade_rpcmgr.h @@ -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); diff --git a/libs/libblade/src/include/blade_session.h b/libs/libblade/src/include/blade_session.h index b84ac257ad..4bdbe8a85c 100644 --- a/libs/libblade/src/include/blade_session.h +++ b/libs/libblade/src/include/blade_session.h @@ -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); diff --git a/libs/libblade/src/include/blade_stack.h b/libs/libblade/src/include/blade_stack.h index 4e9c03438e..4a8df5c835 100644 --- a/libs/libblade/src/include/blade_stack.h +++ b/libs/libblade/src/include/blade_stack.h @@ -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); diff --git a/libs/libblade/src/include/blade_subscription.h b/libs/libblade/src/include/blade_subscription.h index 96052a744e..5c591941bd 100644 --- a/libs/libblade/src/include/blade_subscription.h +++ b/libs/libblade/src/include/blade_subscription.h @@ -36,10 +36,9 @@ #include 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); diff --git a/libs/libblade/src/include/blade_subscriptionmgr.h b/libs/libblade/src/include/blade_subscriptionmgr.h index 045130c2e5..0cc811985e 100644 --- a/libs/libblade/src/include/blade_subscriptionmgr.h +++ b/libs/libblade/src/include/blade_subscriptionmgr.h @@ -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 diff --git a/libs/libblade/src/include/blade_types.h b/libs/libblade/src/include/blade_types.h index db1c0b3ed2..c806dec27b 100644 --- a/libs/libblade/src/include/blade_types.h +++ b/libs/libblade/src/include/blade_types.h @@ -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); diff --git a/libs/libblade/src/include/blade_upstreammgr.h b/libs/libblade/src/include/blade_upstreammgr.h deleted file mode 100644 index d662560aff..0000000000 --- a/libs/libblade/src/include/blade_upstreammgr.h +++ /dev/null @@ -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 - -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: - */ diff --git a/libs/libblade/switchblade/switchblade.c b/libs/libblade/switchblade/switchblade.c index ae69a24bf8..8a62c3fed3 100644 --- a/libs/libblade/switchblade/switchblade.c +++ b/libs/libblade/switchblade/switchblade.c @@ -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: diff --git a/libs/libblade/test/bladec.c b/libs/libblade/test/bladec.c index cb6a2fb4bc..e5744e3dd8 100644 --- a/libs/libblade/test/bladec.c +++ b/libs/libblade/test/bladec.c @@ -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); } diff --git a/libs/libblade/test/blades.c b/libs/libblade/test/blades.c index 668d6ad2b7..d81904ebab 100644 --- a/libs/libblade/test/blades.c +++ b/libs/libblade/test/blades.c @@ -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); } diff --git a/libs/libblade/test/testcli.c b/libs/libblade/test/testcli.c index 213c159386..d904c448af 100644 --- a/libs/libblade/test/testcli.c +++ b/libs/libblade/test/testcli.c @@ -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); } diff --git a/libs/libblade/test/testcon.c b/libs/libblade/test/testcon.c index 3394576da9..4dffa70330 100644 --- a/libs/libblade/test/testcon.c +++ b/libs/libblade/test/testcon.c @@ -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: diff --git a/libs/libks/src/ks_ssl.c b/libs/libks/src/ks_ssl.c index 5db491d4d5..4f3efafd8f 100644 --- a/libs/libks/src/ks_ssl.c +++ b/libs/libks/src/ks_ssl.c @@ -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(); }