{"schema":"libjg2-1",
"vpath":"/git/",
"avatar":"/git/avatar/",
"alang":"",
"gen_ut":1746423088,
"reponame":"libwebsockets",
"desc":"libwebsockets lightweight C networking library",
"owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets",
"f":3,
"items": [
{"schema":"libjg2-1",
"cid":"83cb11e1a5b029090988279e0e7fc117",
"commit": {"type":"commit",
"time": 1539389787,
"time_ofs": 480,
"oid_tree": { "oid": "6d9680c75366f9545705667d8501749ef741f3fa", "alias": []},
"oid":{ "oid": "47e10ab20055a267fcb3eaf8662220b4125f00d5", "alias": []},
"msg": "dbus-ws-proxy",
"sig_commit": { "git_time": { "time": 1539389787, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },
"sig_author": { "git_time": { "time": 1538547269, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }},
"body": "dbus-ws-proxy\n\nThis builds on the new dbus role support to provide a minimal example proxy\nbetween ws and dbus.\n\nA client app is provided that asks the proxy to connect to libwebsockets.org\nand proxy the drawing data from the mirror example there back to the dbus\nclient using dbus messages."
,
"diff": "diff --git a/.travis.yml b/.travis.yml\nindex be87f71..c218606 100644\n--- a/.travis.yml\n+++ b/.travis.yml\n@@ -4,8 +4,8 @@ env:\n global:\n - secure: \u0022KhAdQ9ja+LBObWNQTYO7Df5J4DyOih6S+eerDMu8UPSO+CoWV2pWoQzbOfocjyOscGOwC+2PrrHDNZyGfqkCLDXg1BxynXPCFerHC1yc2IajvKpGXmAAygNIvp4KACDfGv/dkXrViqIzr/CdcNaU4vIMHSVb5xkeLi0W1dPnQOI\u003d\u0022\n matrix:\n- - LWS_METHOD\u003dlwsws CMAKE_ARGS\u003d\u0022-DLWS_WITH_LWSWS\u003dON -DLWS_WITHOUT_EXTENSIONS\u003d0 -DLWS_WITH_HTTP2\u003d1 -DLWS_WITH_ACME\u003d1 -DLWS_WITH_MINIMAL_EXAMPLES\u003d1 -DCMAKE_BUILD_TYPE\u003dDEBUG\u0022\n- - LWS_METHOD\u003dlwsws2 CMAKE_ARGS\u003d\u0022-DLWS_WITH_LWSWS\u003dON -DLWS_WITHOUT_EXTENSIONS\u003d0 -DLWS_WITH_HTTP2\u003d1 -DLWS_WITH_ACME\u003d1 -DLWS_WITH_MINIMAL_EXAMPLES\u003d1 -DCMAKE_BUILD_TYPE\u003dDEBUG\u0022\n+ - LWS_METHOD\u003dlwsws CMAKE_ARGS\u003d\u0022-DLWS_WITH_LWSWS\u003dON -DLWS_WITHOUT_EXTENSIONS\u003d0 -DLWS_WITH_HTTP2\u003d1 -DLWS_WITH_ACME\u003d1 -DLWS_WITH_MINIMAL_EXAMPLES\u003d1 -DCMAKE_BUILD_TYPE\u003dDEBUG -DLWS_ROLE_DBUS\u003d1 -DLWS_DBUS_INCLUDE2\u003d/usr/lib/x86_64-linux-gnu/dbus-1.0/include/\u0022\n+ - LWS_METHOD\u003dlwsws2 CMAKE_ARGS\u003d\u0022-DLWS_WITH_LWSWS\u003dON -DLWS_WITHOUT_EXTENSIONS\u003d0 -DLWS_WITH_HTTP2\u003d1 -DLWS_WITH_ACME\u003d1 -DLWS_WITH_MINIMAL_EXAMPLES\u003d1 -DCMAKE_BUILD_TYPE\u003dDEBUG -DLWS_ROLE_DBUS\u003d1 -DLWS_DBUS_INCLUDE2\u003d/usr/lib/x86_64-linux-gnu/dbus-1.0/include/\u0022\n - LWS_METHOD\u003ddefault CMAKE_ARGS\u003d\u0022-DLWS_WITH_MINIMAL_EXAMPLES\u003d1\u0022\n - LWS_METHOD\u003dmbedtls CMAKE_ARGS\u003d\u0022-DLWS_WITH_MBEDTLS\u003d1 -DLWS_WITH_HTTP2\u003d1 -DLWS_WITH_LWSWS\u003d1 -DLWS_WITH_MINIMAL_EXAMPLES\u003d1 -DCMAKE_BUILD_TYPE\u003dDEBUG\u0022\n - LWS_METHOD\u003dnoserver CMAKE_ARGS\u003d\u0022-DLWS_WITHOUT_SERVER\u003dON -DLWS_WITH_MINIMAL_EXAMPLES\u003d1\u0022\ndiff --git a/CMakeLists.txt b/CMakeLists.txt\nindex ba7dac7..8150f82 100644\n--- a/CMakeLists.txt\n+++ b/CMakeLists.txt\n@@ -133,6 +133,12 @@ if(LWS_WITH_DISTRO_RECOMMENDED)\n \tset(LWS_ROLE_DBUS 1)\n endif()\n \n+# do you care about this? Then send me a patch where it disables it on travis\n+# but allows it on APPLE\n+if (APPLE)\n+\tset(LWS_ROLE_DBUS 0)\n+endif()\n+\n if(NOT DEFINED CMAKE_BUILD_TYPE)\n \tset(CMAKE_BUILD_TYPE Release CACHE STRING \u0022Build type\u0022)\n endif()\n@@ -686,15 +692,15 @@ CHECK_INCLUDE_FILE(pthread.h LWS_HAVE_PTHREAD_H)\n CHECK_LIBRARY_EXISTS(cap cap_set_flag \u0022\u0022 LWS_HAVE_LIBCAP)\n \n if (LWS_ROLE_DBUS)\n-\tif (NOT LWS_HAVE_LIBDBUS)\n-\t\tmessage(FATAL_ERROR \u0022Install dbus-devel, or libdbus-1-dev etc\u0022)\n-\tendif()\n \n \tif (NOT LWS_DBUS_LIB)\n \t\tset(LWS_DBUS_LIB \u0022dbus-1\u0022)\n \tendif()\n \n \tCHECK_LIBRARY_EXISTS(${LWS_DBUS_LIB} dbus_connection_set_watch_functions \u0022\u0022 LWS_HAVE_LIBDBUS)\n+\tif (NOT LWS_HAVE_LIBDBUS)\n+\t\tmessage(FATAL_ERROR \u0022Install dbus-devel, or libdbus-1-dev etc\u0022)\n+\tendif()\n \n \tif (NOT LWS_DBUS_INCLUDE1)\n \t\t# look in fedora and debian / ubuntu place\ndiff --git a/minimal-examples/dbus-client/README.md b/minimal-examples/dbus-client/README.md\nindex 7951825..ecde9d1 100644\n--- a/minimal-examples/dbus-client/README.md\n+++ b/minimal-examples/dbus-client/README.md\n@@ -1,4 +1,4 @@\n |Example|Demonstrates|\n ---|---\n minimal-dbus-client|Shows how to connect to a DBusServer dbus server like minimal-dbus-server\n-\n+minimal-dbus-ws-proxy-testclient|A test client for use with minimal-dbus-ws-proxy\ndiff --git a/minimal-examples/dbus-client/minimal-dbus-client/minimal-dbus-client.c b/minimal-examples/dbus-client/minimal-dbus-client/minimal-dbus-client.c\nindex 7e30d13..5b0f2d9 100644\n--- a/minimal-examples/dbus-client/minimal-dbus-client/minimal-dbus-client.c\n+++ b/minimal-examples/dbus-client/minimal-dbus-client/minimal-dbus-client.c\n@@ -40,8 +40,9 @@ client_message_handler(DBusConnection *conn, DBusMessage *message, void *data)\n \t\t dbus_message_get_member(message),\n \t\t dbus_message_get_path(message));\n \n-\tif (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING,\n-\t\t\t\t \u0026str, DBUS_TYPE_INVALID))\n+\tif (!dbus_message_get_args(message, NULL,\n+\t\t\t\t DBUS_TYPE_STRING, \u0026str,\n+\t\t\t\t DBUS_TYPE_INVALID))\n \t\treturn DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n \n \tlwsl_notice(\u0022%s: '%s'\u005cn\u0022, __func__, str);\ndiff --git a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt\nnew file mode 100644\nindex 0000000..dda46bf\n--- /dev/null\n+++ b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/CMakeLists.txt\n@@ -0,0 +1,120 @@\n+cmake_minimum_required(VERSION 2.8)\n+include(CheckCSourceCompiles)\n+include(CheckLibraryExists)\n+\n+set(SAMP lws-minimal-dbus-ws-proxy-testclient)\n+set(SRCS minimal-dbus-ws-proxy-testclient.c)\n+\n+if (NOT LWS_WITH_MINIMAL_EXAMPLES)\n+\tCHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions \u0022\u0022 LWS_HAVE_LIBDBUS)\n+\tif (NOT LWS_HAVE_LIBDBUS)\n+\t\tmessage(FATAL_ERROR \u0022Install dbus-devel, or libdbus-1-dev etc\u0022)\n+\tendif()\n+\n+\tif (NOT LWS_DBUS_LIB)\n+\t\tset(LWS_DBUS_LIB \u0022dbus-1\u0022)\n+\tendif()\n+\n+\tif (NOT LWS_DBUS_INCLUDE1)\n+\t\t# look in fedora and debian / ubuntu place\n+\t\tif (EXISTS \u0022/usr/include/dbus-1.0\u0022)\n+\t\t\tset(LWS_DBUS_INCLUDE1 \u0022/usr/include/dbus-1.0\u0022)\n+\t\telse()\n+\t\t\tmessage(FATAL_ERROR \u0022Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are\u0022)\n+\t\tendif()\n+\tendif()\n+\n+\tif (NOT LWS_DBUS_INCLUDE2)\n+\t\t# look in fedora... debian / ubuntu has the ARCH in the path...\n+\t\tif (EXISTS \u0022/usr/lib64/dbus-1.0/include\u0022)\n+\t\t\tset(LWS_DBUS_INCLUDE2 \u0022/usr/lib64/dbus-1.0/include\u0022)\n+\t\telse()\n+\t\t\tmessage(FATAL_ERROR \u0022Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system\u0022)\n+\t\tendif()\n+\tendif()\n+\n+\tset(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2})\n+\n+\tif (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2)\n+\t\tmessage(FATAL_ERROR \u0022To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md\u0022)\n+\tendif()\n+\n+endif()\n+\n+# If we are being built as part of lws, confirm current build config supports\n+# reqconfig, else skip building ourselves.\n+#\n+# If we are being built externally, confirm installed lws was configured to\n+# support reqconfig, else error out with a helpful message about the problem.\n+#\n+MACRO(require_lws_config reqconfig _val result)\n+\n+\tif (DEFINED ${reqconfig})\n+\tif (${reqconfig})\n+\t\tset (rq 1)\n+\telse()\n+\t\tset (rq 0)\n+\tendif()\n+\telse()\n+\t\tset(rq 0)\n+\tendif()\n+\n+\tif (${_val} EQUAL ${rq})\n+\t\tset(SAME 1)\n+\telse()\n+\t\tset(SAME 0)\n+\tendif()\n+\n+\tif (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})\n+\t\tif (${_val})\n+\t\t\tmessage(\u0022${SAMP}: skipping as lws being built without ${reqconfig}\u0022)\n+\t\telse()\n+\t\t\tmessage(\u0022${SAMP}: skipping as lws built with ${reqconfig}\u0022)\n+\t\tendif()\n+\t\tset(${result} 0)\n+\telse()\n+\t\tif (LWS_WITH_MINIMAL_EXAMPLES)\n+\t\t\tset(MET ${SAME})\n+\t\telse()\n+\t\t\tCHECK_C_SOURCE_COMPILES(\u0022#include \u003clibwebsockets.h\u003e\u005cnint main(void) {\u005cn#if defined(${reqconfig})\u005cn return 0;\u005cn#else\u005cn fail;\u005cn#endif\u005cn return 0;\u005cn}\u005cn\u0022 HAS_${reqconfig})\n+\t\t\tif (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})\n+\t\t\t\tset(HAS_${reqconfig} 0)\n+\t\t\telse()\n+\t\t\t\tset(HAS_${reqconfig} 1)\n+\t\t\tendif()\n+\t\t\tif ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))\n+\t\t\t\tset(MET 1)\n+\t\t\telse()\n+\t\t\t\tset(MET 0)\n+\t\t\tendif()\n+\t\tendif()\n+\t\tif (NOT MET)\n+\t\t\tif (${_val})\n+\t\t\t\tmessage(FATAL_ERROR \u0022This project requires lws must have been configured with ${reqconfig}\u0022)\n+\t\t\telse()\n+\t\t\t\tmessage(FATAL_ERROR \u0022Lws configuration of ${reqconfig} is incompatible with this project\u0022)\n+\t\t\tendif()\n+\t\tendif()\n+\n+\tendif()\n+ENDMACRO()\n+\n+\n+set(requirements 1)\n+require_lws_config(LWS_ROLE_DBUS 1 requirements)\n+require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)\n+\n+if (requirements)\n+\tadd_executable(${SAMP} ${SRCS})\n+\t\n+\tinclude_directories(\u0022${LWS_DBUS_INCLUDE1}\u0022)\n+\tinclude_directories(\u0022${LWS_DBUS_INCLUDE2}\u0022)\n+\tlist(APPEND LIB_LIST dbus-1)\n+\n+\tif (websockets_shared)\n+\t\ttarget_link_libraries(${SAMP} websockets_shared)\n+\t\tadd_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB})\n+\telse()\n+\t\ttarget_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB})\n+\tendif()\n+endif()\ndiff --git a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/README.md b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/README.md\nnew file mode 100644\nindex 0000000..1e0dbbf\n--- /dev/null\n+++ b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/README.md\n@@ -0,0 +1,52 @@\n+# lws minimal dbus ws proxy testclient\n+\n+This is a test client used to test `./minimal-examples/dbus-server/minimal-dbus-ws-proxy`\n+\n+It asks the minimal dbus ws proxy application to connect to libwebsockets.org\n+over the mirror protocol. And it proxies back the ASCII packets used to\n+communicate the mirror sample drawing vectors over dbus to this test client\n+if you draw on the mirror example app at https://libwebsockets.org/testserver/\n+in a browser.\n+\n+## build\n+\n+Using libdbus requires additional non-default include paths setting, same as\n+is necessary for lws build described in ./lib/roles/dbus/README.md\n+\n+CMake can guess one path and the library name usually, see the README above\n+for details of how to override for custom libdbus and cross build.\n+\n+Fedora example:\n+```\n+$ cmake .. -DLWS_DBUS_INCLUDE2\u003d\u0022/usr/lib64/dbus-1.0/include\u0022\n+$ make\n+```\n+\n+Ubuntu example:\n+```\n+$ cmake .. -DLWS_DBUS_INCLUDE2\u003d\u0022/usr/lib/x86_64-linux-gnu/dbus-1.0/include\u0022\n+$ make\n+```\n+\n+## usage\n+\n+Commandline option|Meaning\n+---|---\n+-d \u003cloglevel\u003e|Debug verbosity in decimal, eg, -d15\n+\n+This connects to the minimal-dbus-ws-proxy example running in another terminal.\n+\n+```\n+ $ ./lws-minimal-dbus-ws-proxy-testclient\n+[2018/10/05 14:17:16:6286] USER: LWS minimal DBUS ws proxy testclient\n+[2018/10/05 14:17:16:6538] NOTICE: Creating Vhost 'default' port 0, 1 protocols, IPv6 off\n+[2018/10/05 14:17:16:6617] USER: create_dbus_client_conn: connecting to 'unix:abstract\u003dorg.libwebsockets.wsclientproxy'\n+[2018/10/05 14:17:16:7189] NOTICE: create_dbus_client_conn: created OK\n+[2018/10/05 14:17:16:7429] USER: remote_method_call: requesting proxy connection wss://libwebsockets.org/ lws-mirror-protocol\n+[2018/10/05 14:17:17:0387] USER: pending_call_notify: received 'Connecting'\n+[2018/10/05 14:17:18:7475] NOTICE: client_message_handler: (type 7) 'ws client connection established'\n+[2018/10/05 14:17:21:2028] NOTICE: client_message_handler: (type 6) 'd #000000 323 63 323 67;'\n+[2018/10/05 14:17:21:2197] NOTICE: client_message_handler: (type 6) 'd #000000 323 67 327 73;'\n+...\n+```\n+\ndiff --git a/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c\nnew file mode 100644\nindex 0000000..294a556\n--- /dev/null\n+++ b/minimal-examples/dbus-client/minimal-dbus-ws-proxy-testclient/minimal-dbus-ws-proxy-testclient.c\n@@ -0,0 +1,447 @@\n+/*\n+ * lws-minimal-dbus-ws-proxy-testclient\n+ *\n+ * Copyright (C) 2018 Andy Green \u003candy@warmcat.com\u003e\n+ *\n+ * This file is made available under the Creative Commons CC0 1.0\n+ * Universal Public Domain Dedication.\n+ *\n+ * This acts as a test client over DBUS, opening a session with\n+ * minimal-dbus-ws-proxy and sending and receiving data on the libwebsockets\n+ * mirror demo page.\n+ */\n+\n+#include \u003cstdbool.h\u003e\n+#include \u003cstring.h\u003e\n+#include \u003cstdio.h\u003e\n+#include \u003cstdlib.h\u003e\n+#include \u003cunistd.h\u003e\n+#include \u003csignal.h\u003e\n+\n+#include \u003clibwebsockets.h\u003e\n+#include \u003clibwebsockets/lws-dbus.h\u003e\n+\n+/*\n+ * These are the various states our connection can be in, both with regards\n+ * to the direct connection to the proxy, and the state of the onward ws\n+ * connection the proxy opens at our request.\n+ */\n+\n+enum lws_dbus_client_state {\n+\tLDCS_NOTHING,\t\t /* no connection yet */\n+\tLDCS_CONN,\t\t /* conn to proxy */\n+\tLDCS_CONN_WAITING_ONWARD, /* conn to proxy, awaiting proxied conn */\n+\tLDCS_CONN_ONWARD,\t /* conn to proxy and onward conn OK */\n+\tLDCS_CONN_CLOSED,\t /* conn to proxy but onward conn closed */\n+\tLDCS_CLOSED,\t\t /* connection to proxy is closed */\n+};\n+\n+/*\n+ * our expanded dbus context\n+ */\n+\n+struct lws_dbus_ctx_wsproxy_client {\n+\tstruct lws_dbus_ctx ctx;\n+\n+\tenum lws_dbus_client_state state;\n+};\n+\n+static struct lws_dbus_ctx_wsproxy_client *dbus_ctx;\n+static struct lws_context *context;\n+static int interrupted, autoexit_budget \u003d -1, count_rx, count_tx;\n+\n+#define THIS_INTERFACE\t \u0022org.libwebsockets.wsclientproxy\u0022\n+#define THIS_OBJECT\t \u0022/org/libwebsockets/wsclientproxy\u0022\n+#define THIS_BUSNAME\t \u0022org.libwebsockets.wsclientproxy\u0022\n+\n+#define THIS_LISTEN_PATH \u0022unix:abstract\u003dorg.libwebsockets.wsclientproxy\u0022\n+\n+static void\n+state_transition(struct lws_dbus_ctx_wsproxy_client *dcwc,\n+\t\t enum lws_dbus_client_state state)\n+{\n+\tlwsl_notice(\u0022%s: %p: from state %d -\u003e %d\u005cn\u0022, __func__,\n+\t\t dcwc,dcwc-\u003estate, state);\n+\tdcwc-\u003estate \u003d state;\n+}\n+\n+static DBusHandlerResult\n+filter(DBusConnection *conn, DBusMessage *message, void *data)\n+{\n+\tstruct lws_dbus_ctx_wsproxy_client *dcwc \u003d\n+\t\t\t(struct lws_dbus_ctx_wsproxy_client *)data;\n+\tconst char *str;\n+\n+\tif (!dbus_message_get_args(message, NULL,\n+\t\t\t\t DBUS_TYPE_STRING, \u0026str,\n+\t\t\t\t DBUS_TYPE_INVALID))\n+\t\treturn DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n+\n+\t/* received ws data */\n+\n+\tif (dbus_message_is_signal(message, THIS_INTERFACE, \u0022Receive\u0022)) {\n+\t\tlwsl_user(\u0022%s: Received '%s'\u005cn\u0022, __func__, str);\n+\t\tcount_rx++;\n+\t}\n+\n+\t/* proxy ws connection failed */\n+\n+\tif (dbus_message_is_signal(message, THIS_INTERFACE, \u0022Status\u0022) \u0026\u0026\n+\t !strcmp(str, \u0022ws client connection error\u0022))\n+\t\tstate_transition(dcwc, LDCS_CONN_CLOSED);\n+\n+\t/* proxy ws connection succeeded */\n+\n+\tif (dbus_message_is_signal(message, THIS_INTERFACE, \u0022Status\u0022) \u0026\u0026\n+\t !strcmp(str, \u0022ws client connection established\u0022))\n+\t\tstate_transition(dcwc, LDCS_CONN_ONWARD);\n+\n+\t/* proxy ws connection has closed */\n+\n+\tif (dbus_message_is_signal(message, THIS_INTERFACE, \u0022Status\u0022) \u0026\u0026\n+\t !strcmp(str, \u0022ws client connection closed\u0022))\n+\t\tstate_transition(dcwc, LDCS_CONN_CLOSED);\n+\n+\treturn DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n+}\n+\n+static void\n+destroy_dbus_client_conn(struct lws_dbus_ctx_wsproxy_client **pdcwc)\n+{\n+\tstruct lws_dbus_ctx_wsproxy_client *dcwc \u003d *pdcwc;\n+\n+\tif (!dcwc || !dcwc-\u003ectx.conn)\n+\t\treturn;\n+\n+\tlwsl_notice(\u0022%s\u005cn\u0022, __func__);\n+\n+\tdbus_connection_remove_filter(dcwc-\u003ectx.conn, filter, \u0026dcwc-\u003ectx);\n+\tdbus_connection_close(dcwc-\u003ectx.conn);\n+\tdbus_connection_unref(dcwc-\u003ectx.conn);\n+\n+\tfree(dcwc);\n+\n+\t*pdcwc \u003d NULL;\n+}\n+\n+/*\n+ * This callback is coming when lws has noticed the fd took a POLLHUP. The\n+ * ctx has effectively gone out of scope before this, and the connection can\n+ * be cleaned up and the ctx freed.\n+ */\n+\n+static void\n+cb_closing(struct lws_dbus_ctx *ctx)\n+{\n+\tstruct lws_dbus_ctx_wsproxy_client *dcwc \u003d\n+\t\t\t(struct lws_dbus_ctx_wsproxy_client *)ctx;\n+\n+\tlwsl_err(\u0022%s: closing\u005cn\u0022, __func__);\n+\n+\tif (dcwc \u003d\u003d dbus_ctx)\n+\t\tdbus_ctx \u003d NULL;\n+\n+\tdestroy_dbus_client_conn(\u0026dcwc);\n+\n+\tinterrupted \u003d 1;\n+}\n+\n+static struct lws_dbus_ctx_wsproxy_client *\n+create_dbus_client_conn(struct lws_vhost *vh, int tsi, const char *ads)\n+{\n+\tstruct lws_dbus_ctx_wsproxy_client *dcwc;\n+\tDBusError e;\n+\n+\tdcwc \u003d malloc(sizeof(*dcwc));\n+\tif (!dcwc)\n+\t\treturn NULL;\n+\n+\tmemset(dcwc, 0, sizeof(*dcwc));\n+\n+\tdcwc-\u003estate \u003d LDCS_NOTHING;\n+\tdcwc-\u003ectx.vh \u003d vh;\n+\tdcwc-\u003ectx.tsi \u003d tsi;\n+\n+ dbus_error_init(\u0026e);\n+\n+ lwsl_user(\u0022%s: connecting to '%s'\u005cn\u0022, __func__, ads);\n+#if 1\n+\t/* connect to our daemon bus */\n+\n+ dcwc-\u003ectx.conn \u003d dbus_connection_open_private(ads, \u0026e);\n+\tif (!dcwc-\u003ectx.conn) {\n+\t\tlwsl_err(\u0022%s: Failed to connect: %s\u005cn\u0022,\n+\t\t\t __func__, e.message);\n+\t\tgoto fail;\n+\t}\n+#else\n+\t/* connect to the SYSTEM bus */\n+\n+\tdcwc-\u003ectx.conn \u003d dbus_bus_get(DBUS_BUS_SYSTEM, \u0026e);\n+\tif (!dcwc-\u003ectx.conn) {\n+\t\tlwsl_err(\u0022%s: Failed to get a session DBus connection: %s\u005cn\u0022,\n+\t\t\t __func__, e.message);\n+\t\tgoto fail;\n+\t}\n+#endif\n+\tdbus_connection_set_exit_on_disconnect(dcwc-\u003ectx.conn, 0);\n+\n+\tif (!dbus_connection_add_filter(dcwc-\u003ectx.conn, filter,\n+\t\t\t\t\t\u0026dcwc-\u003ectx, NULL)) {\n+\t\tlwsl_err(\u0022%s: Failed to add filter\u005cn\u0022, __func__);\n+\t\tgoto fail;\n+\t}\n+\n+\t/*\n+\t * This is the part that binds the connection to lws watcher and\n+\t * timeout handling provided by lws\n+\t */\n+\n+\tif (lws_dbus_connection_setup(\u0026dcwc-\u003ectx, dcwc-\u003ectx.conn, cb_closing)) {\n+\t\tlwsl_err(\u0022%s: connection bind to lws failed\u005cn\u0022, __func__);\n+\t\tgoto fail;\n+\t}\n+\n+\tstate_transition(dcwc, LDCS_CONN);\n+\n+\tlwsl_notice(\u0022%s: created OK\u005cn\u0022, __func__);\n+\n+\treturn dcwc;\n+\n+fail:\n+\tdbus_error_free(\u0026e);\n+\n+\tfree(dcwc);\n+\n+\treturn NULL;\n+}\n+\n+\n+void sigint_handler(int sig)\n+{\n+\tinterrupted \u003d 1;\n+}\n+\n+/*\n+ * This gets called if we timed out waiting for the dbus server reply, or the\n+ * reply arrived.\n+ */\n+\n+static void\n+pending_call_notify(DBusPendingCall *pending, void *data)\n+{\n+\tconst char *payload;\n+\tDBusMessage *msg;\n+\n+\tif (!dbus_pending_call_get_completed(pending)) {\n+\t\tlwsl_err(\u0022%s: timed out waiting for reply\u005cn\u0022, __func__);\n+\n+\t\tgoto bail;\n+\t}\n+\n+\tmsg \u003d dbus_pending_call_steal_reply(pending);\n+\tif (!msg)\n+\t\tgoto bail;\n+\n+\tif (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, \u0026payload,\n+\t\t\t\t\t DBUS_TYPE_INVALID)) {\n+\t\tgoto bail1;\n+\t}\n+\n+\tlwsl_user(\u0022%s: received '%s'\u005cn\u0022, __func__, payload);\n+\n+bail1:\n+\tdbus_message_unref(msg);\n+bail:\n+\tdbus_pending_call_unref(pending);\n+}\n+\n+static int\n+remote_method_call(struct lws_dbus_ctx_wsproxy_client *dcwc)\n+{\n+\tconst char *uri \u003d \u0022wss://libwebsockets.org/\u0022;\n+\tconst char *subprotocol \u003d \u0022lws-mirror-protocol\u0022;\n+\tDBusMessage *msg;\n+\tint ret \u003d 1;\n+\n+\tmsg \u003d dbus_message_new_method_call(\n+\t\t\t/* dest */\t THIS_BUSNAME,\n+\t\t\t/* object-path */ THIS_OBJECT,\n+\t\t\t/* interface */ THIS_INTERFACE,\n+\t\t\t/* method */\t \u0022Connect\u0022);\n+\tif (!msg)\n+\t\treturn 1;\n+\n+\tif (!dbus_message_append_args(msg, DBUS_TYPE_STRING, \u0026uri,\n+\t\t\t\t\t DBUS_TYPE_STRING, \u0026subprotocol,\n+\t\t\t\t\t DBUS_TYPE_INVALID))\n+\t\tgoto bail;\n+\n+\tlwsl_user(\u0022%s: requesting proxy connection %s %s\u005cn\u0022, __func__,\n+\t\t\turi, subprotocol);\n+\n+\tif (!dbus_connection_send_with_reply(dcwc-\u003ectx.conn, msg, \u0026dcwc-\u003ectx.pc,\n+\t\t\t\t\t DBUS_TIMEOUT_USE_DEFAULT)) {\n+\t\tlwsl_err(\u0022%s: unable to send\u005cn\u0022, __func__);\n+\n+\t\tgoto bail;\n+\t}\n+\n+\tdbus_pending_call_set_notify(dcwc-\u003ectx.pc, pending_call_notify,\n+\t\t\t\t \u0026dcwc-\u003ectx, NULL);\n+\n+\tstate_transition(dcwc, LDCS_CONN_WAITING_ONWARD);\n+\n+\tret \u003d 0;\n+\n+bail:\n+\tdbus_message_unref(msg);\n+\n+\treturn ret;\n+}\n+\n+/*\n+ * Stub lws protocol, just so we can get synchronous timers conveniently.\n+ *\n+ * Set up a 1Hz timer and if our connection state is suitable, use that\n+ * to write mirror protocol drawing packets to the proxied ws connection\n+ */\n+\n+static int\n+callback_just_timer(struct lws *wsi, enum lws_callback_reasons reason,\n+\t\t void *user, void *in, size_t len)\n+{\n+\tchar payload[64];\n+\tconst char *ws_pkt \u003d payload;\n+\tDBusMessage *msg;\n+\n+\tswitch (reason) {\n+\tcase LWS_CALLBACK_PROTOCOL_INIT:\n+\tcase LWS_CALLBACK_USER:\n+\t\tlwsl_info(\u0022%s: LWS_CALLBACK_USER\u005cn\u0022, __func__);\n+\n+\t\tif (!dbus_ctx || dbus_ctx-\u003estate !\u003d LDCS_CONN_ONWARD)\n+\t\t\tgoto again;\n+\n+\t\tif (autoexit_budget \u003e 0) {\n+\t\t\tif (!--autoexit_budget) {\n+\t\t\t\tlwsl_notice(\u0022reached autoexit budget\u005cn\u0022);\n+\t\t\t\tinterrupted \u003d 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tmsg \u003d dbus_message_new_method_call(THIS_BUSNAME, THIS_OBJECT,\n+\t\t\t\t\t\t THIS_INTERFACE, \u0022Send\u0022);\n+\t\tif (!msg)\n+\t\t\tbreak;\n+\n+\t\tlws_snprintf(payload, sizeof(payload), \u0022d #%06X %d %d %d %d;\u0022,\n+\t\t\t rand() \u0026 0xffffff, rand() % 480, rand() % 300,\n+\t\t\t rand() % 480, rand() % 300);\n+\n+\t\tif (!dbus_message_append_args(msg, DBUS_TYPE_STRING, \u0026ws_pkt,\n+\t\t\t\t\t\t DBUS_TYPE_INVALID)) {\n+\t\t\tdbus_message_unref(msg);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (!dbus_connection_send_with_reply(dbus_ctx-\u003ectx.conn, msg,\n+\t\t\t\t\t\t \u0026dbus_ctx-\u003ectx.pc,\n+\t\t\t\t\t\t DBUS_TIMEOUT_USE_DEFAULT)) {\n+\t\t\tlwsl_err(\u0022%s: unable to send\u005cn\u0022, __func__);\n+\t\t\tdbus_message_unref(msg);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tdbus_message_unref(msg);\n+\t\tdbus_pending_call_set_notify(dbus_ctx-\u003ectx.pc,\n+\t\t\t\t\t pending_call_notify,\n+\t\t\t\t\t \u0026dbus_ctx-\u003ectx, NULL);\n+\t\tcount_tx++;\n+\n+again:\n+\t\tlws_timed_callback_vh_protocol(lws_get_vhost(wsi),\n+\t\t\t\t\t lws_get_protocol(wsi),\n+\t\t\t\t\t LWS_CALLBACK_USER, 2);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static struct lws_protocols protocols[] \u003d {\n+\t\t{ \u0022_just_timer\u0022, callback_just_timer, 0, 10, 0, NULL, 0 },\n+\t\t{ }\n+};\n+\n+\n+int main(int argc, const char **argv)\n+{\n+\tstruct lws_vhost *vh;\n+\tstruct lws_context_creation_info info;\n+\tconst char *p;\n+\tint n \u003d 0, logs \u003d LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE\n+\t\t\t/* for LLL_ verbosity above NOTICE to be built into lws,\n+\t\t\t * lws must have been configured and built with\n+\t\t\t * -DCMAKE_BUILD_TYPE\u003dDEBUG instead of \u003dRELEASE */\n+\t\t\t/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */\n+\t\t\t/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */\n+\t\t\t/* | LLL_DEBUG */ /* | LLL_THREAD */;\n+\n+\tsignal(SIGINT, sigint_handler);\n+\n+\tif ((p \u003d lws_cmdline_option(argc, argv, \u0022-d\u0022)))\n+\t\tlogs \u003d atoi(p);\n+\n+\tif ((p \u003d lws_cmdline_option(argc, argv, \u0022-x\u0022)))\n+\t\tautoexit_budget \u003d atoi(p);\n+\n+\tlws_set_log_level(logs, NULL);\n+\tlwsl_user(\u0022LWS minimal DBUS ws proxy testclient\u005cn\u0022);\n+\n+\tmemset(\u0026info, 0, sizeof info); /* otherwise uninitialized garbage */\n+\tinfo.options \u003d LWS_SERVER_OPTION_EXPLICIT_VHOSTS;\n+\tinfo.protocols \u003d protocols;\n+\tcontext \u003d lws_create_context(\u0026info);\n+\tif (!context) {\n+\t\tlwsl_err(\u0022lws init failed\u005cn\u0022);\n+\t\treturn 1;\n+\t}\n+\n+\tvh \u003d lws_create_vhost(context, \u0026info);\n+\tif (!vh)\n+\t\tgoto bail;\n+\n+\tdbus_ctx \u003d create_dbus_client_conn(vh, 0, THIS_LISTEN_PATH);\n+\tif (!dbus_ctx)\n+\t\tgoto bail1;\n+\n+\tif (remote_method_call(dbus_ctx))\n+\t\tgoto bail2;\n+\n+\t/* lws event loop (default poll one) */\n+\n+\twhile (n \u003e\u003d 0 \u0026\u0026 !interrupted)\n+\t\tn \u003d lws_service(context, 1000);\n+\n+bail2:\n+\tdestroy_dbus_client_conn(\u0026dbus_ctx);\n+\n+bail1:\n+\t/* this is required for valgrind-cleanliness */\n+\tdbus_shutdown();\n+\tlws_context_destroy(context);\n+\n+\tlwsl_notice(\u0022Exiting cleanly, rx: %d, tx: %d\u005cn\u0022, count_rx, count_tx);\n+\n+\treturn 0;\n+\n+bail:\n+\tlwsl_err(\u0022%s: failed to start\u005cn\u0022, __func__);\n+\tlws_context_destroy(context);\n+\n+\treturn 1;\n+}\ndiff --git a/minimal-examples/dbus-server/README.md b/minimal-examples/dbus-server/README.md\nindex 9503920..fc59bfb 100644\n--- a/minimal-examples/dbus-server/README.md\n+++ b/minimal-examples/dbus-server/README.md\n@@ -1,3 +1,4 @@\n |Example|Demonstrates|\n ---|---\n minimal-dbus-server|Shows how to run a DBUS session server using lws event loop\n+minimal-dbus-ws-proxy|Control ws client connections via DBUS\ndiff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt\nnew file mode 100644\nindex 0000000..bad9ec3\n--- /dev/null\n+++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/CMakeLists.txt\n@@ -0,0 +1,122 @@\n+cmake_minimum_required(VERSION 2.8)\n+include(CheckCSourceCompiles)\n+include(CheckLibraryExists)\n+\n+set(SAMP lws-minimal-dbus-ws-proxy)\n+set(SRCS main.c)\n+\n+if (NOT LWS_WITH_MINIMAL_EXAMPLES)\n+\tCHECK_LIBRARY_EXISTS(dbus-1 dbus_connection_set_watch_functions \u0022\u0022 LWS_HAVE_LIBDBUS)\n+\tif (NOT LWS_HAVE_LIBDBUS)\n+\t\tmessage(FATAL_ERROR \u0022Install dbus-devel, or libdbus-1-dev etc\u0022)\n+\tendif()\n+\n+\tif (NOT LWS_DBUS_LIB)\n+\t\tset(LWS_DBUS_LIB \u0022dbus-1\u0022)\n+\tendif()\n+\n+\tif (NOT LWS_DBUS_INCLUDE1)\n+\t\t# look in fedora and debian / ubuntu place\n+\t\tif (EXISTS \u0022/usr/include/dbus-1.0\u0022)\n+\t\t\tset(LWS_DBUS_INCLUDE1 \u0022/usr/include/dbus-1.0\u0022)\n+\t\telse()\n+\t\t\tmessage(FATAL_ERROR \u0022Set LWS_DBUS_INCLUDE1 to /usr/include/dbus-1.0 or wherever the main dbus includes are\u0022)\n+\t\tendif()\n+\tendif()\n+\n+\tif (NOT LWS_DBUS_INCLUDE2)\n+\t\t# look in fedora... debian / ubuntu has the ARCH in the path...\n+\t\tif (EXISTS \u0022/usr/lib64/dbus-1.0/include\u0022)\n+\t\t\tset(LWS_DBUS_INCLUDE2 \u0022/usr/lib64/dbus-1.0/include\u0022)\n+\t\telse()\n+\t\t\tmessage(FATAL_ERROR \u0022Set LWS_DBUS_INCLUDE2 to /usr/lib/ARCH-linux-gnu/dbus-1.0/include or wherever dbus-arch-deps.h is on your system\u0022)\n+\t\tendif()\n+\tendif()\n+\n+\tset(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES};${LWS_DBUS_INCLUDE1};${LWS_DBUS_INCLUDE2})\n+\n+\tif (NOT LWS_DBUS_INCLUDE1 OR NOT LWS_DBUS_INCLUDE2)\n+\t\tmessage(FATAL_ERROR \u0022To build with libdbus, LWS_DBUS_INCLUDE1/2 must be given. See lib/roles/dbus/README.md\u0022)\n+\tendif()\n+\n+endif()\n+\n+# If we are being built as part of lws, confirm current build config supports\n+# reqconfig, else skip building ourselves.\n+#\n+# If we are being built externally, confirm installed lws was configured to\n+# support reqconfig, else error out with a helpful message about the problem.\n+#\n+MACRO(require_lws_config reqconfig _val result)\n+\n+\tif (DEFINED ${reqconfig})\n+\tif (${reqconfig})\n+\t\tset (rq 1)\n+\telse()\n+\t\tset (rq 0)\n+\tendif()\n+\telse()\n+\t\tset(rq 0)\n+\tendif()\n+\n+\tif (${_val} EQUAL ${rq})\n+\t\tset(SAME 1)\n+\telse()\n+\t\tset(SAME 0)\n+\tendif()\n+\n+\tif (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})\n+\t\tif (${_val})\n+\t\t\tmessage(\u0022${SAMP}: skipping as lws being built without ${reqconfig}\u0022)\n+\t\telse()\n+\t\t\tmessage(\u0022${SAMP}: skipping as lws built with ${reqconfig}\u0022)\n+\t\tendif()\n+\t\tset(${result} 0)\n+\telse()\n+\t\tif (LWS_WITH_MINIMAL_EXAMPLES)\n+\t\t\tset(MET ${SAME})\n+\t\telse()\n+\t\t\tCHECK_C_SOURCE_COMPILES(\u0022#include \u003clibwebsockets.h\u003e\u005cnint main(void) {\u005cn#if defined(${reqconfig})\u005cn return 0;\u005cn#else\u005cn fail;\u005cn#endif\u005cn return 0;\u005cn}\u005cn\u0022 HAS_${reqconfig})\n+\t\t\tif (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})\n+\t\t\t\tset(HAS_${reqconfig} 0)\n+\t\t\telse()\n+\t\t\t\tset(HAS_${reqconfig} 1)\n+\t\t\tendif()\n+\t\t\tif ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))\n+\t\t\t\tset(MET 1)\n+\t\t\telse()\n+\t\t\t\tset(MET 0)\n+\t\t\tendif()\n+\t\tendif()\n+\t\tif (NOT MET)\n+\t\t\tif (${_val})\n+\t\t\t\tmessage(FATAL_ERROR \u0022This project requires lws must have been configured with ${reqconfig}\u0022)\n+\t\t\telse()\n+\t\t\t\tmessage(FATAL_ERROR \u0022Lws configuration of ${reqconfig} is incompatible with this project\u0022)\n+\t\t\tendif()\n+\t\tendif()\n+\n+\tendif()\n+ENDMACRO()\n+\n+\n+set(requirements 1)\n+require_lws_config(LWS_ROLE_DBUS 1 requirements)\n+require_lws_config(LWS_ROLE_WS 1 requirements)\n+require_lws_config(LWS_WITHOUT_SERVER 0 requirements)\n+require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)\n+\n+if (requirements)\n+\tadd_executable(${SAMP} ${SRCS})\n+\n+\tinclude_directories(\u0022${LWS_DBUS_INCLUDE1}\u0022)\n+\tinclude_directories(\u0022${LWS_DBUS_INCLUDE2}\u0022)\n+\tlist(APPEND LIB_LIST dbus-1)\n+\n+\tif (websockets_shared)\n+\t\ttarget_link_libraries(${SAMP} websockets_shared)\n+\t\tadd_dependencies(${SAMP} websockets_shared ${LWS_DBUS_LIB})\n+\telse()\n+\t\ttarget_link_libraries(${SAMP} websockets ${LWS_DBUS_LIB})\n+\tendif()\n+endif()\ndiff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/README.md b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/README.md\nnew file mode 100644\nindex 0000000..7192854\n--- /dev/null\n+++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/README.md\n@@ -0,0 +1,115 @@\n+# lws minimal dbus ws proxy\n+\n+This is an application which presents a DBUS server on one side, and a\n+websocket client proxy on the other.\n+\n+You connect to it over DBUS, send a Connect method on its interface giving\n+a URI and a ws subprotocol name.\n+\n+It replies with a string \u0022Connecting\u0022 if all is well.\n+\n+Connection progress (including close) is then provided using type 7 messages\n+sent back to the dbus client.\n+\n+Payload from the ws connection is provided using type 6 messages sent back to\n+the dbus client.\n+\n+## build\n+\n+Using libdbus requires additional non-default include paths setting, same as\n+is necessary for lws build described in ./lib/roles/dbus/README.md\n+\n+CMake can guess one path and the library name usually, see the README above\n+for details of how to override for custom libdbus and cross build.\n+\n+Fedora example:\n+```\n+$ cmake .. -DLWS_DBUS_INCLUDE2\u003d\u0022/usr/lib64/dbus-1.0/include\u0022\n+$ make\n+```\n+\n+Ubuntu example:\n+```\n+$ cmake .. -DLWS_DBUS_INCLUDE2\u003d\u0022/usr/lib/x86_64-linux-gnu/dbus-1.0/include\u0022\n+$ make\n+```\n+\n+## Configuration\n+\n+The dbus-ws-proxy server tries to register its actual bus name with the SYSTEM\n+bus in DBUS. If it fails, eg because of insufficient permissions on the user,\n+then it continues without that and starts its own daemon normally.\n+\n+The main dbus daemon must be told how to accept these registrations if that's\n+what you want. A config file is provided that tells dbus to allow the\n+well-known busname for this daemon to be registered, but only by root.\n+\n+``` \n+$ sudo cp org.libwebsockets.wsclientproxy.conf /etc/dbus-1/system.d\n+$ sudo systemctl restart dbus\n+```\n+\n+## usage\n+\n+Run the dbus-ws-proxy server, then start lws-minimal-dbus-ws-proxy-testclient in\n+another terminal.\n+\n+This test app sends a random line drawing message to the mirror example on\n+https://libwebsockets.org/testserver every couple of seconds, and displays\n+any received messages (such as its own sends mirrored back, or anything\n+drawn in the canvas in a browser).\n+\n+```\n+ $ sudo ./lws-minimal-dbus-ws-proxy-testclient\n+[2018/10/07 10:05:29:2084] USER: LWS minimal DBUS ws proxy testclient\n+[2018/10/07 10:05:29:2345] NOTICE: Creating Vhost 'default' port 0, 1 protocols, IPv6 off\n+[2018/10/07 10:05:29:2424] USER: create_dbus_client_conn: connecting to 'unix:abstract\u003dorg.libwebsockets.wsclientproxy'\n+[2018/10/07 10:05:29:2997] NOTICE: state_transition: 0x5679720: from state 0 -\u003e 1\n+[2018/10/07 10:05:29:2999] NOTICE: create_dbus_client_conn: created OK\n+[2018/10/07 10:05:29:3232] USER: remote_method_call: requesting proxy connection wss://libwebsockets.org/ lws-mirror-protocol\n+[2018/10/07 10:05:29:3450] NOTICE: state_transition: 0x5679720: from state 1 -\u003e 2\n+[2018/10/07 10:05:29:5972] USER: pending_call_notify: received 'Connecting'\n+[2018/10/07 10:05:31:3387] NOTICE: state_transition: 0x5679720: from state 2 -\u003e 3\n+[2018/10/07 10:05:33:6672] USER: filter: Received 'd #B0DC51 115 177 166 283;'\n+[2018/10/07 10:05:35:9723] USER: filter: Received 'd #E87CCD 9 192 106 235;'\n+[2018/10/07 10:05:38:2784] USER: filter: Received 'd #E2A9E3 379 290 427 62;'\n+[2018/10/07 10:05:39:5833] USER: filter: Received 'd #B127F8 52 126 60 226;'\n+[2018/10/07 10:05:41:8908] USER: filter: Received 'd #0E0F76 429 267 8 11;'\n+...\n+```\n+\n+## ws proxy DBUS details\n+\n+### Fixed details\n+\n+Item|Value\n+---|---\n+Address|unix:abstract\u003dorg.libwebsockets.wsclientproxy\n+Interface|org.libwebsockets.wsclientproxy\n+Bus Name|org.libwebsockets.wsclientproxy\n+Object path|/org/libwebsockets/wsclientproxy\n+\n+### Interface Methods\n+\n+Method|Arguments|Returns\n+---|---|---\n+Connect|s: ws URI, s: ws subprotocol name|\u0022Bad Uri\u0022, \u0022Connecting\u0022 or \u0022Failed\u0022\n+Send|s: payload|Empty message if no problem, or error message\n+\n+When Connecting, the actual connection happens asynchronously if the initial\n+connection attempt doesn't fail immediately. If it's continuing in the\n+background, the reply will have been \u0022Connecting\u0022.\n+\n+### Signals\n+\n+Signal Name|Argument|Meaning\n+---|---|---\n+Receive|s: payload|Received data from the ws link\n+Status|s: status|See table below\n+\n+Status String|Meaning\n+---|---\n+\u0022ws client connection error\u0022|The ws connection attempt ended with a fatal error\n+\u0022ws client connection established\u0022|The ws connection attempt succeeded\n+\u0022ws client connection closed\u0022|The ws connection has closed\n+\ndiff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c\nnew file mode 100644\nindex 0000000..4510fd8\n--- /dev/null\n+++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/main.c\n@@ -0,0 +1,101 @@\n+/*\n+ * lws-minimal-dbus-ws-proxy\n+ *\n+ * Copyright (C) 2018 Andy Green \u003candy@warmcat.com\u003e\n+ *\n+ * This file is made available under the Creative Commons CC0 1.0\n+ * Universal Public Domain Dedication.\n+ *\n+ * This demonstrates a minimal session dbus server that uses the lws event loop,\n+ * and allows proxying ws client connections via DBUS.\n+ */\n+\n+#include \u003cstdbool.h\u003e\n+#include \u003cstring.h\u003e\n+#include \u003cstdio.h\u003e\n+#include \u003cstdlib.h\u003e\n+#include \u003cunistd.h\u003e\n+#include \u003csignal.h\u003e\n+\n+#include \u003clibwebsockets.h\u003e\n+#include \u003clibwebsockets/lws-dbus.h\u003e\n+\n+#define LWS_PLUGIN_STATIC\n+#include \u0022protocol_lws_minimal_dbus_ws_proxy.c\u0022\n+\n+static int interrupted;\n+static struct lws_protocols protocols[] \u003d {\n+\tLWS_PLUGIN_PROTOCOL_MINIMAL_DBUS_WSPROXY,\n+\t{ NULL, NULL, 0, 0 } /* terminator */\n+};\n+\n+/*\n+ * we pass the dbus address to connect to proxy with from outside the\n+ * protocol plugin... eg if built as a plugin for lwsws, you would instead\n+ * set this pvo in the lwsws JSON config.\n+ */\n+\n+static const struct lws_protocol_vhost_options pvo_ads \u003d {\n+\tNULL,\n+\tNULL,\n+\t\u0022ads\u0022,\t\t\t\t/* pvo name */\n+\t(void *)\u0022unix:abstract\u003dorg.libwebsockets.wsclientproxy\u0022\t/* pvo value */\n+};\n+\n+static const struct lws_protocol_vhost_options pvo \u003d {\n+\tNULL,\t\t\t\t/* \u0022next\u0022 pvo linked-list */\n+\t\u0026pvo_ads,\t\t\t/* \u0022child\u0022 pvo linked-list */\n+\t\u0022lws-minimal-dbus-wsproxy\u0022,\t/* protocol name we belong to on this vhost */\n+\t\u0022\u0022\t\t\t\t/* ignored */\n+};\n+\n+void sigint_handler(int sig)\n+{\n+\tinterrupted \u003d 1;\n+}\n+\n+int main(int argc, const char **argv)\n+{\n+\tstatic struct lws_context *context;\n+\tstruct lws_context_creation_info info;\n+\tconst char *p;\n+\tint n \u003d 0, logs \u003d LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE\n+\t\t\t/* for LLL_ verbosity above NOTICE to be built into lws,\n+\t\t\t * lws must have been configured and built with\n+\t\t\t * -DCMAKE_BUILD_TYPE\u003dDEBUG instead of \u003dRELEASE */\n+\t\t\t/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */\n+\t\t\t/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */\n+\t\t\t/* | LLL_DEBUG */ /* | LLL_THREAD */;\n+\n+\tsignal(SIGINT, sigint_handler);\n+\n+\tif ((p \u003d lws_cmdline_option(argc, argv, \u0022-d\u0022)))\n+\t\tlogs \u003d atoi(p);\n+\n+\tlws_set_log_level(logs, NULL);\n+\tlwsl_user(\u0022LWS DBUS ws client proxy\u005cn\u0022);\n+\n+\tmemset(\u0026info, 0, sizeof info); /* otherwise uninitialized garbage */\n+\tinfo.options \u003d LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;\n+\tinfo.port \u003d CONTEXT_PORT_NO_LISTEN;\n+\tinfo.ws_ping_pong_interval \u003d 30;\n+\tinfo.protocols \u003d protocols;\n+\tinfo.pvo \u003d \u0026pvo;\n+\n+\tcontext \u003d lws_create_context(\u0026info);\n+\tif (!context) {\n+\t\tlwsl_err(\u0022lws init failed\u005cn\u0022);\n+\t\treturn 1;\n+\t}\n+\n+\t/* lws event loop (default poll one) */\n+\n+\twhile (n \u003e\u003d 0 \u0026\u0026 !interrupted)\n+\t\tn \u003d lws_service(context, 1000);\n+\n+\tlws_context_destroy(context);\n+\n+\tlwsl_notice(\u0022Exiting cleanly\u005cn\u0022);\n+\n+\treturn 0;\n+}\ndiff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/org.libwebsockets.wsclientproxy.conf b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/org.libwebsockets.wsclientproxy.conf\nnew file mode 100644\nindex 0000000..49e430b\n--- /dev/null\n+++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/org.libwebsockets.wsclientproxy.conf\n@@ -0,0 +1,14 @@\n+\u003c!DOCTYPE busconfig PUBLIC\n+ \u0022-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN\u0022\n+ \u0022http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd\u0022\u003e\n+\u003cbusconfig\u003e\n+\t\u003cpolicy user\u003d\u0022root\u0022\u003e\n+\t\t\u003callow own\u003d\u0022org.libwebsockets.wsclientproxy\u0022/\u003e\n+\t\t\u003callow send_destination\u003d\u0022org.libwebsockets.wsclientproxy\u0022/\u003e\n+\t\u003c/policy\u003e\n+\t\u003cpolicy context\u003d\u0022default\u0022\u003e\n+ \u003cdeny own\u003d\u0022org.libwebsockets.wsclientproxy\u0022/\u003e\n+ \u003cdeny send_destination\u003d\u0022org.libwebsockets.wsclientproxy\u0022/\u003e\n+ \u003c/policy\u003e\n+\u003c/busconfig\u003e\n+\ndiff --git a/minimal-examples/dbus-server/minimal-dbus-ws-proxy/protocol_lws_minimal_dbus_ws_proxy.c b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/protocol_lws_minimal_dbus_ws_proxy.c\nnew file mode 100644\nindex 0000000..5a61ed5\n--- /dev/null\n+++ b/minimal-examples/dbus-server/minimal-dbus-ws-proxy/protocol_lws_minimal_dbus_ws_proxy.c\n@@ -0,0 +1,827 @@\n+/*\n+ * ws protocol handler plugin for dbus ws proxy\n+ *\n+ * Copyright (C) 2010-2018 Andy Green \u003candy@warmcat.com\u003e\n+ *\n+ * This file is made available under the Creative Commons CC0 1.0\n+ * Universal Public Domain Dedication.\n+ *\n+ * This proxies outgoing ws client connections on DBUS. So a DBUS client can\n+ * reach out and get remote WS payloads in both directions.\n+ *\n+ * DEVELOPER NOTE\n+ *\n+ * Two worlds, dbus and ws, collide in this file.\n+ *\n+ * There main thing keeping it sane is both worlds are running in the same\n+ * thread and on the same event loop. Although things may happen completely\n+ * asynchronously in both worlds, the logical reaction to those events are\n+ * serialized in a single event loop doing one thing at a time.\n+ *\n+ * So while you are servicing an event in the ws world, you can be certain the\n+ * logical state of any related dbus thing cannot change underneath you, until\n+ * you return back to the event loop, and vice versa. So other-world objects\n+ * can't be freed, other-world handles can't close etc while you are servicing\n+ * in your world.\n+ *\n+ * Since all bets are off what happens next, and in which world, after you\n+ * return back to the event loop though, an additional rule is needed: worlds\n+ * must not allocate in objects owned by the other world. They must generate\n+ * their own objects in their world and use those for allocations and state.\n+ *\n+ * For example in the dbus-world there is a struct lws_dbus_ctx_wsproxy with\n+ * various state, but he is subject to deletion by events in dbus-world. If\n+ * the ws-world stored things there, they are subject to going out of scope\n+ * at the whim of the dbus connection without the ws world hearing about it and\n+ * cleanly deallocaing them. So the ws world must keep his own pss that remains\n+ * in scope until the ws link closes for allocations from ws-world.\n+ *\n+ * In this application there's a point of contact between the worlds, a ring\n+ * buffer allocated in ws world when the ws connection is established, and\n+ * deallocated when the ws connection is closed. The DBUS world needs to put\n+ * things in this ringbuffer. But the way lws_ring works, when the message\n+ * allocated in DBUS world is queued on the ringbuffer, the ringbuffer itself\n+ * takes responsibility for deallocation. So there is no problem.\n+ */\n+\n+#if !defined (LWS_PLUGIN_STATIC)\n+#define LWS_DLL\n+#define LWS_INTERNAL\n+#include \u003clibwebsockets.h\u003e\n+#include \u003clibwebsockets/lws-dbus.h\u003e\n+#endif\n+\n+#include \u003cstring.h\u003e\n+#include \u003cassert.h\u003e\n+#include \u003csignal.h\u003e\n+\n+/*\n+ * dbus accepted connections create these larger context structs that start\n+ * with the lws dbus context\n+ */\n+\n+struct vhd_dbus_proxy;\n+\n+struct msg {\n+\tvoid *payload; /* is malloc'd */\n+\tsize_t len;\n+\tchar binary;\n+\tchar first;\n+\tchar final;\n+};\n+\n+struct pss_dbus_proxy {\n+\tstruct lws_ring *ring_out;\n+\tuint32_t ring_out_tail;\n+};\n+\n+struct lws_dbus_ctx_wsproxy {\n+\tstruct lws_dbus_ctx ctx;\n+\n+\tstruct lws *cwsi;\n+\tstruct vhd_dbus_proxy *vhd;\n+\tstruct pss_dbus_proxy *pss;\n+};\n+\n+struct vhd_dbus_proxy {\n+\tstruct lws_context *context;\n+\tstruct lws_vhost *vhost;\n+\n+\t/*\n+\t * Because the listener ctx is composed in the vhd, we can always get a\n+\t * pointer to the outer vhd from a pointer to ctx_listener inside.\n+\t */\n+\tstruct lws_dbus_ctx ctx_listener;\n+\tstruct lws_dbus_ctx_wsproxy dctx;\n+\n+\tconst char *dbus_listen_ads;\n+};\n+\n+#define THIS_INTERFACE\t\u0022org.libwebsockets.wsclientproxy\u0022\n+#define THIS_OBJECT\t\u0022/org/libwebsockets/wsclientproxy\u0022\n+#define THIS_BUSNAME\t\u0022org.libwebsockets.wsclientproxy\u0022\n+static const char *version \u003d \u00220.1\u0022;\n+\n+static const char *server_introspection_xml \u003d\n+\tDBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE\n+\t\u0022\u003cnode\u003e\u005cn\u0022\n+\t\u0022 \u003cinterface name\u003d'\u0022 DBUS_INTERFACE_INTROSPECTABLE \u0022'\u003e\u005cn\u0022\n+\t\u0022 \u003cmethod name\u003d'Introspect'\u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'data' type\u003d's' direction\u003d'out' /\u003e\u005cn\u0022\n+\t\u0022 \u003c/method\u003e\u005cn\u0022\n+\t\u0022 \u003c/interface\u003e\u005cn\u0022\n+\n+\t\u0022 \u003cinterface name\u003d'\u0022 DBUS_INTERFACE_PROPERTIES \u0022'\u003e\u005cn\u0022\n+\t\u0022 \u003cmethod name\u003d'Get'\u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'interface' type\u003d's' direction\u003d'in' /\u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'property' type\u003d's' direction\u003d'in' /\u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'value' type\u003d's' direction\u003d'out' /\u003e\u005cn\u0022\n+\t\u0022 \u003c/method\u003e\u005cn\u0022\n+\t\u0022 \u003cmethod name\u003d'GetAll'\u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'interface' type\u003d's' direction\u003d'in'/\u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'properties' type\u003d'a{sv}' direction\u003d'out'/\u003e\u005cn\u0022\n+\t\u0022 \u003c/method\u003e\u005cn\u0022\n+\t\u0022 \u003c/interface\u003e\u005cn\u0022\n+\n+\t\u0022 \u003cinterface name\u003d'\u0022THIS_INTERFACE\u0022'\u003e\u005cn\u0022\n+\t\u0022 \u003cproperty name\u003d'Version' type\u003d's' access\u003d'read' /\u003e\u005cn\u0022\n+\t\u0022 \u003cmethod name\u003d'Connect' \u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'url' type\u003d's' direction\u003d'in' /\u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'subprotocol' type\u003d's' direction\u003d'in' /\u003e\u005cn\u0022\n+\t\u0022 \u003c/method\u003e\u005cn\u0022\n+\t\u0022 \u003cmethod name\u003d'Send'\u003e\u005cn\u0022\n+\t\u0022 \u003carg name\u003d'payload' type\u003d's' direction\u003d'in' /\u003e\u005cn\u0022\n+\t\u0022 \u003c/method\u003e\u005cn\u0022\n+\t\u0022 \u003csignal name\u003d'Receive'\u003e\u005cn\u0022\n+\t\u0022 \u003c/signal\u003e\u0022\n+\t\u0022 \u003csignal name\u003d'Status'\u003e\u005cn\u0022\n+\t\u0022 \u003c/signal\u003e\u0022\n+\t\u0022 \u003c/interface\u003e\u005cn\u0022\n+\n+\t\u0022\u003c/node\u003e\u005cn\u0022;\n+\n+static void\n+destroy_message(void *_msg)\n+{\n+\tstruct msg *msg \u003d _msg;\n+\n+\tfree(msg-\u003epayload);\n+\tmsg-\u003epayload \u003d NULL;\n+\tmsg-\u003elen \u003d 0;\n+}\n+\n+/*\n+ * DBUS WORLD\n+ */\n+\n+static DBusHandlerResult\n+dmh_introspect(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d)\n+{\n+\tdbus_message_append_args(*reply,\n+\t\t\t\t DBUS_TYPE_STRING, \u0026server_introspection_xml,\n+\t\t\t\t DBUS_TYPE_INVALID);\n+\n+\treturn DBUS_HANDLER_RESULT_HANDLED;\n+}\n+\n+static DBusHandlerResult\n+dmh_get(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d)\n+{\n+\tconst char *interface, *property;\n+\tDBusError err;\n+\n+\tdbus_error_init(\u0026err);\n+\n+\tif (!dbus_message_get_args(m, \u0026err, DBUS_TYPE_STRING, \u0026interface,\n+\t\t\t\t\t DBUS_TYPE_STRING, \u0026property,\n+\t\t\t\t\t DBUS_TYPE_INVALID)) {\n+\t\tdbus_message_unref(*reply);\n+\t\t*reply \u003d dbus_message_new_error(m, err.name, err.message);\n+\t\tdbus_error_free(\u0026err);\n+\n+\t\treturn DBUS_HANDLER_RESULT_HANDLED;\n+\t}\n+\n+\tif (strcmp(property, \u0022Version\u0022)) /* Unknown property */\n+\t\treturn DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n+\n+\tdbus_message_append_args(*reply, DBUS_TYPE_STRING, \u0026version,\n+\t\t\t\t\t DBUS_TYPE_INVALID);\n+\n+\treturn DBUS_HANDLER_RESULT_HANDLED;\n+}\n+\n+static DBusHandlerResult\n+dmh_getall(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d)\n+{\n+\tDBusMessageIter arr, di, iter, va;\n+\tconst char *property \u003d \u0022Version\u0022;\n+\n+\tdbus_message_iter_init_append(*reply, \u0026iter);\n+\tdbus_message_iter_open_container(\u0026iter, DBUS_TYPE_ARRAY, \u0022{sv}\u0022, \u0026arr);\n+\n+\t/* Append all properties name/value pairs */\n+\tdbus_message_iter_open_container(\u0026arr, DBUS_TYPE_DICT_ENTRY, NULL, \u0026di);\n+\tdbus_message_iter_append_basic(\u0026di, DBUS_TYPE_STRING, \u0026property);\n+\tdbus_message_iter_open_container(\u0026di, DBUS_TYPE_VARIANT, \u0022s\u0022, \u0026va);\n+\tdbus_message_iter_append_basic(\u0026va, DBUS_TYPE_STRING, \u0026version);\n+\tdbus_message_iter_close_container(\u0026di, \u0026va);\n+\tdbus_message_iter_close_container(\u0026arr, \u0026di);\n+\n+\tdbus_message_iter_close_container(\u0026iter, \u0026arr);\n+\n+\treturn DBUS_HANDLER_RESULT_HANDLED;\n+}\n+\n+static DBusHandlerResult\n+dmh_connect(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d)\n+{\n+\tstruct lws_dbus_ctx_wsproxy *wspctx \u003d (struct lws_dbus_ctx_wsproxy *)d;\n+\tconst char *prot \u003d \u0022\u0022, *ads \u003d \u0022\u0022, *path \u003d \u0022\u0022, *baduri \u003d \u0022Bad Uri\u0022,\n+\t\t *connecting \u003d \u0022Connecting\u0022, *failed \u003d \u0022Failed\u0022, **pp;\n+\tstruct lws_client_connect_info i;\n+\tchar host[128], uri_copy[512];\n+\tconst char *uri, *subprotocol;\n+\tDBusError err;\n+\tint port \u003d 0;\n+\n+\tdbus_error_init(\u0026err);\n+\n+\tif (!dbus_message_get_args(m, \u0026err, DBUS_TYPE_STRING, \u0026uri,\n+\t\t\t \t \t DBUS_TYPE_STRING, \u0026subprotocol,\n+\t\t\t\t\t DBUS_TYPE_INVALID)) {\n+\t\tdbus_message_unref(*reply);\n+\t\t*reply \u003d dbus_message_new_error(m, err.name, err.message);\n+\t\tdbus_error_free(\u0026err);\n+\n+\t\treturn DBUS_HANDLER_RESULT_HANDLED;\n+\t}\n+\n+\tstrncpy(uri_copy, uri, sizeof(uri_copy) - 1);\n+\turi_copy[sizeof(uri_copy) - 1] \u003d '\u005c0';\n+\n+\tif (lws_parse_uri(uri_copy, \u0026prot, \u0026ads, \u0026port, \u0026path)) {\n+\t\tpp \u003d \u0026baduri;\n+\t\tgoto send_reply;\n+\t}\n+\n+\tlws_snprintf(host, sizeof(host), \u0022%s:%u\u0022, ads, port);\n+\n+\tmemset(\u0026i, 0, sizeof(i));\n+\n+\tassert(wspctx);\n+\tassert(wspctx-\u003evhd);\n+\n+\ti.context \u003d wspctx-\u003evhd-\u003econtext;\n+\ti.port \u003d port;\n+\ti.address \u003d ads;\n+\ti.path \u003d path;\n+\ti.host \u003d host;\n+\ti.origin \u003d host;\n+\ti.ssl_connection \u003d !strcmp(prot, \u0022https\u0022) || !strcmp(prot, \u0022wss\u0022);\n+\ti.vhost \u003d wspctx-\u003ectx.vh;\n+\ti.protocol \u003d subprotocol;\n+\ti.local_protocol_name \u003d \u0022lws-minimal-dbus-wsproxy\u0022;\n+\ti.pwsi \u003d \u0026wspctx-\u003ecwsi;\n+\n+\tlwsl_user(\u0022%s: connecting to %s://%s:%d%s\u005cn\u0022, __func__, prot,\n+\t\t\ti.address, i.port, i.path);\n+\n+\tif (!lws_client_connect_via_info(\u0026i)) {\n+\t\tlwsl_notice(\u0022%s: client connect failed\u005cn\u0022, __func__);\n+\t\tpp \u003d \u0026failed;\n+\t\tgoto send_reply;\n+\t}\n+\n+\tlws_set_opaque_parent_data(wspctx-\u003ecwsi, wspctx);\n+\tlwsl_notice(\u0022%s: client connecting...\u005cn\u0022, __func__);\n+\tpp \u003d \u0026connecting;\n+\n+send_reply:\n+\tdbus_message_append_args(*reply, DBUS_TYPE_STRING, pp,\n+\t\t\t\t\t DBUS_TYPE_INVALID);\n+\n+\treturn DBUS_HANDLER_RESULT_HANDLED;\n+}\n+\n+static int\n+issue_dbus_signal(struct lws *wsi, const char *signame, const char *string)\n+{\n+\tstruct lws_dbus_ctx_wsproxy *wspctx \u003d\n+\t\t\tlws_get_opaque_parent_data(wsi);\n+\tDBusMessage *m;\n+\n+\tif (!wspctx)\n+\t\treturn 1;\n+\n+\tm \u003d dbus_message_new_signal(THIS_OBJECT, THIS_INTERFACE, signame);\n+\tif (!m) {\n+\t\tlwsl_err(\u0022%s: new signal failed\u005cn\u0022, __func__);\n+\t\treturn 1;\n+\t}\n+\n+\tdbus_message_append_args(m, DBUS_TYPE_STRING, \u0026string,\n+\t\t\t\t DBUS_TYPE_INVALID);\n+\n+\tif (!dbus_connection_send(wspctx-\u003ectx.conn, m, NULL))\n+\t\tlwsl_err(\u0022%s: unable to send\u005cn\u0022, __func__);\n+\n+\tdbus_message_unref(m);\n+\n+\treturn 0;\n+}\n+\n+static DBusHandlerResult\n+dmh_send(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d)\n+{\n+\tstruct lws_dbus_ctx_wsproxy *wspctx \u003d (struct lws_dbus_ctx_wsproxy *)d;\n+\tconst char *payload;\n+\tstruct msg amsg;\n+\tDBusError err;\n+\n+\tdbus_error_init(\u0026err);\n+\n+\tif (!wspctx-\u003ecwsi || !wspctx-\u003epss) {\n+\t\tdbus_message_unref(*reply);\n+\t\t*reply \u003d dbus_message_new_error(m, \u0022Send Fail\u0022, \u0022No ws conn\u0022);\n+\n+\t\treturn DBUS_HANDLER_RESULT_HANDLED;\n+\t}\n+\n+\tif (!dbus_message_get_args(m, \u0026err, DBUS_TYPE_STRING, \u0026payload,\n+\t\t\t\t\t DBUS_TYPE_INVALID)) {\n+\t\tdbus_message_unref(*reply);\n+\t\t*reply \u003d dbus_message_new_error(m, err.name, err.message);\n+\t\tdbus_error_free(\u0026err);\n+\n+\t\treturn DBUS_HANDLER_RESULT_HANDLED;\n+\t}\n+\n+\t/*\n+\t * we allocate on the ringbuffer in ws world, but responsibility for\n+\t * freeing it is understood by lws_ring.\n+\t */\n+\n+\tamsg.len \u003d strlen(payload);\n+\t/* notice we over-allocate by LWS_PRE */\n+\tamsg.payload \u003d malloc(LWS_PRE + amsg.len);\n+\tif (!amsg.payload) {\n+\t\tlwsl_user(\u0022OOM: dropping\u005cn\u0022);\n+\t\tdbus_message_unref(*reply);\n+\t\t*reply \u003d dbus_message_new_error(m, \u0022Send Fail\u0022, \u0022OOM\u0022);\n+\n+\t\treturn DBUS_HANDLER_RESULT_HANDLED;\n+\t}\n+\tamsg.binary \u003d 0;\n+\tamsg.first \u003d 1;\n+\tamsg.final \u003d 1;\n+\n+\tmemcpy((char *)amsg.payload + LWS_PRE, payload, amsg.len);\n+\tif (!lws_ring_insert(wspctx-\u003epss-\u003ering_out, \u0026amsg, 1)) {\n+\t\tdestroy_message(\u0026amsg);\n+\t\tlwsl_user(\u0022Ring Full!\u005cn\u0022);\n+\t\tdbus_message_unref(*reply);\n+\t\t*reply \u003d dbus_message_new_error(m, \u0022Send Fail\u0022, \u0022Ring full\u0022);\n+\n+\t\treturn DBUS_HANDLER_RESULT_HANDLED;\n+\t}\n+\tif (wspctx-\u003ecwsi)\n+\t\tlws_callback_on_writable(wspctx-\u003ecwsi);\n+\n+\treturn DBUS_HANDLER_RESULT_HANDLED;\n+}\n+\n+struct lws_dbus_methods {\n+\tconst char *inter;\n+\tconst char *call;\n+\tlws_dbus_message_handler handler;\n+} meths[] \u003d {\n+\t{ DBUS_INTERFACE_INTROSPECTABLE, \u0022Introspect\u0022,\tdmh_introspect\t},\n+\t{ DBUS_INTERFACE_PROPERTIES,\t \u0022Get\u0022,\t\tdmh_get\t\t},\n+\t{ DBUS_INTERFACE_PROPERTIES,\t \u0022GetAll\u0022,\tdmh_getall\t},\n+\t{ THIS_INTERFACE,\t\t \u0022Connect\u0022,\tdmh_connect\t},\n+\t{ THIS_INTERFACE,\t\t \u0022Send\u0022,\tdmh_send\t},\n+};\n+\n+static DBusHandlerResult\n+server_message_handler(DBusConnection *conn, DBusMessage *message, void *data)\n+{\n+\tstruct lws_dbus_methods *mp \u003d meths;\n+ DBusMessage *reply \u003d NULL;\n+\tDBusHandlerResult result;\n+\tsize_t n;\n+\n+\tassert(data);\n+\n+\tlwsl_info(\u0022%s: Got D-Bus request: %s.%s on %s\u005cn\u0022, __func__,\n+\t\tdbus_message_get_interface(message),\n+\t\tdbus_message_get_member(message),\n+\t\tdbus_message_get_path(message));\n+\n+\tfor (n \u003d 0; n \u003c LWS_ARRAY_SIZE(meths); n++) {\n+\t\tif (dbus_message_is_method_call(message, mp-\u003einter, mp-\u003ecall)) {\n+\t\t\treply \u003d dbus_message_new_method_return(message);\n+\t\t\tif (!reply)\n+\t\t\t\treturn DBUS_HANDLER_RESULT_NEED_MEMORY;\n+\n+\t\t\tresult \u003d mp-\u003ehandler(conn, message, \u0026reply, data);\n+\n+\t\t\tif (result \u003d\u003d DBUS_HANDLER_RESULT_HANDLED \u0026\u0026\n+\t\t\t !dbus_connection_send(conn, reply, NULL))\n+\t\t\t\tresult \u003d DBUS_HANDLER_RESULT_NEED_MEMORY;\n+\n+\t\t\tdbus_message_unref(reply);\n+\n+\t\t\treturn result;\n+\t\t}\n+\n+\t\tmp++;\n+\t}\n+\n+\treturn DBUS_HANDLER_RESULT_NOT_YET_HANDLED;\n+}\n+\n+static const DBusObjectPathVTable vtable \u003d {\n+\t.message_function \u003d server_message_handler\n+};\n+\n+static void\n+destroy_dbus_server_conn(struct lws_dbus_ctx_wsproxy *wsctx)\n+{\n+\tif (!wsctx-\u003ectx.conn)\n+\t\treturn;\n+\n+\tlwsl_notice(\u0022%s\u005cn\u0022, __func__);\n+\n+\tdbus_connection_unregister_object_path(wsctx-\u003ectx.conn, THIS_OBJECT);\n+\tlws_dll_remove(\u0026wsctx-\u003ectx.next);\n+\tdbus_connection_unref(wsctx-\u003ectx.conn);\n+}\n+\n+/*\n+ * This is the client dbus side going away. We need to stop the associated\n+ * client ws part and make sure it can't dereference us now we are gone.\n+ */\n+\n+static void\n+cb_closing(struct lws_dbus_ctx *ctx)\n+{\n+\tstruct lws_dbus_ctx_wsproxy *wspctx \u003d\n+\t\t\t(struct lws_dbus_ctx_wsproxy *)ctx;\n+\tlwsl_err(\u0022%s: closing\u005cn\u0022, __func__);\n+\n+\t/*\n+\t * We have to take care that the associated proxy wsi knows our\n+\t * dbus ctx is going out of scope after we return from here.\n+\t *\n+\t * We do it by setting its pointer to our dbus ctx to NULL.\n+\t */\n+\n+\tif (wspctx-\u003ecwsi) {\n+\t\tlws_set_opaque_parent_data(wspctx-\u003ecwsi, NULL);\n+\t\tlws_set_timeout(wspctx-\u003ecwsi,\n+\t\t\t\tPENDING_TIMEOUT_KILLED_BY_PROXY_CLIENT_CLOSE,\n+\t\t\t\tLWS_TO_KILL_ASYNC);\n+\t}\n+\n+\tdestroy_dbus_server_conn(wspctx);\n+\n+\tfree(wspctx);\n+}\n+\n+static void\n+new_conn(DBusServer *server, DBusConnection *conn, void *d)\n+{\n+\tstruct lws_dbus_ctx_wsproxy *conn_wspctx, /* the new conn context */\n+\t\t\t\t /* the listener context */\n+\t\t\t\t *wspctx \u003d (struct lws_dbus_ctx_wsproxy *)d;\n+\tstruct vhd_dbus_proxy *vhd \u003d lws_container_of(d,\n+\t\t\t\t\tstruct vhd_dbus_proxy, ctx_listener);\n+\n+\tassert(vhd-\u003evhost \u003d\u003d wspctx-\u003ectx.vh);\n+\n+\tlwsl_notice(\u0022%s\u005cn\u0022, __func__);\n+\n+\tconn_wspctx \u003d malloc(sizeof(*conn_wspctx));\n+\tif (!conn_wspctx)\n+\t\treturn;\n+\n+\tmemset(conn_wspctx, 0, sizeof(*conn_wspctx));\n+\n+\tconn_wspctx-\u003ectx.tsi \u003d conn_wspctx-\u003ectx.tsi;\n+\tconn_wspctx-\u003ectx.vh \u003d wspctx-\u003ectx.vh;\n+\tconn_wspctx-\u003ectx.conn \u003d conn;\n+\tconn_wspctx-\u003evhd \u003d vhd; /* let accepted connections also know the vhd */\n+\n+\tassert(conn_wspctx-\u003evhd);\n+\n+\tif (lws_dbus_connection_setup(\u0026conn_wspctx-\u003ectx, conn, cb_closing)) {\n+\t\tlwsl_err(\u0022%s: connection bind to lws failed\u005cn\u0022, __func__);\n+\t\tgoto bail;\n+\t}\n+\n+\tif (!dbus_connection_register_object_path(conn, THIS_OBJECT, \u0026vtable,\n+\t\t\t\t\t\t conn_wspctx)) {\n+\t\tlwsl_err(\u0022%s: Failed to register object path\u005cn\u0022, __func__);\n+\t\tgoto bail;\n+\t}\n+\n+\tlws_dll_add_front(\u0026conn_wspctx-\u003ectx.next, \u0026wspctx-\u003ectx.next);\n+\n+\t/* we take on responsibility for explicit close / unref with this... */\n+\tdbus_connection_ref(conn);\n+\n+\treturn;\n+\n+bail:\n+\tfree(conn_wspctx);\n+}\n+\n+static int\n+create_dbus_listener(struct vhd_dbus_proxy *vhd, int tsi)\n+{\n+\tDBusError e;\n+\n+ dbus_error_init(\u0026e);\n+#if 0\n+ vhd-\u003edctx.ctx.tsi \u003d tsi;\n+ vhd-\u003edctx.ctx.vh \u003d vhd-\u003evhost;\n+ vhd-\u003edctx.ctx.next.prev \u003d NULL;\n+ vhd-\u003edctx.ctx.next.next \u003d NULL;\n+ vhd-\u003edctx.vhd \u003d vhd;\n+ vhd-\u003edctx.cwsi \u003d NULL;\n+\n+\t/* connect to the SYSTEM bus */\n+\n+\tvhd-\u003edctx.ctx.conn \u003d dbus_bus_get(DBUS_BUS_SYSTEM, \u0026e);\n+\tif (!vhd-\u003edctx.ctx.conn) {\n+\t\tlwsl_notice(\u0022%s: Failed to get a session DBus connection: '%s'\u0022\n+\t\t\t \u0022, continuing with daemon listener only\u005cn\u0022,\n+\t\t\t __func__, e.message);\n+\t\tdbus_error_free(\u0026e);\n+\t\tdbus_error_init(\u0026e);\n+\t\tgoto daemon;\n+\t}\n+\n+\t/*\n+\t * by default dbus will call exit() when this connection closes...\n+\t * we have to shut down other things cleanly, so disable that\n+\t */\n+\tdbus_connection_set_exit_on_disconnect(vhd-\u003edctx.ctx.conn, 0);\n+\n+\tif (dbus_bus_request_name(vhd-\u003edctx.ctx.conn, THIS_BUSNAME,\n+\t\t\t\t DBUS_NAME_FLAG_REPLACE_EXISTING, \u0026e) !\u003d\n+\t\t\t\t\tDBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {\n+\t\tlwsl_notice(\u0022%s: Failed to request name on bus: '%s',\u0022\n+\t\t\t \u0022 continuing with daemon listener only\u005cn\u0022,\n+\t\t\t __func__, e.message);\n+\t\tdbus_connection_unref(vhd-\u003edctx.ctx.conn);\n+\t\tvhd-\u003edctx.ctx.conn \u003d NULL;\n+\t\tdbus_error_free(\u0026e);\n+\t\tdbus_error_init(\u0026e);\n+\t\tgoto daemon;\n+\t}\n+\n+\tif (!dbus_connection_register_object_path(vhd-\u003edctx.ctx.conn,\n+\t\t\t\t\t\t THIS_OBJECT, \u0026vtable,\n+\t\t\t\t\t\t \u0026vhd-\u003edctx)) {\n+\t\tlwsl_err(\u0022%s: Failed to register object path\u005cn\u0022, __func__);\n+\t\tgoto fail;\n+\t}\n+\n+\t/*\n+\t * This is the part that binds the connection to lws watcher and\n+\t * timeout handling provided by lws\n+\t */\n+\n+\tif (lws_dbus_connection_setup(\u0026vhd-\u003edctx.ctx, vhd-\u003edctx.ctx.conn,\n+\t\t\t\t cb_closing)) {\n+\t\tlwsl_err(\u0022%s: connection bind to lws failed\u005cn\u0022, __func__);\n+\t\tgoto fail;\n+\t}\n+\n+daemon:\n+#endif\n+ vhd-\u003ectx_listener.vh \u003d vhd-\u003evhost;\n+ vhd-\u003ectx_listener.tsi \u003d tsi;\n+\n+\tif (!lws_dbus_server_listen(\u0026vhd-\u003ectx_listener, vhd-\u003edbus_listen_ads,\n+\t\t\t\t \u0026e, new_conn)) {\n+\t\tlwsl_err(\u0022%s: failed\u005cn\u0022, __func__);\n+\t\tdbus_error_free(\u0026e);\n+\n+\t\treturn 1;\n+\t}\n+\n+\tlwsl_notice(\u0022%s: created DBUS listener on %s\u005cn\u0022, __func__,\n+\t\t\tvhd-\u003edbus_listen_ads);\n+\n+\treturn 0;\n+#if 0\n+fail:\n+\tdbus_error_free(\u0026e);\n+\n+\treturn 1;\n+#endif\n+}\n+\n+static void\n+destroy_dbus_server_listener(struct vhd_dbus_proxy *vhd)\n+{\n+\tdbus_server_disconnect(vhd-\u003ectx_listener.dbs);\n+\n+\tlws_start_foreach_dll_safe(struct lws_dll *, rdt, nx,\n+\t\t\tvhd-\u003ectx_listener.next.next) {\n+\t\tstruct lws_dbus_ctx *r \u003d lws_container_of(rdt,\n+\t\t\t\t\t\tstruct lws_dbus_ctx, next);\n+\n+\t\tdbus_connection_close(r-\u003econn);\n+\t\tdbus_connection_unref(r-\u003econn);\n+\t\tfree(r);\n+\t} lws_end_foreach_dll_safe(rdt, nx);\n+\n+\tif (vhd-\u003edctx.ctx.conn)\n+\t\tdbus_connection_unref(vhd-\u003edctx.ctx.conn);\n+\tdbus_server_unref(vhd-\u003ectx_listener.dbs);\n+}\n+\n+/*\n+ * WS WORLD\n+ */\n+\n+static int\n+callback_minimal_dbus_wsproxy(struct lws *wsi, enum lws_callback_reasons reason,\n+\t\t\t void *user, void *in, size_t len)\n+{\n+\tstruct pss_dbus_proxy *pss \u003d (struct pss_dbus_proxy *)user;\n+\tstruct vhd_dbus_proxy *vhd \u003d (struct vhd_dbus_proxy *)\n+\t\t\tlws_protocol_vh_priv_get(lws_get_vhost(wsi),\n+\t\t\t\t\t\t lws_get_protocol(wsi));\n+\tstruct lws_dbus_ctx_wsproxy *wspctx;\n+\tconst struct msg *pmsg;\n+\tint flags, m;\n+\n+\tswitch (reason) {\n+\n+\tcase LWS_CALLBACK_PROTOCOL_INIT:\n+\t\tvhd \u003d lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),\n+\t\t\t\t\tlws_get_protocol(wsi), sizeof(*vhd));\n+\t\tif (!vhd)\n+\t\t\treturn -1;\n+\n+\t\tvhd-\u003econtext \u003d lws_get_context(wsi);\n+\t\tvhd-\u003evhost \u003d lws_get_vhost(wsi);\n+\n+\t\tif (lws_pvo_get_str(in, \u0022ads\u0022, \u0026vhd-\u003edbus_listen_ads)) {\n+\t\t\tlwsl_err(\u0022%s: pvo 'ads' must be set\u005cn\u0022, __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (create_dbus_listener(vhd, 0)) {\n+\t\t\tlwsl_err(\u0022%s: create_dbus_listener failed\u005cn\u0022, __func__);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbreak;\n+\n+\tcase LWS_CALLBACK_PROTOCOL_DESTROY:\n+\t\tdestroy_dbus_server_listener(vhd);\n+\t\t/* this is required for valgrind-cleanliness */\n+\t\tdbus_shutdown();\n+\t\tbreak;\n+\n+\tcase LWS_CALLBACK_CLIENT_ESTABLISHED:\n+\t\tlwsl_user(\u0022LWS_CALLBACK_CLIENT_ESTABLISHED\u005cn\u0022);\n+\n+\t\t/*\n+\t\t * create the send ringbuffer now the ws connection is\n+\t\t * established.\n+\t\t */\n+\n+\t\twspctx \u003d lws_get_opaque_parent_data(wsi);\n+\t\tif (!wspctx)\n+\t\t\tbreak;\n+\n+\t\twspctx-\u003epss \u003d pss;\n+\t\tpss-\u003ering_out_tail \u003d 0;\n+\t\tpss-\u003ering_out \u003d lws_ring_create(sizeof(struct msg), 8,\n+\t\t\t\t\t\t destroy_message);\n+\t\tif (!pss-\u003ering_out) {\n+\t\t\tlwsl_err(\u0022OOM\u005cn\u0022);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tissue_dbus_signal(wsi, \u0022Status\u0022,\n+\t\t\t\t \u0022ws client connection established\u0022);\n+\t\tbreak;\n+\n+\tcase LWS_CALLBACK_CLIENT_WRITEABLE:\n+\t\tlwsl_user(\u0022LWS_CALLBACK_CLIENT_WRITEABLE:\u005cn\u0022);\n+\n+\t\tpmsg \u003d lws_ring_get_element(pss-\u003ering_out, \u0026pss-\u003ering_out_tail);\n+\t\tif (!pmsg) {\n+\t\t\tlwsl_user(\u0022 (nothing in ring)\u005cn\u0022);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tflags \u003d lws_write_ws_flags(\n+\t\t\t pmsg-\u003ebinary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT,\n+\t\t\t pmsg-\u003efirst, pmsg-\u003efinal);\n+\n+\t\t/* notice we allowed for LWS_PRE in the payload already */\n+\t\tm \u003d lws_write(wsi, pmsg-\u003epayload + LWS_PRE, pmsg-\u003elen, flags);\n+\t\tif (m \u003c (int)pmsg-\u003elen) {\n+\t\t\tlwsl_err(\u0022ERROR %d writing to ws socket\u005cn\u0022, m);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tlwsl_user(\u0022 wrote %d: flags: 0x%x first: %d final %d\u005cn\u0022,\n+\t\t\t\tm, flags, pmsg-\u003efirst, pmsg-\u003efinal);\n+\n+\t\tlws_ring_consume_single_tail(pss-\u003ering_out,\n+\t\t\t\t\t \u0026pss-\u003ering_out_tail, 1);\n+\n+\t\t/* more to do for us? */\n+\t\tif (lws_ring_get_element(pss-\u003ering_out, \u0026pss-\u003ering_out_tail))\n+\t\t\t/* come back as soon as we can write more */\n+\t\t\tlws_callback_on_writable(wsi);\n+\n+\t\tbreak;\n+\n+\tcase LWS_CALLBACK_CLIENT_RECEIVE:\n+\n+\t\tlwsl_user(\u0022LWS_CALLBACK_CLIENT_RECEIVE: %4d \u0022\n+\t\t\t \u0022(rpp %5d, first %d, last %d, bin %d)\u005cn\u0022,\n+\t\t\t (int)len, (int)lws_remaining_packet_payload(wsi),\n+\t\t\t lws_is_first_fragment(wsi),\n+\t\t\t lws_is_final_fragment(wsi),\n+\t\t\t lws_frame_is_binary(wsi));\n+\n+\t\t{\n+\t\t\tchar strbuf[256];\n+\t\t\tint l \u003d len;\n+\n+\t\t\tif (l \u003e (int)sizeof(strbuf) - 1)\n+\t\t\t\tl \u003d sizeof(strbuf) - 1;\n+\n+\t\t\tmemcpy(strbuf, in, l);\n+\t\t\tstrbuf[l] \u003d '\u005c0';\n+\n+\t\t\tissue_dbus_signal(wsi, \u0022Receive\u0022, strbuf);\n+\t\t}\n+\t\tbreak;\n+\n+\tcase LWS_CALLBACK_CLIENT_CONNECTION_ERROR:\n+\t\tlwsl_err(\u0022CLIENT_CONNECTION_ERROR: %s\u005cn\u0022,\n+\t\t\t in ? (char *)in : \u0022(null)\u0022);\n+\t\tissue_dbus_signal(wsi, \u0022Status\u0022, \u0022ws client connection error\u0022);\n+\t\tbreak;\n+\n+\tcase LWS_CALLBACK_CLIENT_CLOSED:\n+\t\tlwsl_err(\u0022LWS_CALLBACK_CLIENT_CLOSED ()\u005cn\u0022);\n+\t\tissue_dbus_signal(wsi, \u0022Status\u0022, \u0022ws client connection closed\u0022);\n+\n+\t\t/* destroy any ringbuffer and pending messages */\n+\n+\t\tlws_ring_destroy(pss-\u003ering_out);\n+\n+\t\twspctx \u003d lws_get_opaque_parent_data(wsi);\n+\t\tif (!wspctx)\n+\t\t\tbreak;\n+\n+\t\t/*\n+\t\t * the wspctx cannot refer to its child wsi any longer, it is\n+\t\t * about to go out of scope.\n+\t\t */\n+\n+\t\twspctx-\u003ecwsi \u003d NULL;\n+\t\twspctx-\u003epss \u003d NULL;\n+\t\tbreak;\n+\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+#define LWS_PLUGIN_PROTOCOL_MINIMAL_DBUS_WSPROXY \u005c\n+\t{ \u005c\n+\t\t\u0022lws-minimal-dbus-wsproxy\u0022, \u005c\n+\t\tcallback_minimal_dbus_wsproxy, \u005c\n+\t\tsizeof(struct pss_dbus_proxy), \u005c\n+\t\t1024, \u005c\n+\t\t0, NULL, 0 \u005c\n+\t}\n+\n+#if !defined (LWS_PLUGIN_STATIC)\n+\n+/* boilerplate needed if we are built as a dynamic plugin */\n+\n+static const struct lws_protocols protocols[] \u003d {\n+\tLWS_PLUGIN_PROTOCOL_MINIMAL_DBUS_WSPROXY\n+};\n+\n+LWS_EXTERN LWS_VISIBLE int\n+init_protocol_minimal_dbus_wsproxy(struct lws_context *context,\n+\t\t\t struct lws_plugin_capability *c)\n+{\n+\tif (c-\u003eapi_magic !\u003d LWS_PLUGIN_API_MAGIC) {\n+\t\tlwsl_err(\u0022Plugin API %d, library API %d\u0022, LWS_PLUGIN_API_MAGIC,\n+\t\t\t c-\u003eapi_magic);\n+\t\treturn 1;\n+\t}\n+\n+\tc-\u003eprotocols \u003d protocols;\n+\tc-\u003ecount_protocols \u003d LWS_ARRAY_SIZE(protocols);\n+\tc-\u003eextensions \u003d NULL;\n+\tc-\u003ecount_extensions \u003d 0;\n+\n+\treturn 0;\n+}\n+\n+LWS_EXTERN LWS_VISIBLE int\n+destroy_protocol_minimal_dbus_wsproxy(struct lws_context *context)\n+{\n+\treturn 0;\n+}\n+#endif\ndiff --git a/scripts/test-dbus-proxy.sh b/scripts/test-dbus-proxy.sh\nnew file mode 100755\nindex 0000000..1aec16f\n--- /dev/null\n+++ b/scripts/test-dbus-proxy.sh\n@@ -0,0 +1,34 @@\n+#!/bin/sh\n+\n+echo \u0022Starting $0\u0022\n+\n+bin/lws-minimal-dbus-ws-proxy 2\u003e /tmp/dbuss\u0026\n+\n+echo \u0022 server starting\u0022\n+sleep 1s\n+PID_PROX\u003d$!\n+\n+echo \u0022 client starting\u0022\n+bin/lws-minimal-dbus-ws-proxy-testclient -x 10 2\u003e /tmp/dbusc\n+R\u003d$?\n+\n+kill -2 $PID_PROX\n+\n+if [ $R -ne 0 ] ; then\n+\techo \u0022$0 FAILED\u0022\n+\tcat /tmp/dbuss\n+\tcat /tmp/dbusc\n+\texit 1\n+fi\n+\n+if [ -z \u0022`cat /tmp/dbusc | grep 'rx: 9, tx: 9'`\u0022 ] ; then\n+\techo \u0022$0 FAILED\u0022\n+\tcat /tmp/dbuss\n+\tcat /tmp/dbusc\n+\texit 1\n+fi\n+\n+echo \u0022$0 PASSED\u0022\n+\n+exit 0\n+\ndiff --git a/scripts/travis_control.sh b/scripts/travis_control.sh\nindex 92e086b..41fc775 100755\n--- a/scripts/travis_control.sh\n+++ b/scripts/travis_control.sh\n@@ -15,6 +15,7 @@ else\n \t\t\tcmake --build . \u0026\u0026\n \t\t\tsudo make install \u0026\u0026\n \t\t\t../minimal-examples/selftests.sh \u0026\u0026\n+\t\t\t../scripts/test-dbus-proxy.sh \u0026\u0026\n \t\t\t../scripts/h2spec.sh \u0026\u0026\n \t\t\t../scripts/attack.sh \u0026\u0026\n \t\t\t../scripts/h2load.sh \u0026\u0026\ndiff --git a/scripts/travis_install.sh b/scripts/travis_install.sh\nindex 4cdeccb..724ced8 100755\n--- a/scripts/travis_install.sh\n+++ b/scripts/travis_install.sh\n@@ -8,7 +8,7 @@ then\n \n \tif [ \u0022$LWS_METHOD\u0022 \u003d\u003d \u0022lwsws\u0022 -o \u0022$LWS_METHOD\u0022 \u003d\u003d \u0022lwsws2\u0022 ];\n \tthen\n-\t\tsudo apt-get install -y -qq realpath libjemalloc1 libev4 libuv-dev\n+\t\tsudo apt-get install -y -qq realpath libjemalloc1 libev4 libuv-dev libdbus-1-dev\n \t\tsudo apt-get remove python-six\n \t\tsudo pip install six\u003e\u003d1.9\n \t\tsudo pip install Twisted\u003d\u003d16.0.0\n@@ -56,6 +56,12 @@ fi\n \n if [ \u0022$TRAVIS_OS_NAME\u0022 \u003d\u003d \u0022osx\u0022 ];\n then\n+\tif [ \u0022$LWS_METHOD\u0022 \u003d\u003d \u0022lwsws\u0022 -o \u0022$LWS_METHOD\u0022 \u003d\u003d \u0022lwsws2\u0022 ];\n+\tthen\n+\t\tbrew update;\n+\t\tbrew install dbus;\n+\tfi\n+\n \tif [ \u0022$LWS_METHOD\u0022 \u003d\u003d \u0022libev\u0022 ];\n \tthen\n \t\tbrew update;\n","s":{"c":1746402546,"u": 15188}}
],"g": 2936,"chitpc": 0,"ehitpc": 0,"indexed":0
,
"ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "7d0a"}