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
{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
// 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;
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;
// 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;
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
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);
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);
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);
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;
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));
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);
// 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);
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;
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);
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
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)
blade_identity_destroy(&target);
- ks_sleep_ms(5000);
-
-
+ ks_sleep_ms(3000);
}
loop(bh);
};
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 }
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));
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);
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);
}
--- /dev/null
+#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:
+*/
--- /dev/null
+blade:
+{
+};
--- /dev/null
+<?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>
\ No newline at end of file
--- /dev/null
+#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:
+*/
--- /dev/null
+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
+ };
+ };
+ };
+};
--- /dev/null
+<?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>
\ No newline at end of file