FS-10167: First pass of adding a test protocol

This commit is contained in:
Shane Bryldt 2017-06-21 17:15:53 -06:00
parent dcc0bf72ec
commit 3ff59b6a5a
12 changed files with 1473 additions and 18 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -201,9 +201,7 @@ int main(int argc, char **argv)
blade_identity_destroy(&target);
ks_sleep_ms(5000);
ks_sleep_ms(3000);
}
loop(bh);

View File

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

View File

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

View File

@ -0,0 +1,3 @@
blade:
{
};

View File

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{CF89E839-AB50-4BBB-AC34-0D6232E1EBB5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>testcli</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\w32\openssl-version.props" />
<Import Project="..\..\..\w32\sodium.props" />
<Import Project="..\..\..\w32\config.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\w32\openssl-version.props" />
<Import Project="..\..\..\w32\sodium.props" />
<Import Project="..\..\..\w32\config.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\w32\openssl-version.props" />
<Import Project="..\..\..\w32\sodium.props" />
<Import Project="..\..\..\w32\config.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\w32\openssl-version.props" />
<Import Project="..\..\..\w32\sodium.props" />
<Import Project="..\..\..\w32\config.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IncludePath>$(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>$(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include64;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IncludePath>$(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>$(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include64;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x86;../src/include;.</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4090</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x64;../src/include;.</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4090</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x86;../src/include;.</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4090</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x64;../src/include;.</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4090</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="tap.c" />
<ClCompile Include="testcli.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\libks\libks.vcxproj">
<Project>{70d178d8-1100-4152-86c0-809a91cff832}</Project>
</ProjectReference>
<ProjectReference Include="..\..\win32\libconfig\libconfig.2015.vcxproj">
<Project>{1a234565-926d-49b2-83e4-d56e0c38c9f2}</Project>
</ProjectReference>
<ProjectReference Include="..\..\win32\libsodium\libsodium.2015.vcxproj">
<Project>{a185b162-6cb6-4502-b03f-b56f7699a8d9}</Project>
</ProjectReference>
<ProjectReference Include="..\..\win32\openssl\libeay32.2015.vcxproj">
<Project>{d331904d-a00a-4694-a5a3-fcff64ab5dbe}</Project>
</ProjectReference>
<ProjectReference Include="..\..\win32\openssl\ssleay32.2015.vcxproj">
<Project>{b4b62169-5ad4-4559-8707-3d933ac5db39}</Project>
</ProjectReference>
<ProjectReference Include="..\libblade.vcxproj">
<Project>{a89d6d18-6203-4149-9051-f8e798e7a3e7}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

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

View File

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

View File

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D67EEF66-B323-4BCF-9E3C-3A640B9949B7}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>testcon</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\w32\openssl-version.props" />
<Import Project="..\..\..\w32\sodium.props" />
<Import Project="..\..\..\w32\config.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\w32\openssl-version.props" />
<Import Project="..\..\..\w32\sodium.props" />
<Import Project="..\..\..\w32\config.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\w32\openssl-version.props" />
<Import Project="..\..\..\w32\sodium.props" />
<Import Project="..\..\..\w32\config.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\w32\openssl-version.props" />
<Import Project="..\..\..\w32\sodium.props" />
<Import Project="..\..\..\w32\config.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IncludePath>$(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>$(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include64;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IncludePath>$(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
<IncludePath>$(SolutionDir);$(SolutionDir)..\libks\src\include;$(SolutionDir)..\libsodium-$(SodiumVersion)\src\libsodium\include;$(SolutionDir)..\libconfig-$(ConfigVersion)\lib;$(SolutionDir)\openssl\include64;$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x86;../src/include;.</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4090</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x64;../src/include;.</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4090</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x86;../src/include;.</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4090</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)..\win32\openssl\include;$(SolutionDir)..\win32\openssl\include_x64;../src/include;.</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4090</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="tap.c" />
<ClCompile Include="testcon.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\libks\libks.vcxproj">
<Project>{70d178d8-1100-4152-86c0-809a91cff832}</Project>
</ProjectReference>
<ProjectReference Include="..\..\win32\libconfig\libconfig.2015.vcxproj">
<Project>{1a234565-926d-49b2-83e4-d56e0c38c9f2}</Project>
</ProjectReference>
<ProjectReference Include="..\..\win32\libsodium\libsodium.2015.vcxproj">
<Project>{a185b162-6cb6-4502-b03f-b56f7699a8d9}</Project>
</ProjectReference>
<ProjectReference Include="..\..\win32\openssl\libeay32.2015.vcxproj">
<Project>{d331904d-a00a-4694-a5a3-fcff64ab5dbe}</Project>
</ProjectReference>
<ProjectReference Include="..\..\win32\openssl\ssleay32.2015.vcxproj">
<Project>{b4b62169-5ad4-4559-8707-3d933ac5db39}</Project>
</ProjectReference>
<ProjectReference Include="..\libblade.vcxproj">
<Project>{a89d6d18-6203-4149-9051-f8e798e7a3e7}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>