From 3ff59b6a5a403dd1b1bff9ff231f699ef510cc36 Mon Sep 17 00:00:00 2001 From: Shane Bryldt Date: Wed, 21 Jun 2017 17:15:53 -0600 Subject: [PATCH] FS-10167: First pass of adding a test protocol --- libs/libblade/libblade.sln | 36 ++ libs/libblade/src/blade_stack.c | 78 +++- libs/libblade/src/include/blade_stack.h | 7 +- libs/libblade/test/Makefile.am | 10 + libs/libblade/test/bladec.c | 4 +- libs/libblade/test/blades.c | 27 +- libs/libblade/test/testcli.c | 462 ++++++++++++++++++++++++ libs/libblade/test/testcli.cfg | 3 + libs/libblade/test/testcli.vcxproj | 215 +++++++++++ libs/libblade/test/testcon.c | 414 +++++++++++++++++++++ libs/libblade/test/testcon.cfg | 20 + libs/libblade/test/testcon.vcxproj | 215 +++++++++++ 12 files changed, 1473 insertions(+), 18 deletions(-) create mode 100644 libs/libblade/test/testcli.c create mode 100644 libs/libblade/test/testcli.cfg create mode 100644 libs/libblade/test/testcli.vcxproj create mode 100644 libs/libblade/test/testcon.c create mode 100644 libs/libblade/test/testcon.cfg create mode 100644 libs/libblade/test/testcon.vcxproj diff --git a/libs/libblade/libblade.sln b/libs/libblade/libblade.sln index 8b9d9cce67..4eed1e7669 100644 --- a/libs/libblade/libblade.sln +++ b/libs/libblade/libblade.sln @@ -23,6 +23,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bladec", "test\bladec.vcxpr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "switchblade", "switchblade\switchblade.vcxproj", "{8330E669-77F3-4F70-A275-6F7BABE050A7}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testcli", "test\testcli.vcxproj", "{CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testcon", "test\testcon.vcxproj", "{D67EEF66-B323-4BCF-9E3C-3A640B9949B7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -195,6 +199,38 @@ Global {8330E669-77F3-4F70-A275-6F7BABE050A7}.ReleaseDLL|x64.Build.0 = Release|x64 {8330E669-77F3-4F70-A275-6F7BABE050A7}.ReleaseDLL|x86.ActiveCfg = Release|Win32 {8330E669-77F3-4F70-A275-6F7BABE050A7}.ReleaseDLL|x86.Build.0 = Release|Win32 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.Debug|x64.ActiveCfg = Debug|x64 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.Debug|x64.Build.0 = Debug|x64 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.Debug|x86.ActiveCfg = Debug|Win32 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.Debug|x86.Build.0 = Debug|Win32 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.DebugDLL|x64.ActiveCfg = Debug|x64 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.DebugDLL|x64.Build.0 = Debug|x64 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.DebugDLL|x86.ActiveCfg = Debug|Win32 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.DebugDLL|x86.Build.0 = Debug|Win32 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.Release|x64.ActiveCfg = Release|x64 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.Release|x64.Build.0 = Release|x64 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.Release|x86.ActiveCfg = Release|Win32 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.Release|x86.Build.0 = Release|Win32 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.ReleaseDLL|x64.ActiveCfg = Release|x64 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.ReleaseDLL|x64.Build.0 = Release|x64 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.ReleaseDLL|x86.ActiveCfg = Release|Win32 + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}.ReleaseDLL|x86.Build.0 = Release|Win32 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.Debug|x64.ActiveCfg = Debug|x64 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.Debug|x64.Build.0 = Debug|x64 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.Debug|x86.ActiveCfg = Debug|Win32 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.Debug|x86.Build.0 = Debug|Win32 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.DebugDLL|x64.ActiveCfg = Debug|x64 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.DebugDLL|x64.Build.0 = Debug|x64 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.DebugDLL|x86.ActiveCfg = Debug|Win32 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.DebugDLL|x86.Build.0 = Debug|Win32 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.Release|x64.ActiveCfg = Release|x64 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.Release|x64.Build.0 = Release|x64 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.Release|x86.ActiveCfg = Release|Win32 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.Release|x86.Build.0 = Release|Win32 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.ReleaseDLL|x64.ActiveCfg = Release|x64 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.ReleaseDLL|x64.Build.0 = Release|x64 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.ReleaseDLL|x86.ActiveCfg = Release|Win32 + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7}.ReleaseDLL|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/libs/libblade/src/blade_stack.c b/libs/libblade/src/blade_stack.c index 38c2029045..28e92ae9bf 100644 --- a/libs/libblade/src/blade_stack.c +++ b/libs/libblade/src/blade_stack.c @@ -1557,6 +1557,9 @@ done: // blade.locate request generator +// @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 providers 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_protocol_locate(blade_handle_t *bh, const char *name, const char *realm, blade_rpc_response_callback_t callback, void *data) { ks_status_t ret = KS_STATUS_SUCCESS; @@ -1878,6 +1881,40 @@ done: return ret; } +KS_DECLARE(const char *) blade_protocol_execute_request_requester_nodeid_get(blade_rpc_request_t *brpcreq) +{ + cJSON *req = NULL; + cJSON *req_params = NULL; + const char *req_requester_nodeid = NULL; + + ks_assert(brpcreq); + + req = blade_rpc_request_message_get(brpcreq); + ks_assert(req); + + req_params = cJSON_GetObjectItem(req, "params"); + if (req_params) req_requester_nodeid = cJSON_GetObjectCstr(req_params, "requester-nodeid"); + + return req_requester_nodeid; +} + +KS_DECLARE(const char *) blade_protocol_execute_request_responder_nodeid_get(blade_rpc_request_t *brpcreq) +{ + cJSON *req = NULL; + cJSON *req_params = NULL; + const char *req_responder_nodeid = NULL; + + ks_assert(brpcreq); + + req = blade_rpc_request_message_get(brpcreq); + ks_assert(req); + + req_params = cJSON_GetObjectItem(req, "params"); + if (req_params) req_responder_nodeid = cJSON_GetObjectCstr(req_params, "responder-nodeid"); + + return req_responder_nodeid; +} + KS_DECLARE(cJSON *) blade_protocol_execute_request_params_get(blade_rpc_request_t *brpcreq) { cJSON *req = NULL; @@ -2147,7 +2184,7 @@ done: // blade.broadcast request generator -KS_DECLARE(ks_status_t) blade_protocol_broadcast(blade_handle_t *bh, const char *event, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data) +KS_DECLARE(ks_status_t) blade_protocol_broadcast(blade_handle_t *bh, const char *broadcaster_nodeid, const char *event, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data) { ks_status_t ret = KS_STATUS_SUCCESS; @@ -2157,7 +2194,10 @@ KS_DECLARE(ks_status_t) blade_protocol_broadcast(blade_handle_t *bh, const char ks_assert(realm); // this will ensure any downstream subscriber sessions, and upstream session if available will be broadcasted to - ret = blade_protocol_broadcast_raw(bh, NULL, event, protocol, realm, params, callback, data); + ks_rwl_read_lock(bh->local_nodeid_rwl); + if (!broadcaster_nodeid) broadcaster_nodeid = bh->local_nodeid; + ret = blade_protocol_broadcast_raw(bh, broadcaster_nodeid, NULL, event, protocol, realm, params, callback, data); + ks_rwl_read_unlock(bh->local_nodeid_rwl); // @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 @@ -2166,13 +2206,14 @@ KS_DECLARE(ks_status_t) blade_protocol_broadcast(blade_handle_t *bh, const char return ret; } -KS_DECLARE(ks_status_t) blade_protocol_broadcast_raw(blade_handle_t *bh, const char *excluded_nodeid, const char *event, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data) +KS_DECLARE(ks_status_t) blade_protocol_broadcast_raw(blade_handle_t *bh, const char *broadcaster_nodeid, const char *excluded_nodeid, const char *event, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data) { const char *bsub_key = NULL; blade_subscription_t *bsub = NULL; blade_session_t *bs = NULL; ks_assert(bh); + ks_assert(broadcaster_nodeid); ks_assert(event); ks_assert(protocol); ks_assert(realm); @@ -2205,6 +2246,7 @@ KS_DECLARE(ks_status_t) blade_protocol_broadcast_raw(blade_handle_t *bh, const c blade_rpc_request_raw_create(bh->pool, &req, &req_params, NULL, "blade.broadcast"); + cJSON_AddStringToObject(req_params, "broadcaster-nodeid", broadcaster_nodeid); cJSON_AddStringToObject(req_params, "event", event); cJSON_AddStringToObject(req_params, "protocol", protocol); cJSON_AddStringToObject(req_params, "realm", realm); @@ -2234,6 +2276,7 @@ KS_DECLARE(ks_status_t) blade_protocol_broadcast_raw(blade_handle_t *bh, const c blade_rpc_request_raw_create(bh->pool, &req, &req_params, NULL, "blade.broadcast"); + cJSON_AddStringToObject(req_params, "broadcaster-nodeid", broadcaster_nodeid); cJSON_AddStringToObject(req_params, "event", event); cJSON_AddStringToObject(req_params, "protocol", protocol); cJSON_AddStringToObject(req_params, "realm", realm); @@ -2258,6 +2301,7 @@ ks_bool_t blade_protocol_broadcast_request_handler(blade_rpc_request_t *brpcreq, blade_session_t *bs = NULL; cJSON *req = NULL; cJSON *req_params = NULL; + const char *req_params_broadcaster_nodeid = NULL; const char *req_params_event = NULL; const char *req_params_protocol = NULL; const char *req_params_realm = NULL; @@ -2287,6 +2331,14 @@ ks_bool_t blade_protocol_broadcast_request_handler(blade_rpc_request_t *brpcreq, goto done; } + req_params_broadcaster_nodeid = cJSON_GetObjectCstr(req_params, "broadcaster-nodeid"); + if (!req_params_broadcaster_nodeid) { + ks_log(KS_LOG_DEBUG, "Session (%s) broadcast request missing 'broadcaster-nodeid'\n", blade_session_id_get(bs)); + blade_rpc_error_raw_create(&res, NULL, blade_rpc_request_messageid_get(brpcreq), -32602, "Missing params broadcaster-nodeid"); + blade_session_send(bs, res, NULL, NULL); + goto done; + } + req_params_event = cJSON_GetObjectCstr(req_params, "event"); if (!req_params_event) { ks_log(KS_LOG_DEBUG, "Session (%s) broadcast request missing 'event'\n", blade_session_id_get(bs)); @@ -2314,7 +2366,7 @@ ks_bool_t blade_protocol_broadcast_request_handler(blade_rpc_request_t *brpcreq, req_params_params = cJSON_GetObjectItem(req_params, "params"); - blade_protocol_broadcast_raw(bh, blade_session_id_get(bs), req_params_event, req_params_protocol, req_params_realm, req_params_params, NULL, NULL); + blade_protocol_broadcast_raw(bh, req_params_broadcaster_nodeid, blade_session_id_get(bs), req_params_event, req_params_protocol, req_params_realm, req_params_params, NULL, NULL); bsub_key = ks_psprintf(bh->pool, "%s@%s/%s", req_params_protocol, req_params_realm, req_params_event); @@ -2338,6 +2390,7 @@ ks_bool_t blade_protocol_broadcast_request_handler(blade_rpc_request_t *brpcreq, // build the actual response finally blade_rpc_response_raw_create(&res, &res_result, blade_rpc_request_messageid_get(brpcreq)); + cJSON_AddStringToObject(res_result, "broadcaster-nodeid", req_params_broadcaster_nodeid); cJSON_AddStringToObject(res_result, "event", req_params_event); cJSON_AddStringToObject(res_result, "protocol", req_params_protocol); cJSON_AddStringToObject(res_result, "realm", req_params_realm); @@ -2354,6 +2407,23 @@ done: return ret; } +KS_DECLARE(const char *) blade_protocol_broadcast_request_broadcaster_nodeid_get(blade_rpc_request_t *brpcreq) +{ + cJSON *req = NULL; + cJSON *req_params = NULL; + const char *req_broadcaster_nodeid = NULL; + + ks_assert(brpcreq); + + req = blade_rpc_request_message_get(brpcreq); + ks_assert(req); + + req_params = cJSON_GetObjectItem(req, "params"); + if (req_params) req_broadcaster_nodeid = cJSON_GetObjectCstr(req_params, "broadcaster-nodeid"); + + return req_broadcaster_nodeid; +} + KS_DECLARE(cJSON *) blade_protocol_broadcast_request_params_get(blade_rpc_request_t *brpcreq) { cJSON *req = NULL; diff --git a/libs/libblade/src/include/blade_stack.h b/libs/libblade/src/include/blade_stack.h index 9ab945612e..4b33cea51c 100644 --- a/libs/libblade/src/include/blade_stack.h +++ b/libs/libblade/src/include/blade_stack.h @@ -105,6 +105,8 @@ KS_DECLARE(ks_status_t) blade_protocol_publish(blade_handle_t *bh, const char *n KS_DECLARE(ks_status_t) blade_protocol_locate(blade_handle_t *bh, const char *name, const char *realm, blade_rpc_response_callback_t callback, void *data); KS_DECLARE(ks_status_t) blade_protocol_execute(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(const char *) blade_protocol_execute_request_requester_nodeid_get(blade_rpc_request_t *brpcreq); +KS_DECLARE(const char *) blade_protocol_execute_request_responder_nodeid_get(blade_rpc_request_t *brpcreq); KS_DECLARE(cJSON *) blade_protocol_execute_request_params_get(blade_rpc_request_t *brpcreq); KS_DECLARE(cJSON *) blade_protocol_execute_response_result_get(blade_rpc_response_t *brpcres); KS_DECLARE(void) blade_protocol_execute_response_send(blade_rpc_request_t *brpcreq, cJSON *result); @@ -112,8 +114,9 @@ KS_DECLARE(void) blade_protocol_execute_response_send(blade_rpc_request_t *brpcr KS_DECLARE(ks_status_t) blade_protocol_subscribe(blade_handle_t *bh, const char *event, const char *protocol, const char *realm, ks_bool_t remove, blade_rpc_response_callback_t callback, void *data, blade_rpc_request_callback_t event_callback, void *event_data); KS_DECLARE(ks_status_t) blade_protocol_subscribe_raw(blade_handle_t *bh, const char *event, const char *protocol, const char *realm, ks_bool_t remove, blade_rpc_response_callback_t callback, void *data); -KS_DECLARE(ks_status_t) blade_protocol_broadcast(blade_handle_t *bh, const char *event, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data); -KS_DECLARE(ks_status_t) blade_protocol_broadcast_raw(blade_handle_t *bh, const char *excluded_nodeid, const char *event, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data); +KS_DECLARE(ks_status_t) blade_protocol_broadcast(blade_handle_t *bh, const char *broadcaster_nodeid, const char *event, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data); +KS_DECLARE(ks_status_t) blade_protocol_broadcast_raw(blade_handle_t *bh, const char *broadcaster_nodeid, const char *excluded_nodeid, const char *event, const char *protocol, const char *realm, cJSON *params, blade_rpc_response_callback_t callback, void *data); +KS_DECLARE(const char *) blade_protocol_broadcast_request_broadcaster_nodeid_get(blade_rpc_request_t *brpcreq); KS_DECLARE(cJSON *) blade_protocol_broadcast_request_params_get(blade_rpc_request_t *brpcreq); KS_END_EXTERN_C diff --git a/libs/libblade/test/Makefile.am b/libs/libblade/test/Makefile.am index 9d4f9f6b50..1884b5847e 100644 --- a/libs/libblade/test/Makefile.am +++ b/libs/libblade/test/Makefile.am @@ -18,6 +18,16 @@ blades_SOURCES = blades.c tap.c blades_CFLAGS = $(AM_CFLAGS) blades_LDADD = $(TEST_LDADD) +check_PROGRAMS += testcli +testcli_SOURCES = testcli.c tap.c +testcli_CFLAGS = $(AM_CFLAGS) +testcli_LDADD = $(TEST_LDADD) + +check_PROGRAMS += testcon +testcon_SOURCES = testcon.c tap.c +testcon_CFLAGS = $(AM_CFLAGS) +testcon_LDADD = $(TEST_LDADD) + #check_PROGRAMS += testdht2 #testdht2_SOURCES = testdht2.c tap.c #testdht2_CFLAGS = $(AM_CFLAGS) diff --git a/libs/libblade/test/bladec.c b/libs/libblade/test/bladec.c index 2858dc0946..e1a34a6b83 100644 --- a/libs/libblade/test/bladec.c +++ b/libs/libblade/test/bladec.c @@ -201,9 +201,7 @@ int main(int argc, char **argv) blade_identity_destroy(&target); - ks_sleep_ms(5000); - - + ks_sleep_ms(3000); } loop(bh); diff --git a/libs/libblade/test/blades.c b/libs/libblade/test/blades.c index 15a323f23c..bc3fc6f09e 100644 --- a/libs/libblade/test/blades.c +++ b/libs/libblade/test/blades.c @@ -16,10 +16,12 @@ struct command_def_s { }; void command_quit(blade_handle_t *bh, char *args); +void command_publish(blade_handle_t *bh, char *args); void command_broadcast(blade_handle_t *bh, char *args); static const struct command_def_s command_defs[] = { { "quit", command_quit }, + { "publish", command_publish }, { "broadcast", command_broadcast }, { NULL, NULL } @@ -144,7 +146,6 @@ int main(int argc, char **argv) if (autoconnect) { blade_connection_t *bc = NULL; blade_identity_t *target = NULL; - blade_rpc_t *brpc = NULL; blade_identity_create(&target, blade_handle_pool_get(bh)); @@ -152,13 +153,7 @@ int main(int argc, char **argv) blade_identity_destroy(&target); - ks_sleep_ms(5000); // @todo use session state change callback to know when the session is ready, this hack temporarily ensures it's ready before trying to publish upstream - - blade_rpc_create(&brpc, bh, "test.echo", "test", "mydomain.com", test_echo_request_handler, NULL); - blade_handle_protocolrpc_register(brpc); - - // @todo build up json-based method schema for each protocolrpc registered above, and pass into blade_protocol_publish() to attach to the request, to be stored in the blade_protocol_t tracked by the master node - blade_protocol_publish(bh, "test", "mydomain.com", blade_publish_response_handler, NULL); + ks_sleep_ms(3000); // @todo use session state change callback to know when the session is ready, this hack temporarily ensures it's ready before trying to publish upstream } loop(bh); @@ -237,12 +232,26 @@ void command_quit(blade_handle_t *bh, char *args) g_shutdown = KS_TRUE; } +void command_publish(blade_handle_t *bh, char *args) +{ + blade_rpc_t *brpc = NULL; + + ks_assert(bh); + ks_assert(args); + + blade_rpc_create(&brpc, bh, "test.echo", "test", "mydomain.com", test_echo_request_handler, NULL); + blade_handle_protocolrpc_register(brpc); + + // @todo build up json-based method schema for each protocolrpc registered above, and pass into blade_protocol_publish() to attach to the request, to be stored in the blade_protocol_t tracked by the master node + blade_protocol_publish(bh, "test", "mydomain.com", blade_publish_response_handler, NULL); +} + void command_broadcast(blade_handle_t *bh, char *args) { ks_assert(bh); ks_assert(args); - blade_protocol_broadcast(bh, "test.event", "test", "mydomain.com", NULL, test_event_response_handler, NULL); + blade_protocol_broadcast(bh, NULL, "test.event", "test", "mydomain.com", NULL, test_event_response_handler, NULL); } diff --git a/libs/libblade/test/testcli.c b/libs/libblade/test/testcli.c new file mode 100644 index 0000000000..60db6dcd7c --- /dev/null +++ b/libs/libblade/test/testcli.c @@ -0,0 +1,462 @@ +#include "blade.h" +#include "tap.h" + +#define CONSOLE_INPUT_MAX 512 + +ks_bool_t g_shutdown = KS_FALSE; + +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); +void command_locate(blade_handle_t *bh, char *args); +void command_join(blade_handle_t *bh, char *args); +void command_leave(blade_handle_t *bh, char *args); +void command_talk(blade_handle_t *bh, char *args); + +static const struct command_def_s command_defs[] = { + { "quit", command_quit }, + { "locate", command_locate }, + { "join", command_join }, + { "leave", command_leave }, + { "talk", command_talk }, + + { NULL, NULL } +}; + +const char *g_testcon_nodeid = NULL; + +ks_bool_t test_locate_response_handler(blade_rpc_response_t *brpcres, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + const char *nodeid = NULL; + cJSON *res = NULL; + cJSON *res_result = NULL; + cJSON *res_result_providers = NULL; + const char *res_result_protocol = NULL; + const char *res_result_realm = NULL; + //cJSON *params = NULL; + + ks_assert(brpcres); + + bh = blade_rpc_response_handle_get(brpcres); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_response_sessionid_get(brpcres)); + ks_assert(bs); + + res = blade_rpc_response_message_get(brpcres); + ks_assert(res); + + res_result = cJSON_GetObjectItem(res, "result"); + ks_assert(res_result); + + 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_providers = cJSON_GetObjectItem(res_result, "providers"); + ks_assert(res_result_providers); + + ks_log(KS_LOG_DEBUG, "Session (%s) locate (%s@%s) response processing\n", blade_session_id_get(bs), res_result_protocol, res_result_realm); + + for (int index = 0; index < cJSON_GetArraySize(res_result_providers); ++index) { + cJSON *elem = cJSON_GetArrayItem(res_result_providers, index); + if (elem->type == cJSON_String) { + nodeid = elem->valuestring; + } + } + + blade_session_read_unlock(bs); + + if (nodeid) { + g_testcon_nodeid = ks_pstrdup(blade_handle_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); + + return KS_FALSE; +} + +ks_bool_t test_join_response_handler(blade_rpc_response_t *brpcres, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + cJSON *result = NULL; + + ks_assert(brpcres); + + bh = blade_rpc_response_handle_get(brpcres); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_response_sessionid_get(brpcres)); + ks_assert(bs); + + result = blade_protocol_execute_response_result_get(brpcres); + ks_assert(result); + + ks_log(KS_LOG_DEBUG, "Session (%s) test.join response processing\n", blade_session_id_get(bs)); + + blade_session_read_unlock(bs); + + return KS_FALSE; +} + +ks_bool_t test_leave_response_handler(blade_rpc_response_t *brpcres, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + cJSON *result = NULL; + + ks_assert(brpcres); + + bh = blade_rpc_response_handle_get(brpcres); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_response_sessionid_get(brpcres)); + ks_assert(bs); + + result = blade_protocol_execute_response_result_get(brpcres); + ks_assert(result); + + ks_log(KS_LOG_DEBUG, "Session (%s) test.leave response processing\n", blade_session_id_get(bs)); + + blade_session_read_unlock(bs); + + return KS_FALSE; +} + +ks_bool_t test_talk_response_handler(blade_rpc_response_t *brpcres, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + cJSON *result = NULL; + + ks_assert(brpcres); + + bh = blade_rpc_response_handle_get(brpcres); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_response_sessionid_get(brpcres)); + ks_assert(bs); + + result = blade_protocol_execute_response_result_get(brpcres); + ks_assert(result); + + ks_log(KS_LOG_DEBUG, "Session (%s) test.talk response processing\n", blade_session_id_get(bs)); + + blade_session_read_unlock(bs); + + return KS_FALSE; +} + +ks_bool_t test_join_broadcast_handler(blade_rpc_request_t *brpcreq, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + const char *broadcaster_nodeid = NULL; + cJSON *params = NULL; + cJSON *result = NULL; + + ks_assert(brpcreq); + + bh = blade_rpc_request_handle_get(brpcreq); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_request_sessionid_get(brpcreq)); + ks_assert(bs); + + params = blade_protocol_broadcast_request_params_get(brpcreq); + ks_assert(params); + + broadcaster_nodeid = blade_protocol_broadcast_request_broadcaster_nodeid_get(brpcreq); + ks_assert(broadcaster_nodeid); + + ks_log(KS_LOG_DEBUG, "Session (%s) test.join (%s) broadcast processing\n", blade_session_id_get(bs), broadcaster_nodeid); + + blade_session_read_unlock(bs); + + return KS_FALSE; +} + +ks_bool_t test_leave_broadcast_handler(blade_rpc_request_t *brpcreq, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + const char *broadcaster_nodeid = NULL; + cJSON *params = NULL; + cJSON *result = NULL; + + ks_assert(brpcreq); + + bh = blade_rpc_request_handle_get(brpcreq); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_request_sessionid_get(brpcreq)); + ks_assert(bs); + + params = blade_protocol_broadcast_request_params_get(brpcreq); + ks_assert(params); + + broadcaster_nodeid = blade_protocol_broadcast_request_broadcaster_nodeid_get(brpcreq); + ks_assert(broadcaster_nodeid); + + ks_log(KS_LOG_DEBUG, "Session (%s) test.leave (%s) broadcast processing\n", blade_session_id_get(bs), broadcaster_nodeid); + + blade_session_read_unlock(bs); + + return KS_FALSE; +} + +ks_bool_t test_talk_broadcast_handler(blade_rpc_request_t *brpcreq, void *data) +{ + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + const char *broadcaster_nodeid = NULL; + cJSON *params = NULL; + cJSON *result = NULL; + + ks_assert(brpcreq); + + bh = blade_rpc_request_handle_get(brpcreq); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_request_sessionid_get(brpcreq)); + ks_assert(bs); + + broadcaster_nodeid = blade_protocol_broadcast_request_broadcaster_nodeid_get(brpcreq); + ks_assert(broadcaster_nodeid); + + params = blade_protocol_broadcast_request_params_get(brpcreq); + ks_assert(params); + + // @todo pull out text from params + + ks_log(KS_LOG_DEBUG, "Session (%s) test.talk (%s) broadcast processing\n", blade_session_id_get(bs), broadcaster_nodeid); + + blade_session_read_unlock(bs); + + return KS_FALSE; +} + + +int main(int argc, char **argv) +{ + blade_handle_t *bh = NULL; + config_t config; + config_setting_t *config_blade = NULL; + const char *cfgpath = "testcli.cfg"; + //const char *session_state_callback_id = NULL; + const char *autoconnect = NULL; + + ks_global_set_default_logger(KS_LOG_LEVEL_DEBUG); + + blade_init(); + + blade_handle_create(&bh); + + //if (argc > 1) cfgpath = argv[1]; + if (argc > 1) autoconnect = argv[1]; + + config_init(&config); + if (!config_read_file(&config, cfgpath)) { + ks_log(KS_LOG_ERROR, "%s:%d - %s\n", config_error_file(&config), config_error_line(&config), config_error_text(&config)); + config_destroy(&config); + return EXIT_FAILURE; + } + config_blade = config_lookup(&config, "blade"); + if (!config_blade) { + ks_log(KS_LOG_ERROR, "Missing 'blade' config group\n"); + config_destroy(&config); + return EXIT_FAILURE; + } + if (config_setting_type(config_blade) != CONFIG_TYPE_GROUP) { + ks_log(KS_LOG_ERROR, "The 'blade' config setting is not a group\n"); + return EXIT_FAILURE; + } + + if (blade_handle_startup(bh, config_blade) != KS_STATUS_SUCCESS) { + ks_log(KS_LOG_ERROR, "Blade startup failed\n"); + return EXIT_FAILURE; + } + + if (autoconnect) { + blade_connection_t *bc = NULL; + blade_identity_t *target = NULL; + ks_bool_t connected = KS_FALSE; + + blade_identity_create(&target, blade_handle_pool_get(bh)); + + if (blade_identity_parse(target, autoconnect) == KS_STATUS_SUCCESS) connected = blade_handle_connect(bh, &bc, target, NULL) == KS_STATUS_SUCCESS; + + blade_identity_destroy(&target); + + ks_sleep_ms(3000); + } + + loop(bh); + + blade_handle_destroy(&bh); + + config_destroy(&config); + + blade_shutdown(); + + return 0; +} + +void loop(blade_handle_t *bh) +{ + char buf[CONSOLE_INPUT_MAX]; + while (!g_shutdown) { + 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); + } +} + +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; +} + +void command_locate(blade_handle_t *bh, char *args) +{ + ks_assert(bh); + ks_assert(args); + + blade_protocol_locate(bh, "test", "mydomain.com", test_locate_response_handler, NULL); +} + +void command_join(blade_handle_t *bh, char *args) +{ + cJSON *params = NULL; + + ks_assert(bh); + ks_assert(args); + + if (!g_testcon_nodeid) { + ks_log(KS_LOG_DEBUG, "Protocol controller has not been located\n"); + return; + } + + + params = cJSON_CreateObject(); + + blade_protocol_execute(bh, g_testcon_nodeid, "test.join", "test", "mydomain.com", params, test_join_response_handler, NULL); + + blade_protocol_subscribe(bh, "test.join", "test", "mydomain.com", KS_FALSE, NULL, NULL, test_join_broadcast_handler, NULL); + blade_protocol_subscribe(bh, "test.leave", "test", "mydomain.com", KS_FALSE, NULL, NULL, test_leave_broadcast_handler, NULL); + blade_protocol_subscribe(bh, "test.talk", "test", "mydomain.com", KS_FALSE, NULL, NULL, test_talk_broadcast_handler, NULL); +} + +void command_leave(blade_handle_t *bh, char *args) +{ + cJSON *params = NULL; + + ks_assert(bh); + ks_assert(args); + + if (!g_testcon_nodeid) { + ks_log(KS_LOG_DEBUG, "Protocol controller has not been located\n"); + return; + } + + params = cJSON_CreateObject(); + + blade_protocol_execute(bh, g_testcon_nodeid, "test.leave", "test", "mydomain.com", params, test_leave_response_handler, NULL); + + blade_protocol_subscribe(bh, "test.join", "test", "mydomain.com", KS_TRUE, NULL, NULL, NULL, NULL); + blade_protocol_subscribe(bh, "test.leave", "test", "mydomain.com", KS_TRUE, NULL, NULL, NULL, NULL); + blade_protocol_subscribe(bh, "test.talk", "test", "mydomain.com", KS_TRUE, NULL, NULL, NULL, NULL); +} + +void command_talk(blade_handle_t *bh, char *args) +{ + cJSON *params = NULL; + + ks_assert(bh); + ks_assert(args); + + if (!g_testcon_nodeid) { + ks_log(KS_LOG_DEBUG, "Protocol controller has not been located\n"); + return; + } + if (!args[0]) { + ks_log(KS_LOG_DEBUG, "Syntax: talk \n"); + return; + } + + params = cJSON_CreateObject(); + + cJSON_AddStringToObject(params, "text", args); + + blade_protocol_execute(bh, g_testcon_nodeid, "test.talk", "test", "mydomain.com", params, test_talk_response_handler, NULL); +} + +/* 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/test/testcli.cfg b/libs/libblade/test/testcli.cfg new file mode 100644 index 0000000000..6d7e93b5a0 --- /dev/null +++ b/libs/libblade/test/testcli.cfg @@ -0,0 +1,3 @@ +blade: +{ +}; diff --git a/libs/libblade/test/testcli.vcxproj b/libs/libblade/test/testcli.vcxproj new file mode 100644 index 0000000000..b8cb371645 --- /dev/null +++ b/libs/libblade/test/testcli.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {CF89E839-AB50-4BBB-AC34-0D6232E1EBB5} + Win32Proj + testcli + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include;$(IncludePath) + $(LibraryPath) + + + true + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include64;$(IncludePath) + $(LibraryPath) + + + false + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include;$(IncludePath) + $(LibraryPath) + + + false + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include64;$(IncludePath) + $(LibraryPath) + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x86;../src/include;. + 4090 + true + false + + + Console + true + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x64;../src/include;. + 4090 + true + false + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x86;../src/include;. + 4090 + true + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x64;../src/include;. + 4090 + true + + + Console + true + true + true + + + + + + + + + {70d178d8-1100-4152-86c0-809a91cff832} + + + {1a234565-926d-49b2-83e4-d56e0c38c9f2} + + + {a185b162-6cb6-4502-b03f-b56f7699a8d9} + + + {d331904d-a00a-4694-a5a3-fcff64ab5dbe} + + + {b4b62169-5ad4-4559-8707-3d933ac5db39} + + + {a89d6d18-6203-4149-9051-f8e798e7a3e7} + + + + + + \ No newline at end of file diff --git a/libs/libblade/test/testcon.c b/libs/libblade/test/testcon.c new file mode 100644 index 0000000000..f42796eadc --- /dev/null +++ b/libs/libblade/test/testcon.c @@ -0,0 +1,414 @@ +#include "blade.h" +#include "tap.h" + +#define CONSOLE_INPUT_MAX 512 + +ks_bool_t g_shutdown = KS_FALSE; + +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 } +}; + +struct testproto_s { + blade_handle_t *handle; + ks_pool_t *pool; + ks_hash_t *participants; +}; +typedef struct testproto_s testproto_t; + +static void testproto_cleanup(ks_pool_t *pool, void *ptr, void *arg, ks_pool_cleanup_action_t action, ks_pool_cleanup_type_t type) +{ + //testproto_t *test = (testproto_t *)ptr; + + //ks_assert(test); + + switch (action) { + case KS_MPCL_ANNOUNCE: + break; + case KS_MPCL_TEARDOWN: + break; + case KS_MPCL_DESTROY: + break; + } +} + +ks_status_t testproto_create(testproto_t **testP, blade_handle_t *bh) +{ + testproto_t *test = NULL; + ks_pool_t *pool = NULL; + + ks_assert(testP); + ks_assert(bh); + + ks_pool_open(&pool); + ks_assert(pool); + + test = ks_pool_alloc(pool, sizeof(testproto_t)); + test->handle = bh; + test->pool = pool; + + ks_hash_create(&test->participants, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_RWLOCK | KS_HASH_FLAG_DUP_CHECK | KS_HASH_FLAG_FREE_KEY, pool); + + ks_pool_set_cleanup(pool, test, NULL, testproto_cleanup); + + *testP = test; + + return KS_STATUS_SUCCESS; +} + +ks_status_t testproto_destroy(testproto_t **testP) +{ + testproto_t *test = NULL; + ks_pool_t *pool = NULL; + + ks_assert(testP); + ks_assert(*testP); + + test = *testP; + + ks_pool_free(test->pool, testP); + + return KS_STATUS_SUCCESS; +} + +ks_bool_t test_publish_response_handler(blade_rpc_response_t *brpcres, void *data) +{ + testproto_t *test = NULL; + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + + ks_assert(brpcres); + ks_assert(data); + + test = (testproto_t *)data; + + bh = blade_rpc_response_handle_get(brpcres); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_response_sessionid_get(brpcres)); + ks_assert(bs); + + ks_log(KS_LOG_DEBUG, "Session (%s) publish response processing\n", blade_session_id_get(bs)); + + blade_session_read_unlock(bs); + + return KS_FALSE; +} + +ks_bool_t test_join_request_handler(blade_rpc_request_t *brpcreq, void *data) +{ + testproto_t *test = NULL; + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + const char *requester_nodeid = NULL; + const char *key = NULL; + cJSON *params = NULL; + cJSON *result = NULL; + + ks_assert(brpcreq); + ks_assert(data); + + test = (testproto_t *)data; + + bh = blade_rpc_request_handle_get(brpcreq); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_request_sessionid_get(brpcreq)); + ks_assert(bs); + + requester_nodeid = blade_protocol_execute_request_requester_nodeid_get(brpcreq); + ks_assert(requester_nodeid); + + params = blade_protocol_execute_request_params_get(brpcreq); + ks_assert(params); + + ks_log(KS_LOG_DEBUG, "Session (%s) test.join request processing\n", blade_session_id_get(bs)); + + key = ks_pstrdup(test->pool, requester_nodeid); + ks_assert(key); + + ks_hash_write_lock(test->participants); + ks_hash_insert(test->participants, (void *)key, (void *)KS_TRUE); + ks_hash_write_unlock(test->participants); + + blade_session_read_unlock(bs); + + result = cJSON_CreateObject(); + + blade_protocol_execute_response_send(brpcreq, result); + + params = cJSON_CreateObject(); + + blade_protocol_broadcast(bh, requester_nodeid, "test.join", "test", "mydomain.com", params, NULL, NULL); + + return KS_FALSE; +} + +ks_bool_t test_leave_request_handler(blade_rpc_request_t *brpcreq, void *data) +{ + testproto_t *test = NULL; + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + const char *requester_nodeid = NULL; + const char *key = NULL; + cJSON *params = NULL; + cJSON *result = NULL; + + ks_assert(brpcreq); + ks_assert(data); + + test = (testproto_t *)data; + + bh = blade_rpc_request_handle_get(brpcreq); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_request_sessionid_get(brpcreq)); + ks_assert(bs); + + requester_nodeid = blade_protocol_execute_request_requester_nodeid_get(brpcreq); + ks_assert(requester_nodeid); + + params = blade_protocol_execute_request_params_get(brpcreq); + ks_assert(params); + + ks_log(KS_LOG_DEBUG, "Session (%s) test.leave (%s) request processing\n", blade_session_id_get(bs), requester_nodeid); + + ks_hash_write_lock(test->participants); + ks_hash_remove(test->participants, (void *)requester_nodeid); + ks_hash_write_unlock(test->participants); + + blade_session_read_unlock(bs); + + result = cJSON_CreateObject(); + + blade_protocol_execute_response_send(brpcreq, result); + + params = cJSON_CreateObject(); + + blade_protocol_broadcast(bh, requester_nodeid, "test.leave", "test", "mydomain.com", params, NULL, NULL); + + return KS_FALSE; +} + +ks_bool_t test_talk_request_handler(blade_rpc_request_t *brpcreq, void *data) +{ + testproto_t *test = NULL; + blade_handle_t *bh = NULL; + blade_session_t *bs = NULL; + const char *requester_nodeid = NULL; + const char *text = NULL; + cJSON *params = NULL; + cJSON *result = NULL; + + ks_assert(brpcreq); + ks_assert(data); + + test = (testproto_t *)data; + + bh = blade_rpc_request_handle_get(brpcreq); + ks_assert(bh); + + bs = blade_handle_sessions_lookup(bh, blade_rpc_request_sessionid_get(brpcreq)); + ks_assert(bs); + + requester_nodeid = blade_protocol_execute_request_requester_nodeid_get(brpcreq); + ks_assert(requester_nodeid); + + params = blade_protocol_execute_request_params_get(brpcreq); + ks_assert(params); + + text = cJSON_GetObjectCstr(params, "text"); + ks_assert(text); + + ks_log(KS_LOG_DEBUG, "Session (%s) test.talk (%s) request processing\n", blade_session_id_get(bs), requester_nodeid); + + blade_session_read_unlock(bs); + + result = cJSON_CreateObject(); + + blade_protocol_execute_response_send(brpcreq, result); + + params = cJSON_CreateObject(); + + cJSON_AddStringToObject(params, "text", text); + + blade_protocol_broadcast(bh, requester_nodeid, "test.talk", "test", "mydomain.com", params, NULL, NULL); + + return KS_FALSE; +} + + +int main(int argc, char **argv) +{ + blade_handle_t *bh = NULL; + ks_pool_t *pool = NULL; + config_t config; + config_setting_t *config_blade = NULL; + const char *cfgpath = "testcon.cfg"; + const char *autoconnect = NULL; + testproto_t *test = NULL; + + ks_global_set_default_logger(KS_LOG_LEVEL_DEBUG); + + blade_init(); + + blade_handle_create(&bh); + ks_assert(bh); + + pool = blade_handle_pool_get(bh); + ks_assert(pool); + + if (argc > 1) autoconnect = argv[1]; + + config_init(&config); + if (!config_read_file(&config, cfgpath)) { + ks_log(KS_LOG_ERROR, "%s:%d - %s\n", config_error_file(&config), config_error_line(&config), config_error_text(&config)); + config_destroy(&config); + return EXIT_FAILURE; + } + config_blade = config_lookup(&config, "blade"); + if (!config_blade) { + ks_log(KS_LOG_ERROR, "Missing 'blade' config group\n"); + config_destroy(&config); + return EXIT_FAILURE; + } + if (config_setting_type(config_blade) != CONFIG_TYPE_GROUP) { + ks_log(KS_LOG_ERROR, "The 'blade' config setting is not a group\n"); + return EXIT_FAILURE; + } + + if (blade_handle_startup(bh, config_blade) != KS_STATUS_SUCCESS) { + ks_log(KS_LOG_ERROR, "Blade startup failed\n"); + return EXIT_FAILURE; + } + + testproto_create(&test, bh); + + if (autoconnect) { + blade_connection_t *bc = NULL; + blade_identity_t *target = NULL; + ks_bool_t connected = KS_FALSE; + blade_rpc_t *brpc = NULL; + + blade_identity_create(&target, blade_handle_pool_get(bh)); + + if (blade_identity_parse(target, autoconnect) == KS_STATUS_SUCCESS) connected = blade_handle_connect(bh, &bc, target, NULL) == KS_STATUS_SUCCESS; + + blade_identity_destroy(&target); + + if (connected) { + // @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 + ks_sleep_ms(3000); + + blade_rpc_create(&brpc, bh, "test.join", "test", "mydomain.com", test_join_request_handler, test); + blade_handle_protocolrpc_register(brpc); + + blade_rpc_create(&brpc, bh, "test.leave", "test", "mydomain.com", test_leave_request_handler, test); + blade_handle_protocolrpc_register(brpc); + + blade_rpc_create(&brpc, bh, "test.talk", "test", "mydomain.com", test_talk_request_handler, test); + blade_handle_protocolrpc_register(brpc); + + blade_protocol_publish(bh, "test", "mydomain.com", test_publish_response_handler, test); + } + } + + loop(bh); + + blade_handle_destroy(&bh); + + testproto_destroy(&test); + + config_destroy(&config); + + blade_shutdown(); + + return 0; +} + +void loop(blade_handle_t *bh) +{ + char buf[CONSOLE_INPUT_MAX]; + while (!g_shutdown) { + 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); + } +} + +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: +* 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/test/testcon.cfg b/libs/libblade/test/testcon.cfg new file mode 100644 index 0000000000..6deb9958e2 --- /dev/null +++ b/libs/libblade/test/testcon.cfg @@ -0,0 +1,20 @@ +blade: +{ + transport: + { + wss: + { + endpoints: + { + ipv4 = ( { address = "0.0.0.0", port = 2101 } ); + ipv6 = ( { address = "::", port = 2101 } ); + backlog = 128; + }; + # SSL group is optional, disabled when absent + ssl: + { + # todo: server SSL stuffs here + }; + }; + }; +}; diff --git a/libs/libblade/test/testcon.vcxproj b/libs/libblade/test/testcon.vcxproj new file mode 100644 index 0000000000..8b208c1f57 --- /dev/null +++ b/libs/libblade/test/testcon.vcxproj @@ -0,0 +1,215 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {D67EEF66-B323-4BCF-9E3C-3A640B9949B7} + Win32Proj + testcon + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include;$(IncludePath) + $(LibraryPath) + + + true + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include64;$(IncludePath) + $(LibraryPath) + + + false + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include;$(IncludePath) + $(LibraryPath) + + + false + $(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include64;$(IncludePath) + $(LibraryPath) + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x86;../src/include;. + 4090 + true + false + + + Console + true + + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x64;../src/include;. + 4090 + true + false + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x86;../src/include;. + 4090 + true + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x64;../src/include;. + 4090 + true + + + Console + true + true + true + + + + + + + + + {70d178d8-1100-4152-86c0-809a91cff832} + + + {1a234565-926d-49b2-83e4-d56e0c38c9f2} + + + {a185b162-6cb6-4502-b03f-b56f7699a8d9} + + + {d331904d-a00a-4694-a5a3-fcff64ab5dbe} + + + {b4b62169-5ad4-4559-8707-3d933ac5db39} + + + {a89d6d18-6203-4149-9051-f8e798e7a3e7} + + + + + + \ No newline at end of file