diff --git a/libs/libblade/src/blade_service.c b/libs/libblade/src/blade_service.c
index b52e7d06a9..4eabd669af 100644
--- a/libs/libblade/src/blade_service.c
+++ b/libs/libblade/src/blade_service.c
@@ -130,13 +130,25 @@ ks_status_t blade_service_config(blade_service_t *bs, config_setting_t *config)
 
 	ks_assert(bs);
 
-	if (!config) return KS_STATUS_FAIL;
-	if (!config_setting_is_group(config)) return KS_STATUS_FAIL;
+	if (!config) {
+		ks_log(KS_LOG_DEBUG, "!config\n");
+		return KS_STATUS_FAIL;
+	}
+	if (!config_setting_is_group(config)) {
+		ks_log(KS_LOG_DEBUG, "!config_setting_is_group(config)\n");
+		return KS_STATUS_FAIL;
+	}
 
 	websockets = config_setting_get_member(config, "websockets");
-	if (!websockets) return KS_STATUS_FAIL;
-	websockets_endpoints = config_setting_get_member(config, "endpoints");
-	if (!websockets_endpoints) return KS_STATUS_FAIL;
+	if (!websockets) {
+		ks_log(KS_LOG_DEBUG, "!websockets\n");
+		return KS_STATUS_FAIL;
+	}
+	websockets_endpoints = config_setting_get_member(websockets, "endpoints");
+	if (!websockets_endpoints) {
+		ks_log(KS_LOG_DEBUG, "!websockets_endpoints\n");
+		return KS_STATUS_FAIL;
+	}
 	websockets_endpoints_ipv4 = config_lookup_from(websockets_endpoints, "ipv4");
 	websockets_endpoints_ipv6 = config_lookup_from(websockets_endpoints, "ipv6");
 	if (websockets_endpoints_ipv4) {
@@ -156,6 +168,10 @@ ks_status_t blade_service_config(blade_service_t *bs, config_setting_t *config)
 							config_setting_get_string(tmp1),
 							config_setting_get_int(tmp2),
 							AF_INET) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
+			ks_log(KS_LOG_DEBUG,
+				   "Binding to IPV4 %s on port %d\n",
+				   ks_addr_get_host(&config_websockets_endpoints_ipv4[index]),
+				   ks_addr_get_port(&config_websockets_endpoints_ipv4[index]));
 		}
 	}
 	if (websockets_endpoints_ipv6) {
@@ -175,6 +191,10 @@ ks_status_t blade_service_config(blade_service_t *bs, config_setting_t *config)
 							config_setting_get_string(tmp1),
 							config_setting_get_int(tmp2),
 							AF_INET6) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
+			ks_log(KS_LOG_DEBUG,
+				   "Binding to IPV6 %s on port %d\n",
+				   ks_addr_get_host(&config_websockets_endpoints_ipv6[index]),
+				   ks_addr_get_port(&config_websockets_endpoints_ipv6[index]));
 		}
 	}
 	if (config_websockets_endpoints_ipv4_length + config_websockets_endpoints_ipv6_length <= 0) return KS_STATUS_FAIL;
@@ -212,13 +232,22 @@ KS_DECLARE(ks_status_t) blade_service_startup(blade_service_t *bs, config_settin
 	// @todo: If the configuration is invalid, and this is a case of reloading a new config, then the service shutdown shouldn't occur
 	// but the service may use configuration that changes before we shutdown if it is read successfully, may require a config reader/writer mutex?
 	
-    if (blade_service_config(bs, config) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
+    if (blade_service_config(bs, config) != KS_STATUS_SUCCESS) {
+		ks_log(KS_LOG_DEBUG, "blade_service_config failed\n");
+		return KS_STATUS_FAIL;
+	}
 
 	for (int32_t index = 0; index < bs->config_websockets_endpoints_ipv4_length; ++index) {
-		if (blade_service_listen(bs, &bs->config_websockets_endpoints_ipv4[index]) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
+		if (blade_service_listen(bs, &bs->config_websockets_endpoints_ipv4[index]) != KS_STATUS_SUCCESS) {
+			ks_log(KS_LOG_DEBUG, "blade_service_listen (v4) failed\n");
+			return KS_STATUS_FAIL;
+		}
 	}
 	for (int32_t index = 0; index < bs->config_websockets_endpoints_ipv6_length; ++index) {
-		if (blade_service_listen(bs, &bs->config_websockets_endpoints_ipv6[index]) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
+		if (blade_service_listen(bs, &bs->config_websockets_endpoints_ipv6[index]) != KS_STATUS_SUCCESS) {
+			ks_log(KS_LOG_DEBUG, "blade_service_listen (v6) failed\n");
+			return KS_STATUS_FAIL;
+		}
 	}
 
 	if (ks_thread_create_ex(&bs->listeners_thread,
@@ -282,20 +311,23 @@ ks_status_t blade_service_listen(blade_service_t *bs, ks_sockaddr_t *addr)
 	ks_assert(addr);
 
 	if ((listener = socket(addr->family, SOCK_STREAM, IPPROTO_TCP)) == KS_SOCK_INVALID) {
+		ks_log(KS_LOG_DEBUG, "listener == KS_SOCK_INVALID\n");
 		ret = KS_STATUS_FAIL;
 		goto done;
 	}
 
 	ks_socket_option(listener, SO_REUSEADDR, KS_TRUE);
 	ks_socket_option(listener, TCP_NODELAY, KS_TRUE);
-	// @todo make sure v6 does not automatically map to a v4 using socket option IPV6_V6ONLY?
+	if (addr->family == AF_INET6) ks_socket_option(listener, IPV6_V6ONLY, KS_TRUE);
 
 	if (ks_addr_bind(listener, addr) != KS_STATUS_SUCCESS) {
+		ks_log(KS_LOG_DEBUG, "ks_addr_bind(listener, addr) != KS_STATUS_SUCCESS\n");
 		ret = KS_STATUS_FAIL;
 		goto done;
 	}
 
 	if (listen(listener, bs->config_websockets_endpoints_backlog) != 0) {
+		ks_log(KS_LOG_DEBUG, "listen(listener, backlog) != 0\n");
 		ret = KS_STATUS_FAIL;
 		goto done;
 	}
@@ -327,6 +359,8 @@ void *blade_service_listeners_thread(ks_thread_t *thread, void *data)
 	ks_assert(data);
 
 	service = (blade_service_t *)data;
+
+	ks_log(KS_LOG_DEBUG, "Service running\n");
 	
 	// @todo 1 more callback for blade_service_state_callback_t? providing event up the stack on service startup, shutdown, and service errors?
 	
diff --git a/libs/libblade/src/blade_stack.c b/libs/libblade/src/blade_stack.c
index 48a89afe0d..8504af02c4 100644
--- a/libs/libblade/src/blade_stack.c
+++ b/libs/libblade/src/blade_stack.c
@@ -147,18 +147,27 @@ KS_DECLARE(ks_status_t) blade_handle_startup(blade_handle_t *bh, config_setting_
 {
 	ks_assert(bh);
 
-    if (blade_handle_config(bh, config) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
+    if (blade_handle_config(bh, config) != KS_STATUS_SUCCESS) {
+		ks_log(KS_LOG_DEBUG, "blade_handle_config failed\n");
+		return KS_STATUS_FAIL;
+	}
 
 	if (bh->config_service && !blade_handle_service_available(bh)) {
 		blade_service_create(&bh->service, bh->pool, bh->tpool, bh, service_peer_state_callback);
 		ks_assert(bh->service);
-		if (blade_service_startup(bh->service, bh->config_service) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
+		if (blade_service_startup(bh->service, bh->config_service) != KS_STATUS_SUCCESS) {
+			ks_log(KS_LOG_DEBUG, "blade_service_startup failed\n");
+			return KS_STATUS_FAIL;
+		}
 	}
 	
 	if (bh->config_datastore && !blade_handle_datastore_available(bh)) {
 		blade_datastore_create(&bh->datastore, bh->pool, bh->tpool);
 		ks_assert(bh->datastore);
-		if (blade_datastore_startup(bh->datastore, bh->config_datastore) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
+		if (blade_datastore_startup(bh->datastore, bh->config_datastore) != KS_STATUS_SUCCESS) {
+			ks_log(KS_LOG_DEBUG, "blade_datastore_startup failed\n");
+			return KS_STATUS_FAIL;
+		}
 	}
 	
 	return KS_STATUS_SUCCESS;
diff --git a/libs/libblade/test/Makefile.am b/libs/libblade/test/Makefile.am
index d577b95507..9bc1a688df 100644
--- a/libs/libblade/test/Makefile.am
+++ b/libs/libblade/test/Makefile.am
@@ -1,5 +1,5 @@
 AM_CFLAGS += -I$(abs_top_srcdir)/src/include -g -ggdb -O0 
-TEST_LDADD = $(abs_top_builddir)/libblade.la
+TEST_LDADD = $(abs_top_builddir)/libblade.la -lconfig -lm -lpthread
 check_PROGRAMS =
 
 check_PROGRAMS += testbuild
diff --git a/libs/libblade/test/bladec b/libs/libblade/test/bladec
new file mode 100755
index 0000000000..805d6501b3
--- /dev/null
+++ b/libs/libblade/test/bladec
@@ -0,0 +1,228 @@
+#! /bin/bash
+
+# bladec - temporary wrapper script for .libs/bladec
+# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1.11
+#
+# The bladec program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command="(cd /usr/src/freeswitch/libs/libblade/test; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/usr/lib/ccache:/usr/lib/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:/usr/local/bin:/usr/local/sbin:/usr/local/freeswitch/bin:/opt/bin:/usr/local/bin:/usr/local/sbin:/usr/local/freeswitch/bin; export PATH; gcc -fPIC -Wall -std=c99 -pedantic -DUSE_SCHED_SETSCHEDULER=1 -DKS_API_VISIBILITY=1 -fvisibility=hidden -Werror -DHAVE_PTHREAD_SETSCHEDPARAM=1 -DHAVE_OPENSSL -fsanitize=address -fno-omit-frame-pointer -I/usr/src/freeswitch/libs/libblade/src/include -g -ggdb -O0 -g -O2 -fsanitize=address -o \$progdir/\$file bladec-bladec.o bladec-tap.o  -L/usr/src/freeswitch/libs/libblade/../libks/.libs/ /usr/src/freeswitch/libs/libblade/../libks/.libs//libks.so -lsodium /usr/src/freeswitch/libs/libblade/.libs/libblade.so -lconfig -lm -lpthread -lssl -lcrypto -Wl,-rpath -Wl,/usr/src/freeswitch/libs/libblade/../libks/.libs/ -Wl,-rpath -Wl,/usr/src/freeswitch/libs/libblade/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='2.4.2'
+  notinst_deplibs=' /usr/src/freeswitch/libs/libblade/../libks/.libs//libks.la /usr/src/freeswitch/libs/libblade/libblade.la'
+else
+  # When we are sourced in execute mode, $file and $ECHO are already set.
+  if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+    file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+    ECHO="printf %s\\n"
+  fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+  lt_script_arg0=$0
+  shift
+  for lt_opt
+  do
+    case "$lt_opt" in
+    --lt-debug) lt_option_debug=1 ;;
+    --lt-dump-script)
+        lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
+        test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+        lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'`
+        cat "$lt_dump_D/$lt_dump_F"
+        exit 0
+      ;;
+    --lt-*)
+        $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+        exit 1
+      ;;
+    esac
+  done
+
+  # Print the debug banner immediately:
+  if test -n "$lt_option_debug"; then
+    echo "bladec:bladec:${LINENO}: libtool wrapper (GNU libtool) 2.4.2 Debian-2.4.2-1.11" 1>&2
+  fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+  lt_dump_args_N=1;
+  for lt_arg
+  do
+    $ECHO "bladec:bladec:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
+    lt_dump_args_N=`expr $lt_dump_args_N + 1`
+  done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+      if test -n "$lt_option_debug"; then
+        $ECHO "bladec:bladec:${LINENO}: newargv[0]: $progdir/$program" 1>&2
+        func_lt_dump_args ${1+"$@"} 1>&2
+      fi
+      exec "$progdir/$program" ${1+"$@"}
+
+      $ECHO "$0: cannot exec $program $*" 1>&2
+      exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+  case " $* " in
+  *\ --lt-*)
+    for lt_wr_arg
+    do
+      case $lt_wr_arg in
+      --lt-*) ;;
+      *) set x "$@" "$lt_wr_arg"; shift;;
+      esac
+      shift
+    done ;;
+  esac
+  func_exec_program_core ${1+"$@"}
+}
+
+  # Parse options
+  func_parse_lt_options "$0" ${1+"$@"}
+
+  # Find the directory that this script lives in.
+  thisdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+  test "x$thisdir" = "x$file" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+  while test -n "$file"; do
+    destdir=`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+
+    # If there was a directory component, then change thisdir.
+    if test "x$destdir" != "x$file"; then
+      case "$destdir" in
+      [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+      *) thisdir="$thisdir/$destdir" ;;
+      esac
+    fi
+
+    file=`$ECHO "$file" | /bin/sed 's%^.*/%%'`
+    file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+  if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+    # special case for '.'
+    if test "$thisdir" = "."; then
+      thisdir=`pwd`
+    fi
+    # remove .libs from thisdir
+    case "$thisdir" in
+    *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;;
+    .libs )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=`cd "$thisdir" && pwd`
+  test -n "$absdir" && thisdir="$absdir"
+
+  program=lt-'bladec'
+  progdir="$thisdir/.libs"
+
+  if test ! -f "$progdir/$program" ||
+     { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
+       test "X$file" != "X$progdir/$program"; }; then
+
+    file="$$-$program"
+
+    if test ! -d "$progdir"; then
+      mkdir "$progdir"
+    else
+      rm -f "$progdir/$file"
+    fi
+
+    # relink executable if necessary
+    if test -n "$relink_command"; then
+      if relink_command_output=`eval $relink_command 2>&1`; then :
+      else
+	printf %s\n "$relink_command_output" >&2
+	rm -f "$progdir/$file"
+	exit 1
+      fi
+    fi
+
+    mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+    { rm -f "$progdir/$program";
+      mv -f "$progdir/$file" "$progdir/$program"; }
+    rm -f "$progdir/$file"
+  fi
+
+  if test -f "$progdir/$program"; then
+    if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+      # Run the actual program with our arguments.
+      func_exec_program ${1+"$@"}
+    fi
+  else
+    # The program doesn't exist.
+    $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+    $ECHO "This script is just a wrapper for $program." 1>&2
+    $ECHO "See the libtool documentation for more information." 1>&2
+    exit 1
+  fi
+fi
diff --git a/libs/libblade/test/bladec.c b/libs/libblade/test/bladec.c
index 09e821edc2..aadfed612e 100644
--- a/libs/libblade/test/bladec.c
+++ b/libs/libblade/test/bladec.c
@@ -16,6 +16,7 @@ char g_console_input[CONSOLE_INPUT_MAX];
 size_t g_console_input_length = 0;
 size_t g_console_input_eol = 0;
 
+void service_peer_state_callback(blade_service_t *service, blade_peer_t *peer, blade_peerstate_t state);
 void loop(blade_handle_t *bh);
 void process_console_input(blade_handle_t *bh, char *line);
 
@@ -40,10 +41,11 @@ static const struct command_def_s command_defs[] = {
 	{ NULL, NULL }
 };
 
-
 int main(int argc, char **argv)
 {
 	blade_handle_t *bh = NULL;
+	config_t config;
+	config_setting_t *config_blade = NULL;
 
 	ks_global_set_default_logger(KS_LOG_LEVEL_DEBUG);
 	
@@ -51,8 +53,31 @@ int main(int argc, char **argv)
 
 	blade_handle_create(&bh, NULL, NULL);
 
-	loop(bh);
+	// @todo load config file, and lookup "blade" setting to put into config_blade
+	config_init(&config);
+	if (!config_read_file(&config, "bladec.cfg")) {
+		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, service_peer_state_callback) != KS_STATUS_SUCCESS) {
+		ks_log(KS_LOG_ERROR, "Blade startup failed\n");
+		return EXIT_FAILURE;
+	}
+
+	loop(bh);
+
 	blade_handle_destroy(&bh);
 
 	blade_shutdown();
@@ -60,6 +85,12 @@ int main(int argc, char **argv)
 	return 0;
 }
 
+void service_peer_state_callback(blade_service_t *service, blade_peer_t *peer, blade_peerstate_t state)
+{
+	// @todo log output and pop peer messages if state == BLADE_PEERSTATE_RECEIVING
+	ks_log(KS_LOG_INFO, "service peer state callback: %d\n", (int)state);
+}
+		
 void buffer_console_input(void)
 {
 	ssize_t bytes = 0;
@@ -110,7 +141,6 @@ void loop(blade_handle_t *bh)
 			// @todo lines must not exceed 512 bytes, treat as error and ignore buffer until next new line?
 			ks_assert(0);
 		}
-		blade_handle_pulse(bh);
 	}
 }
 
@@ -175,8 +205,6 @@ void command_store(blade_handle_t *bh, char *args)
 
 	ks_assert(args);
 
-	blade_handle_datastore_startup(bh, NULL);
-	
 	parse_argument(&args, &key, ' ');
 	parse_argument(&args, &data, ' ');
 
@@ -195,8 +223,6 @@ void command_fetch(blade_handle_t *bh, char *args)
 
 	ks_assert(args);
 
-	blade_handle_datastore_startup(bh, NULL);
-	
 	parse_argument(&args, &key, ' ');
 
 	blade_handle_datastore_fetch(bh, blade_datastore_fetch_callback, key, strlen(key), bh);
diff --git a/libs/libblade/test/bladec.cfg b/libs/libblade/test/bladec.cfg
new file mode 100644
index 0000000000..a14a4e7f7a
--- /dev/null
+++ b/libs/libblade/test/bladec.cfg
@@ -0,0 +1,50 @@
+blade:
+{
+    # client stuff, for peers who connect out to services
+    client:
+    {
+        directory:
+        {
+            # todo: hints for ways to find a directory service, at least kws client_data for now
+            # add DNS SRV in the future
+            uri = "???:127.0.0.1+2100:???"; # todo: confirm expected format, "uri:host:proto"
+
+            websocket:
+            {
+                # SSL group is optional, disabled when absent
+                ssl:
+                {
+                    # todo: client SSL stuffs here
+                };
+            };
+        };
+    };
+
+
+    # server stuff, for services that peers connect to
+    # todo: consider encapsulating in a "server" group for organizational structure
+    datastore:
+    {
+        database:
+        {
+            path = ":mem:";
+        };
+    };
+    service:
+    {
+        websockets:
+        {
+            endpoints:
+            {
+                ipv4 = ( { address = "0.0.0.0", port = 2100 } );
+                ipv6 = ( { address = "::", port = 2100 } );
+                backlog = 128;
+            };
+            # SSL group is optional, disabled when absent
+            ssl:
+            {
+                # todo: service SSL stuffs here
+            };
+        };
+    };
+};
diff --git a/libs/libks/src/include/simclist.h b/libs/libks/src/include/simclist.h
index d22587df33..90cdd0cead 100755
--- a/libs/libks/src/include/simclist.h
+++ b/libs/libks/src/include/simclist.h
@@ -27,6 +27,7 @@
 extern "C" {
 #endif
 
+#include <ks.h>
 #include <inttypes.h>
 #include <errno.h>
 #include <sys/types.h>
@@ -209,7 +210,7 @@ extern "C" {
 	 * @param l     must point to a user-provided memory location
 	 * @return      0 for success. -1 for failure
 	 */
-	int list_init(list_t *restrict l);
+	KS_DECLARE(int) list_init(list_t *restrict l);
 
 	/**
 	 * completely remove the list from memory.
@@ -220,7 +221,7 @@ extern "C" {
 	 *
 	 * @param l     list to destroy
 	 */
-	void list_destroy(list_t *restrict l);
+	KS_DECLARE(void) list_destroy(list_t *restrict l);
 
 	/**
 	 * set the comparator function for list elements.
@@ -234,7 +235,7 @@ extern "C" {
 	 *
 	 * @see element_comparator()
 	 */
-	int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun);
+	KS_DECLARE(int) list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun);
 
 	/**
 	 * set a seeker function for list elements.
@@ -248,7 +249,7 @@ extern "C" {
 	 *
 	 * @see element_seeker()
 	 */
-	int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun);
+	KS_DECLARE(int) list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun);
 
 	/**
 	 * require to free element data when list entry is removed (default: don't free).
@@ -280,7 +281,7 @@ extern "C" {
 	 * @see list_meter_double()
 	 * @see list_meter_string()
 	 */
-	int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data);
+	KS_DECLARE(int) list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data);
 
 	/**
 	 * set the element hash computing function for the list elements.
@@ -300,7 +301,7 @@ extern "C" {
 	 *
 	 * @see element_hash_computer()
 	 */
-	int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun);
+	KS_DECLARE(int) list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun);
 
 	/**
 	 * set the element serializer function for the list elements.
@@ -321,7 +322,7 @@ extern "C" {
 	 * @see     list_dump_filedescriptor()
 	 * @see     list_restore_filedescriptor()
 	 */
-	int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun);
+	KS_DECLARE(int) list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun);
 
 	/**
 	 * set the element unserializer function for the list elements.
@@ -343,7 +344,7 @@ extern "C" {
 	 * @see     list_dump_filedescriptor()
 	 * @see     list_restore_filedescriptor()
 	 */
-	int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun);
+	KS_DECLARE(int) list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun);
 
 	/**
 	 * append data at the end of the list.
@@ -355,7 +356,7 @@ extern "C" {
 	 *
 	 * @return      1 for success. < 0 for failure
 	 */
-	int list_append(list_t *restrict l, const void *data);
+	KS_DECLARE(int) list_append(list_t *restrict l, const void *data);
 
 	/**
 	 * insert data in the head of the list.
@@ -367,7 +368,7 @@ extern "C" {
 	 *
 	 * @return      1 for success. < 0 for failure
 	 */
-	int list_prepend(list_t *restrict l, const void *restrict data);
+	KS_DECLARE(int) list_prepend(list_t *restrict l, const void *restrict data);
 
 	/**
 	 * extract the element in the top of the list.
@@ -377,7 +378,7 @@ extern "C" {
 	 * @param l     list to operate
 	 * @return      reference to user datum, or NULL on errors
 	 */
-	void *list_fetch(list_t *restrict l);
+	KS_DECLARE(void *) list_fetch(list_t *restrict l);
 
 	/**
 	 * retrieve an element at a given position.
@@ -386,7 +387,7 @@ extern "C" {
 	 * @param pos   [0,size-1] position index of the element wanted
 	 * @return      reference to user datum, or NULL on errors
 	 */
-	void *list_get_at(const list_t *restrict l, unsigned int pos);
+	KS_DECLARE(void *) list_get_at(const list_t *restrict l, unsigned int pos);
 
 	/**
 	 * return the maximum element of the list.
@@ -400,7 +401,7 @@ extern "C" {
 	 * @param l     list to operate
 	 * @return      the reference to the element, or NULL
 	 */
-	void *list_get_max(const list_t *restrict l);
+	KS_DECLARE(void *) list_get_max(const list_t *restrict l);
 
 	/**
 	 * return the minimum element of the list.
@@ -414,7 +415,7 @@ extern "C" {
 	 * @param l     list to operate
 	 * @return      the reference to the element, or NULL
 	 */
-	void *list_get_min(const list_t *restrict l);
+	KS_DECLARE(void *) list_get_min(const list_t *restrict l);
 
 	/**
 	 * retrieve and remove from list an element at a given position.
@@ -423,7 +424,7 @@ extern "C" {
 	 * @param pos   [0,size-1] position index of the element wanted
 	 * @return      reference to user datum, or NULL on errors
 	 */
-	void *list_extract_at(list_t *restrict l, unsigned int pos);
+	KS_DECLARE(void *) list_extract_at(list_t *restrict l, unsigned int pos);
 
 	/**
 	 * insert an element at a given position.
@@ -433,7 +434,7 @@ extern "C" {
 	 * @param pos   [0,size-1] position index to insert the element at
 	 * @return      positive value on success. Negative on failure
 	 */
-	int list_insert_at(list_t *restrict l, const void *data, unsigned int pos);
+	KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned int pos);
 
 	/**
 	 * expunge the first found given element from the list.
@@ -450,7 +451,7 @@ extern "C" {
 	 * @see list_attributes_comparator()
 	 * @see list_delete_at()
 	 */
-	int list_delete(list_t *restrict l, const void *data);
+	KS_DECLARE(int) list_delete(list_t *restrict l, const void *data);
 
 	/**
 	 * expunge an element at a given position from the list.
@@ -459,7 +460,7 @@ extern "C" {
 	 * @param pos   [0,size-1] position index of the element to be deleted
 	 * @return      0 on success. Negative value on failure
 	 */
-	int list_delete_at(list_t *restrict l, unsigned int pos);
+	KS_DECLARE(int) list_delete_at(list_t *restrict l, unsigned int pos);
 
 	/**
 	 * expunge an array of elements from the list, given their position range.
@@ -469,7 +470,7 @@ extern "C" {
 	 * @param posend    [posstart,size-1] position of the last element to be deleted
 	 * @return      the number of elements successfully removed on success, <0 on error
 	 */
-	int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend);
+	KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend);
 
 	/**
 	 * clear all the elements off of the list.
@@ -482,7 +483,7 @@ extern "C" {
 	 * @param l     list to operate
 	 * @return      the number of elements removed on success, <0 on error
 	 */
-	int list_clear(list_t *restrict l);
+	KS_DECLARE(int) list_clear(list_t *restrict l);
 
 	/**
 	 * inspect the number of elements in the list.
@@ -490,7 +491,7 @@ extern "C" {
 	 * @param l     list to operate
 	 * @return      number of elements currently held by the list
 	 */
-	unsigned int list_size(const list_t *restrict l);
+	KS_DECLARE(unsigned int) list_size(const list_t *restrict l);
 
 	/**
 	 * inspect whether the list is empty.
@@ -500,7 +501,7 @@ extern "C" {
 	 * 
 	 * @see list_size()
 	 */
-	int list_empty(const list_t *restrict l);
+	KS_DECLARE(int) list_empty(const list_t *restrict l);
 
 	/**
 	 * find the position of an element in a list.
@@ -519,7 +520,7 @@ extern "C" {
 	 * @see list_attributes_comparator()
 	 * @see list_get_at()
 	 */
-	int list_locate(const list_t *restrict l, const void *data);
+	KS_DECLARE(int) list_locate(const list_t *restrict l, const void *data);
 
 	/**
 	 * returns an element given an indicator.
@@ -534,7 +535,7 @@ extern "C" {
 	 * @param indicator indicator data to pass to the seeker along with elements
 	 * @return      reference to the element accepted by the seeker, or NULL if none found
 	 */
-	void *list_seek(list_t *restrict l, const void *indicator);
+	KS_DECLARE(void *) list_seek(list_t *restrict l, const void *indicator);
 
 	/**
 	 * inspect whether some data is member of the list.
@@ -555,7 +556,7 @@ extern "C" {
 	 *
 	 * @see list_attributes_comparator()
 	 */
-	int list_contains(const list_t *restrict l, const void *data);
+	KS_DECLARE(int) list_contains(const list_t *restrict l, const void *data);
 
 	/**
 	 * concatenate two lists
@@ -574,7 +575,7 @@ extern "C" {
 	 * @param dest  reference to the destination list
 	 * @return      0 for success, -1 for errors
 	 */
-	int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest);
+	KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest);
 
 	/**
 	 * sort list elements.
@@ -591,7 +592,7 @@ extern "C" {
 	 *
 	 * @see list_attributes_comparator()
 	 */
-	int list_sort(list_t *restrict l, int versus);
+	KS_DECLARE(int) list_sort(list_t *restrict l, int versus);
 
 	/**
 	 * start an iteration session.
@@ -603,7 +604,7 @@ extern "C" {
 	 * 
 	 * @see list_iterator_stop()
 	 */
-	int list_iterator_start(list_t *restrict l);
+	KS_DECLARE(int) list_iterator_start(list_t *restrict l);
 
 	/**
 	 * return the next element in the iteration session.
@@ -611,7 +612,7 @@ extern "C" {
 	 * @param l     list to operate
 	 * @return		element datum, or NULL on errors
 	 */
-	void *list_iterator_next(list_t *restrict l);
+	KS_DECLARE(void *) list_iterator_next(list_t *restrict l);
 
 	/**
 	 * inspect whether more elements are available in the iteration session.
@@ -619,7 +620,7 @@ extern "C" {
 	 * @param l     list to operate
 	 * @return      0 iff no more elements are available.
 	 */
-	int list_iterator_hasnext(const list_t *restrict l);
+	KS_DECLARE(int) list_iterator_hasnext(const list_t *restrict l);
 
 	/**
 	 * end an iteration session.
@@ -627,7 +628,7 @@ extern "C" {
 	 * @param l     list to operate
 	 * @return      0 iff the iteration session cannot be stopped
 	 */
-	int list_iterator_stop(list_t *restrict l);
+	KS_DECLARE(int) list_iterator_stop(list_t *restrict l);
 
 	/**
 	 * return the hash of the current status of the list.
@@ -637,7 +638,7 @@ extern "C" {
 	 *
 	 * @return      0 for success; <0 for failure
 	 */
-	int list_hash(const list_t *restrict l, list_hash_t *restrict hash);
+	KS_DECLARE(int) list_hash(const list_t *restrict l, list_hash_t *restrict hash);
 
 #ifndef SIMCLIST_NO_DUMPRESTORE
 	/**
@@ -655,7 +656,7 @@ extern "C" {
 	 *
 	 * @see list_dump_filedescriptor()
 	 */
-	int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info);
+	KS_DECLARE(int) list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info);
 
 	/**
 	 * get meta informations on a list dump on file.
@@ -670,7 +671,7 @@ extern "C" {
 	 *
 	 * @see list_dump_filedescriptor()
 	 */
-	int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info);
+	KS_DECLARE(int) list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info);
 
 	/**
 	 * dump the list into an open, writable file descriptor.
@@ -706,7 +707,7 @@ extern "C" {
 	 * @see list_attributes_copy()
 	 * @see list_attributes_serializer()
 	 */
-	int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len);
+	KS_DECLARE(int) list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len);
 
 	/**
 	 * dump the list to a file name.
@@ -729,7 +730,7 @@ extern "C" {
 	 *
 	 * This function stores a representation of the list 
 	 */
-	int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len);
+	KS_DECLARE(int) list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len);
 
 	/**
 	 * restore the list from an open, readable file descriptor to memory.
@@ -749,7 +750,7 @@ extern "C" {
 	 * @param len   location to store the length of the dump read (bytes), or NULL
 	 * @return      0 if successful; -1 otherwise
 	 */
-	int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len);
+	KS_DECLARE(int) list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len);
 
 	/**
 	 * restore the list from a file name.
@@ -767,7 +768,7 @@ extern "C" {
 	 * @param len       location to store the length of the dump read (bytes), or NULL
 	 * @return          0 if successful; -1 otherwise
 	 */
-	int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *len);
+	KS_DECLARE(int) list_restore_file(list_t *restrict l, const char *restrict filename, size_t *len);
 #endif
 
 	/* ready-made comparators, meters and hash computers */
@@ -776,201 +777,201 @@ extern "C" {
 	 * ready-made comparator for int8_t elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_int8_t (const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_int8_t (const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for int16_t elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_int16_t (const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_int16_t (const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for int32_t elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_int32_t (const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_int32_t (const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for int64_t elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_int64_t (const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_int64_t (const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for uint8_t elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_uint8_t (const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_uint8_t (const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for uint16_t elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_uint16_t (const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_uint16_t (const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for uint32_t elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_uint32_t (const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_uint32_t (const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for uint64_t elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_uint64_t (const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_uint64_t (const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for float elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_float(const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_float(const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for double elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_double(const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_double(const void *a, const void *b);
 
 	/**
 	 * ready-made comparator for string elements.
 	 * @see list_attributes_comparator()
 	 */
-	int list_comparator_string(const void *a, const void *b);
+	KS_DECLARE(int) list_comparator_string(const void *a, const void *b);
 
 	/*          metric functions        */
 	/**
 	 * ready-made metric function for int8_t elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_int8_t (const void *el);
+	KS_DECLARE(size_t) list_meter_int8_t (const void *el);
 
 	/**
 	 * ready-made metric function for int16_t elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_int16_t (const void *el);
+	KS_DECLARE(size_t) list_meter_int16_t (const void *el);
 
 	/**
 	 * ready-made metric function for int32_t elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_int32_t (const void *el);
+	KS_DECLARE(size_t) list_meter_int32_t (const void *el);
 
 	/**
 	 * ready-made metric function for int64_t elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_int64_t (const void *el);
+	KS_DECLARE(size_t) list_meter_int64_t (const void *el);
 
 	/**
 	 * ready-made metric function for uint8_t elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_uint8_t (const void *el);
+	KS_DECLARE(size_t) list_meter_uint8_t (const void *el);
 
 	/**
 	 * ready-made metric function for uint16_t elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_uint16_t (const void *el);
+	KS_DECLARE(size_t) list_meter_uint16_t (const void *el);
 
 	/**
 	 * ready-made metric function for uint32_t elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_uint32_t (const void *el);
+	KS_DECLARE(size_t) list_meter_uint32_t (const void *el);
 
 	/**
 	 * ready-made metric function for uint64_t elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_uint64_t (const void *el);
+	KS_DECLARE(size_t) list_meter_uint64_t (const void *el);
 
 	/**
 	 * ready-made metric function for float elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_float(const void *el);
+	KS_DECLARE(size_t) list_meter_float(const void *el);
 
 	/**
 	 * ready-made metric function for double elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_double(const void *el);
+	KS_DECLARE(size_t) list_meter_double(const void *el);
 
 	/**
 	 * ready-made metric function for string elements.
 	 * @see list_attributes_copy()
 	 */
-	size_t list_meter_string(const void *el);
+	KS_DECLARE(size_t) list_meter_string(const void *el);
 
 	/*          hash functions          */
 	/**
 	 * ready-made hash function for int8_t elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_int8_t(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_int8_t(const void *el);
 
 	/**
 	 * ready-made hash function for int16_t elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_int16_t(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_int16_t(const void *el);
 
 	/**
 	 * ready-made hash function for int32_t elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_int32_t(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_int32_t(const void *el);
 
 	/**
 	 * ready-made hash function for int64_t elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_int64_t(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_int64_t(const void *el);
 
 	/**
 	 * ready-made hash function for uint8_t elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_uint8_t(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_uint8_t(const void *el);
 
 	/**
 	 * ready-made hash function for uint16_t elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_uint16_t(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_uint16_t(const void *el);
 
 	/**
 	 * ready-made hash function for uint32_t elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_uint32_t(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_uint32_t(const void *el);
 
 	/**
 	 * ready-made hash function for uint64_t elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_uint64_t(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_uint64_t(const void *el);
 
 	/**
 	 * ready-made hash function for float elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_float(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_float(const void *el);
 
 	/**
 	 * ready-made hash function for double elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_double(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_double(const void *el);
 
 	/**
 	 * ready-made hash function for string elements.
 	 * @see list_attributes_hash_computer()
 	 */
-	list_hash_t list_hashcomputer_string(const void *el);
+	KS_DECLARE(list_hash_t) list_hashcomputer_string(const void *el);
 
 #ifdef __cplusplus
 }
diff --git a/libs/libks/src/ks_socket.c b/libs/libks/src/ks_socket.c
index 1696437924..5c951ea956 100644
--- a/libs/libks/src/ks_socket.c
+++ b/libs/libks/src/ks_socket.c
@@ -121,6 +121,15 @@ KS_DECLARE(ks_status_t) ks_socket_option(ks_socket_t socket, int option_name, ks
 #endif
 		}
 		break;
+	case IPV6_V6ONLY:
+#ifdef WIN32
+#warning make sure windows works like linux for IPV6 to IPV4 automapping stuff
+		result = setsockopt(socket, SOL_IPV6, IPV6_V6ONLY, (char *)&opt, sizeof(opt));
+#else
+		result = setsockopt(socket, SOL_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
+#endif
+		if (!result) status = KS_STATUS_SUCCESS;
+		break;
 	default:
 		break;
 	}
diff --git a/libs/libks/src/simclist.c b/libs/libks/src/simclist.c
index e132022260..0f9885af56 100755
--- a/libs/libks/src/simclist.c
+++ b/libs/libks/src/simclist.c
@@ -268,7 +268,7 @@ static inline long get_random(void)
 
 
 /* list initialization */
-int list_init(list_t *restrict l)
+KS_DECLARE(int) list_init(list_t *restrict l)
 {
 	if (l == NULL)
 		return -1;
@@ -306,7 +306,7 @@ int list_init(list_t *restrict l)
 	return 0;
 }
 
-void list_destroy(list_t *restrict l)
+KS_DECLARE(void) list_destroy(list_t *restrict l)
 {
 	unsigned int i;
 
@@ -340,7 +340,7 @@ int list_attributes_setdefaults(list_t *restrict l)
 }
 
 /* setting list properties */
-int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun)
+KS_DECLARE(int) list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun)
 {
 	if (l == NULL)
 		return -1;
@@ -352,7 +352,7 @@ int list_attributes_comparator(list_t *restrict l, element_comparator comparator
 	return 0;
 }
 
-int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun)
+KS_DECLARE(int) list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun)
 {
 	if (l == NULL)
 		return -1;
@@ -363,7 +363,7 @@ int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun)
 	return 0;
 }
 
-int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data)
+KS_DECLARE(int) list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data)
 {
 	if (l == NULL || (metric_fun == NULL && copy_data != 0))
 		return -1;
@@ -376,7 +376,7 @@ int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_
 	return 0;
 }
 
-int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun)
+KS_DECLARE(int) list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun)
 {
 	if (l == NULL)
 		return -1;
@@ -386,7 +386,7 @@ int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash
 	return 0;
 }
 
-int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun)
+KS_DECLARE(int) list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun)
 {
 	if (l == NULL)
 		return -1;
@@ -396,7 +396,7 @@ int list_attributes_serializer(list_t *restrict l, element_serializer serializer
 	return 0;
 }
 
-int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun)
+KS_DECLARE(int) list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun)
 {
 	if (l == NULL)
 		return -1;
@@ -406,22 +406,22 @@ int list_attributes_unserializer(list_t *restrict l, element_unserializer unseri
 	return 0;
 }
 
-int list_append(list_t *restrict l, const void *data)
+KS_DECLARE(int) list_append(list_t *restrict l, const void *data)
 {
 	return list_insert_at(l, data, l->numels);
 }
 
-int list_prepend(list_t *restrict l, const void *data)
+KS_DECLARE(int) list_prepend(list_t *restrict l, const void *data)
 {
 	return list_insert_at(l, data, 0);
 }
 
-void *list_fetch(list_t *restrict l)
+KS_DECLARE(void *) list_fetch(list_t *restrict l)
 {
 	return list_extract_at(l, 0);
 }
 
-void *list_get_at(const list_t *restrict l, unsigned int pos)
+KS_DECLARE(void *) list_get_at(const list_t *restrict l, unsigned int pos)
 {
 	struct list_entry_s *tmp;
 
@@ -430,12 +430,12 @@ void *list_get_at(const list_t *restrict l, unsigned int pos)
 	return (tmp != NULL ? tmp->data : NULL);
 }
 
-void *list_get_max(const list_t *restrict l)
+KS_DECLARE(void *) list_get_max(const list_t *restrict l)
 {
 	return list_get_minmax(l, +1);
 }
 
-void *list_get_min(const list_t *restrict l)
+KS_DECLARE(void *) list_get_min(const list_t *restrict l)
 {
 	return list_get_minmax(l, -1);
 }
@@ -488,7 +488,7 @@ static inline struct list_entry_s *list_findpos(const list_t *restrict l, int po
 	return ptr;
 }
 
-void *list_extract_at(list_t *restrict l, unsigned int pos)
+KS_DECLARE(void *) list_extract_at(list_t *restrict l, unsigned int pos)
 {
 	struct list_entry_s *tmp;
 	void *data;
@@ -508,7 +508,7 @@ void *list_extract_at(list_t *restrict l, unsigned int pos)
 	return data;
 }
 
-int list_insert_at(list_t *restrict l, const void *data, unsigned int pos)
+KS_DECLARE(int) list_insert_at(list_t *restrict l, const void *data, unsigned int pos)
 {
 	struct list_entry_s *lent, *succ, *prec;
 
@@ -561,7 +561,7 @@ int list_insert_at(list_t *restrict l, const void *data, unsigned int pos)
 	return 1;
 }
 
-int list_delete(list_t *restrict l, const void *data)
+KS_DECLARE(int) list_delete(list_t *restrict l, const void *data)
 {
 	int pos, r;
 
@@ -578,7 +578,7 @@ int list_delete(list_t *restrict l, const void *data)
 	return 0;
 }
 
-int list_delete_at(list_t *restrict l, unsigned int pos)
+KS_DECLARE(int) list_delete_at(list_t *restrict l, unsigned int pos)
 {
 	struct list_entry_s *delendo;
 
@@ -598,7 +598,7 @@ int list_delete_at(list_t *restrict l, unsigned int pos)
 	return 0;
 }
 
-int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend)
+KS_DECLARE(int) list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend)
 {
 	struct list_entry_s *lastvalid, *tmp, *tmp2;
 	unsigned int numdel, midposafter, i;
@@ -665,7 +665,7 @@ int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int po
 	return numdel;
 }
 
-int list_clear(list_t *restrict l)
+KS_DECLARE(int) list_clear(list_t *restrict l)
 {
 	struct list_entry_s *s;
 	unsigned int numels;
@@ -715,17 +715,17 @@ int list_clear(list_t *restrict l)
 	return numels;
 }
 
-unsigned int list_size(const list_t *restrict l)
+KS_DECLARE(unsigned int) list_size(const list_t *restrict l)
 {
 	return l->numels;
 }
 
-int list_empty(const list_t *restrict l)
+KS_DECLARE(int) list_empty(const list_t *restrict l)
 {
 	return (l->numels == 0);
 }
 
-int list_locate(const list_t *restrict l, const void *data)
+KS_DECLARE(int) list_locate(const list_t *restrict l, const void *data)
 {
 	struct list_entry_s *el;
 	int pos = 0;
@@ -749,7 +749,7 @@ int list_locate(const list_t *restrict l, const void *data)
 	return pos;
 }
 
-void *list_seek(list_t *restrict l, const void *indicator)
+KS_DECLARE(void *) list_seek(list_t *restrict l, const void *indicator)
 {
 	const struct list_entry_s *iter;
 
@@ -764,12 +764,12 @@ void *list_seek(list_t *restrict l, const void *indicator)
 	return NULL;
 }
 
-int list_contains(const list_t *restrict l, const void *data)
+KS_DECLARE(int) list_contains(const list_t *restrict l, const void *data)
 {
 	return (list_locate(l, data) >= 0);
 }
 
-int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest)
+KS_DECLARE(int) list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest)
 {
 	struct list_entry_s *el, *srcel;
 	unsigned int cnt;
@@ -825,7 +825,7 @@ int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest)
 	return 0;
 }
 
-int list_sort(list_t *restrict l, int versus)
+KS_DECLARE(int) list_sort(list_t *restrict l, int versus)
 {
 	if (l->iter_active || l->attrs.comparator == NULL)	/* cannot modify list in the middle of an iteration */
 		return -1;
@@ -1005,7 +1005,7 @@ static void list_sort_quicksort(list_t *restrict l, int versus, unsigned int fir
 #endif
 }
 
-int list_iterator_start(list_t *restrict l)
+KS_DECLARE(int) list_iterator_start(list_t *restrict l)
 {
 	if (l->iter_active)
 		return 0;
@@ -1015,7 +1015,7 @@ int list_iterator_start(list_t *restrict l)
 	return 1;
 }
 
-void *list_iterator_next(list_t *restrict l)
+KS_DECLARE(void *) list_iterator_next(list_t *restrict l)
 {
 	void *toret;
 
@@ -1029,14 +1029,14 @@ void *list_iterator_next(list_t *restrict l)
 	return toret;
 }
 
-int list_iterator_hasnext(const list_t *restrict l)
+KS_DECLARE(int) list_iterator_hasnext(const list_t *restrict l)
 {
 	if (!l->iter_active)
 		return 0;
 	return (l->iter_pos < l->numels);
 }
 
-int list_iterator_stop(list_t *restrict l)
+KS_DECLARE(int) list_iterator_stop(list_t *restrict l)
 {
 	if (!l->iter_active)
 		return 0;
@@ -1045,7 +1045,7 @@ int list_iterator_stop(list_t *restrict l)
 	return 1;
 }
 
-int list_hash(const list_t *restrict l, list_hash_t *restrict hash)
+KS_DECLARE(int) list_hash(const list_t *restrict l, list_hash_t *restrict hash)
 {
 	struct list_entry_s *x;
 	list_hash_t tmphash;
@@ -1083,7 +1083,7 @@ int list_hash(const list_t *restrict l, list_hash_t *restrict hash)
 }
 
 #ifndef SIMCLIST_NO_DUMPRESTORE
-int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info)
+KS_DECLARE(int) list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info)
 {
 	int32_t terminator_head, terminator_tail;
 	uint32_t elemlen;
@@ -1148,7 +1148,7 @@ int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info)
 	return 0;
 }
 
-int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info)
+KS_DECLARE(int) list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info)
 {
 	int fd, ret;
 
@@ -1162,7 +1162,7 @@ int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *rest
 	return ret;
 }
 
-int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len)
+KS_DECLARE(int) list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len)
 {
 	struct list_entry_s *x;
 	void *ser_buf;
@@ -1311,7 +1311,7 @@ int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict
 	return 0;
 }
 
-int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len)
+KS_DECLARE(int) list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len)
 {
 	struct list_dump_header_s header;
 	unsigned long cnt;
@@ -1436,7 +1436,7 @@ int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len
 	return 0;
 }
 
-int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len)
+KS_DECLARE(int) list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len)
 {
 	int fd, oflag, mode;
 
@@ -1457,7 +1457,7 @@ int list_dump_file(const list_t *restrict l, const char *restrict filename, size
 	return 0;
 }
 
-int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *restrict len)
+KS_DECLARE(int) list_restore_file(list_t *restrict l, const char *restrict filename, size_t *restrict len)
 {
 	int fd;
 
@@ -1507,38 +1507,38 @@ static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned
 }
 
 /* ready-made comparators and meters */
-#define SIMCLIST_NUMBER_COMPARATOR(type)     int list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); }
+#define SIMCLIST_NUMBER_COMPARATOR(type)     KS_DECLARE(int) list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); }
 
 SIMCLIST_NUMBER_COMPARATOR(int8_t)
 SIMCLIST_NUMBER_COMPARATOR(int16_t) SIMCLIST_NUMBER_COMPARATOR(int32_t) SIMCLIST_NUMBER_COMPARATOR(int64_t)
  SIMCLIST_NUMBER_COMPARATOR(uint8_t) SIMCLIST_NUMBER_COMPARATOR(uint16_t) SIMCLIST_NUMBER_COMPARATOR(uint32_t) SIMCLIST_NUMBER_COMPARATOR(uint64_t)
  SIMCLIST_NUMBER_COMPARATOR(float) SIMCLIST_NUMBER_COMPARATOR(double)
 
-	 int list_comparator_string(const void *a, const void *b)
+KS_DECLARE(int) list_comparator_string(const void *a, const void *b)
 {
 	return strcmp((const char *) b, (const char *) a);
 }
 
 /* ready-made metric functions */
-#define SIMCLIST_METER(type)        size_t list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); }
+#define SIMCLIST_METER(type)        KS_DECLARE(size_t) list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); }
 
 SIMCLIST_METER(int8_t) SIMCLIST_METER(int16_t) SIMCLIST_METER(int32_t) SIMCLIST_METER(int64_t)
  SIMCLIST_METER(uint8_t) SIMCLIST_METER(uint16_t) SIMCLIST_METER(uint32_t) SIMCLIST_METER(uint64_t)
  SIMCLIST_METER(float) SIMCLIST_METER(double)
 
-	 size_t list_meter_string(const void *el)
+KS_DECLARE(size_t) list_meter_string(const void *el)
 {
 	return strlen((const char *) el) + 1;
 }
 
 /* ready-made hashing functions */
-#define SIMCLIST_HASHCOMPUTER(type)    list_hash_t list_hashcomputer_##type(const void *el) { return (list_hash_t)(*(type *)el); }
+#define SIMCLIST_HASHCOMPUTER(type)    KS_DECLARE(list_hash_t) list_hashcomputer_##type(const void *el) { return (list_hash_t)(*(type *)el); }
 
 SIMCLIST_HASHCOMPUTER(int8_t) SIMCLIST_HASHCOMPUTER(int16_t) SIMCLIST_HASHCOMPUTER(int32_t) SIMCLIST_HASHCOMPUTER(int64_t)
  SIMCLIST_HASHCOMPUTER(uint8_t) SIMCLIST_HASHCOMPUTER(uint16_t) SIMCLIST_HASHCOMPUTER(uint32_t) SIMCLIST_HASHCOMPUTER(uint64_t)
  SIMCLIST_HASHCOMPUTER(float) SIMCLIST_HASHCOMPUTER(double)
 
-	 list_hash_t list_hashcomputer_string(const void *el)
+KS_DECLARE(list_hash_t) list_hashcomputer_string(const void *el)
 {
 	size_t l;
 	list_hash_t hash = 123;