1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * lws-minimal-dbus-server 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Written in 2010-2019 by Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * This file is made available under the Creative Commons CC0 1.0 7d4afb5ceSopenharmony_ci * Universal Public Domain Dedication. 8d4afb5ceSopenharmony_ci * 9d4afb5ceSopenharmony_ci * This demonstrates a minimal session dbus server that uses the lws event loop, 10d4afb5ceSopenharmony_ci * making it possible to integrate it with other lws features. 11d4afb5ceSopenharmony_ci * 12d4afb5ceSopenharmony_ci * The dbus server parts are based on "Sample code illustrating basic use of 13d4afb5ceSopenharmony_ci * D-BUS" (presumed Public Domain) here: 14d4afb5ceSopenharmony_ci * 15d4afb5ceSopenharmony_ci * https://github.com/fbuihuu/samples-dbus/blob/master/dbus-server.c 16d4afb5ceSopenharmony_ci */ 17d4afb5ceSopenharmony_ci 18d4afb5ceSopenharmony_ci#include <stdbool.h> 19d4afb5ceSopenharmony_ci#include <string.h> 20d4afb5ceSopenharmony_ci#include <stdio.h> 21d4afb5ceSopenharmony_ci#include <stdlib.h> 22d4afb5ceSopenharmony_ci#include <unistd.h> 23d4afb5ceSopenharmony_ci#include <signal.h> 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include <libwebsockets.h> 26d4afb5ceSopenharmony_ci#include <libwebsockets/lws-dbus.h> 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_cistatic struct lws_context *context; 29d4afb5ceSopenharmony_cistatic const char *version = "0.1"; 30d4afb5ceSopenharmony_cistatic int interrupted; 31d4afb5ceSopenharmony_cistatic struct lws_dbus_ctx dbus_ctx, ctx_listener; 32d4afb5ceSopenharmony_cistatic char session; 33d4afb5ceSopenharmony_ci 34d4afb5ceSopenharmony_ci#define THIS_INTERFACE "org.libwebsockets.test" 35d4afb5ceSopenharmony_ci#define THIS_OBJECT "/org/libwebsockets/test" 36d4afb5ceSopenharmony_ci#define THIS_BUSNAME "org.libwebsockets.test" 37d4afb5ceSopenharmony_ci 38d4afb5ceSopenharmony_ci#define THIS_LISTEN_PATH "unix:abstract=org.libwebsockets.test" 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_cistatic const char * 41d4afb5ceSopenharmony_ciserver_introspection_xml = 42d4afb5ceSopenharmony_ci DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE 43d4afb5ceSopenharmony_ci "<node>\n" 44d4afb5ceSopenharmony_ci " <interface name='" DBUS_INTERFACE_INTROSPECTABLE "'>\n" 45d4afb5ceSopenharmony_ci " <method name='Introspect'>\n" 46d4afb5ceSopenharmony_ci " <arg name='data' type='s' direction='out' />\n" 47d4afb5ceSopenharmony_ci " </method>\n" 48d4afb5ceSopenharmony_ci " </interface>\n" 49d4afb5ceSopenharmony_ci 50d4afb5ceSopenharmony_ci " <interface name='" DBUS_INTERFACE_PROPERTIES "'>\n" 51d4afb5ceSopenharmony_ci " <method name='Get'>\n" 52d4afb5ceSopenharmony_ci " <arg name='interface' type='s' direction='in' />\n" 53d4afb5ceSopenharmony_ci " <arg name='property' type='s' direction='in' />\n" 54d4afb5ceSopenharmony_ci " <arg name='value' type='s' direction='out' />\n" 55d4afb5ceSopenharmony_ci " </method>\n" 56d4afb5ceSopenharmony_ci " <method name='GetAll'>\n" 57d4afb5ceSopenharmony_ci " <arg name='interface' type='s' direction='in'/>\n" 58d4afb5ceSopenharmony_ci " <arg name='properties' type='a{sv}' direction='out'/>\n" 59d4afb5ceSopenharmony_ci " </method>\n" 60d4afb5ceSopenharmony_ci " </interface>\n" 61d4afb5ceSopenharmony_ci 62d4afb5ceSopenharmony_ci " <interface name='"THIS_INTERFACE"'>\n" 63d4afb5ceSopenharmony_ci " <property name='Version' type='s' access='read' />\n" 64d4afb5ceSopenharmony_ci " <method name='Ping' >\n" 65d4afb5ceSopenharmony_ci " <arg type='s' direction='out' />\n" 66d4afb5ceSopenharmony_ci " </method>\n" 67d4afb5ceSopenharmony_ci " <method name='Echo'>\n" 68d4afb5ceSopenharmony_ci " <arg name='string' direction='in' type='s'/>\n" 69d4afb5ceSopenharmony_ci " <arg type='s' direction='out' />\n" 70d4afb5ceSopenharmony_ci " </method>\n" 71d4afb5ceSopenharmony_ci " <method name='EmitSignal'>\n" 72d4afb5ceSopenharmony_ci " </method>\n" 73d4afb5ceSopenharmony_ci " <method name='Quit'>\n" 74d4afb5ceSopenharmony_ci " </method>\n" 75d4afb5ceSopenharmony_ci " <signal name='OnEmitSignal'>\n" 76d4afb5ceSopenharmony_ci " </signal>" 77d4afb5ceSopenharmony_ci " </interface>\n" 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci "</node>\n"; 80d4afb5ceSopenharmony_ci 81d4afb5ceSopenharmony_cistatic DBusHandlerResult 82d4afb5ceSopenharmony_cidmh_introspect(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d) 83d4afb5ceSopenharmony_ci{ 84d4afb5ceSopenharmony_ci dbus_message_append_args(*reply, DBUS_TYPE_STRING, 85d4afb5ceSopenharmony_ci &server_introspection_xml, DBUS_TYPE_INVALID); 86d4afb5ceSopenharmony_ci 87d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 88d4afb5ceSopenharmony_ci} 89d4afb5ceSopenharmony_ci 90d4afb5ceSopenharmony_cistatic DBusHandlerResult 91d4afb5ceSopenharmony_cidmh_get(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d) 92d4afb5ceSopenharmony_ci{ 93d4afb5ceSopenharmony_ci const char *interface, *property; 94d4afb5ceSopenharmony_ci DBusError err; 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci dbus_error_init(&err); 97d4afb5ceSopenharmony_ci 98d4afb5ceSopenharmony_ci if (!dbus_message_get_args(m, &err, DBUS_TYPE_STRING, &interface, 99d4afb5ceSopenharmony_ci DBUS_TYPE_STRING, &property, 100d4afb5ceSopenharmony_ci DBUS_TYPE_INVALID)) { 101d4afb5ceSopenharmony_ci dbus_message_unref(*reply); 102d4afb5ceSopenharmony_ci *reply = dbus_message_new_error(m, err.name, err.message); 103d4afb5ceSopenharmony_ci dbus_error_free(&err); 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 106d4afb5ceSopenharmony_ci } 107d4afb5ceSopenharmony_ci 108d4afb5ceSopenharmony_ci if (strcmp(property, "Version")) /* Unknown property */ 109d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 110d4afb5ceSopenharmony_ci 111d4afb5ceSopenharmony_ci dbus_message_append_args(*reply, DBUS_TYPE_STRING, &version, 112d4afb5ceSopenharmony_ci DBUS_TYPE_INVALID); 113d4afb5ceSopenharmony_ci 114d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 115d4afb5ceSopenharmony_ci} 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_cistatic DBusHandlerResult 118d4afb5ceSopenharmony_cidmh_getall(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d) 119d4afb5ceSopenharmony_ci{ 120d4afb5ceSopenharmony_ci DBusMessageIter arr, di, iter, va; 121d4afb5ceSopenharmony_ci const char *property = "Version"; 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_ci dbus_message_iter_init_append(*reply, &iter); 124d4afb5ceSopenharmony_ci dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &arr); 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci /* Append all properties name/value pairs */ 127d4afb5ceSopenharmony_ci dbus_message_iter_open_container(&arr, DBUS_TYPE_DICT_ENTRY, NULL, &di); 128d4afb5ceSopenharmony_ci dbus_message_iter_append_basic(&di, DBUS_TYPE_STRING, &property); 129d4afb5ceSopenharmony_ci dbus_message_iter_open_container(&di, DBUS_TYPE_VARIANT, "s", &va); 130d4afb5ceSopenharmony_ci dbus_message_iter_append_basic(&va, DBUS_TYPE_STRING, &version); 131d4afb5ceSopenharmony_ci dbus_message_iter_close_container(&di, &va); 132d4afb5ceSopenharmony_ci dbus_message_iter_close_container(&arr, &di); 133d4afb5ceSopenharmony_ci 134d4afb5ceSopenharmony_ci dbus_message_iter_close_container(&iter, &arr); 135d4afb5ceSopenharmony_ci 136d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 137d4afb5ceSopenharmony_ci} 138d4afb5ceSopenharmony_ci 139d4afb5ceSopenharmony_cistatic DBusHandlerResult 140d4afb5ceSopenharmony_cidmh_ping(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d) 141d4afb5ceSopenharmony_ci{ 142d4afb5ceSopenharmony_ci const char *pong = "Pong"; 143d4afb5ceSopenharmony_ci 144d4afb5ceSopenharmony_ci dbus_message_append_args(*reply, DBUS_TYPE_STRING, &pong, 145d4afb5ceSopenharmony_ci DBUS_TYPE_INVALID); 146d4afb5ceSopenharmony_ci 147d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 148d4afb5ceSopenharmony_ci} 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_cistatic DBusHandlerResult 151d4afb5ceSopenharmony_cidmh_echo(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d) 152d4afb5ceSopenharmony_ci{ 153d4afb5ceSopenharmony_ci const char *msg; 154d4afb5ceSopenharmony_ci DBusError err; 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci dbus_error_init(&err); 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci if (!dbus_message_get_args(m, &err, DBUS_TYPE_STRING, 159d4afb5ceSopenharmony_ci &msg, DBUS_TYPE_INVALID)) { 160d4afb5ceSopenharmony_ci dbus_message_unref(*reply); 161d4afb5ceSopenharmony_ci *reply = dbus_message_new_error(m, err.name, err.message); 162d4afb5ceSopenharmony_ci dbus_error_free(&err); 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 165d4afb5ceSopenharmony_ci } 166d4afb5ceSopenharmony_ci 167d4afb5ceSopenharmony_ci dbus_message_append_args(*reply, DBUS_TYPE_STRING, &msg, 168d4afb5ceSopenharmony_ci DBUS_TYPE_INVALID); 169d4afb5ceSopenharmony_ci 170d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 171d4afb5ceSopenharmony_ci} 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_cistatic DBusHandlerResult 174d4afb5ceSopenharmony_cidmh_emit_signal(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d) 175d4afb5ceSopenharmony_ci{ 176d4afb5ceSopenharmony_ci DBusMessage *r = dbus_message_new_signal(THIS_OBJECT, THIS_INTERFACE, 177d4afb5ceSopenharmony_ci "OnEmitSignal"); 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci if (!r) 180d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci if (!dbus_connection_send(c, r, NULL)) 183d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_NEED_MEMORY; 184d4afb5ceSopenharmony_ci 185d4afb5ceSopenharmony_ci /* and send the original empty reply after */ 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 188d4afb5ceSopenharmony_ci} 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_cistatic DBusHandlerResult 191d4afb5ceSopenharmony_cidmh_emit_quit(DBusConnection *c, DBusMessage *m, DBusMessage **reply, void *d) 192d4afb5ceSopenharmony_ci{ 193d4afb5ceSopenharmony_ci interrupted = 1; 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_HANDLED; 196d4afb5ceSopenharmony_ci} 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_cistruct lws_dbus_methods { 199d4afb5ceSopenharmony_ci const char *inter; 200d4afb5ceSopenharmony_ci const char *call; 201d4afb5ceSopenharmony_ci lws_dbus_message_handler handler; 202d4afb5ceSopenharmony_ci} meths[] = { 203d4afb5ceSopenharmony_ci { DBUS_INTERFACE_INTROSPECTABLE, "Introspect", dmh_introspect }, 204d4afb5ceSopenharmony_ci { DBUS_INTERFACE_PROPERTIES, "Get", dmh_get }, 205d4afb5ceSopenharmony_ci { DBUS_INTERFACE_PROPERTIES, "GetAll", dmh_getall }, 206d4afb5ceSopenharmony_ci { THIS_INTERFACE, "Ping", dmh_ping }, 207d4afb5ceSopenharmony_ci { THIS_INTERFACE, "Echo", dmh_echo }, 208d4afb5ceSopenharmony_ci { THIS_INTERFACE, "EmitSignal", dmh_emit_signal }, 209d4afb5ceSopenharmony_ci { THIS_INTERFACE, "Quit", dmh_emit_quit }, 210d4afb5ceSopenharmony_ci}; 211d4afb5ceSopenharmony_ci 212d4afb5ceSopenharmony_cistatic DBusHandlerResult 213d4afb5ceSopenharmony_ciserver_message_handler(DBusConnection *conn, DBusMessage *message, void *data) 214d4afb5ceSopenharmony_ci{ 215d4afb5ceSopenharmony_ci struct lws_dbus_methods *mp = meths; 216d4afb5ceSopenharmony_ci DBusHandlerResult result; 217d4afb5ceSopenharmony_ci DBusMessage *reply = NULL; 218d4afb5ceSopenharmony_ci size_t n; 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_ci lwsl_info("%s: Got D-Bus request: %s.%s on %s\n", __func__, 221d4afb5ceSopenharmony_ci dbus_message_get_interface(message), 222d4afb5ceSopenharmony_ci dbus_message_get_member(message), 223d4afb5ceSopenharmony_ci dbus_message_get_path(message)); 224d4afb5ceSopenharmony_ci 225d4afb5ceSopenharmony_ci for (n = 0; n < LWS_ARRAY_SIZE(meths); n++) { 226d4afb5ceSopenharmony_ci if (dbus_message_is_method_call(message, mp->inter, mp->call)) { 227d4afb5ceSopenharmony_ci reply = dbus_message_new_method_return(message); 228d4afb5ceSopenharmony_ci if (!reply) 229d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_NEED_MEMORY; 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_ci result = mp->handler(conn, message, &reply, data); 232d4afb5ceSopenharmony_ci 233d4afb5ceSopenharmony_ci if (result == DBUS_HANDLER_RESULT_HANDLED && 234d4afb5ceSopenharmony_ci !dbus_connection_send(conn, reply, NULL)) 235d4afb5ceSopenharmony_ci result = DBUS_HANDLER_RESULT_NEED_MEMORY; 236d4afb5ceSopenharmony_ci 237d4afb5ceSopenharmony_ci dbus_message_unref(reply); 238d4afb5ceSopenharmony_ci 239d4afb5ceSopenharmony_ci return result; 240d4afb5ceSopenharmony_ci } 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci mp++; 243d4afb5ceSopenharmony_ci } 244d4afb5ceSopenharmony_ci 245d4afb5ceSopenharmony_ci return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 246d4afb5ceSopenharmony_ci} 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_cistatic const DBusObjectPathVTable server_vtable = { 249d4afb5ceSopenharmony_ci .message_function = server_message_handler 250d4afb5ceSopenharmony_ci}; 251d4afb5ceSopenharmony_ci 252d4afb5ceSopenharmony_cistatic void 253d4afb5ceSopenharmony_cidestroy_dbus_server_conn(struct lws_dbus_ctx *ctx) 254d4afb5ceSopenharmony_ci{ 255d4afb5ceSopenharmony_ci if (!ctx->conn) 256d4afb5ceSopenharmony_ci return; 257d4afb5ceSopenharmony_ci 258d4afb5ceSopenharmony_ci lwsl_notice("%s\n", __func__); 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ci dbus_connection_unregister_object_path(ctx->conn, THIS_OBJECT); 261d4afb5ceSopenharmony_ci lws_dll2_remove(&ctx->next); 262d4afb5ceSopenharmony_ci dbus_connection_unref(ctx->conn); 263d4afb5ceSopenharmony_ci} 264d4afb5ceSopenharmony_ci 265d4afb5ceSopenharmony_cistatic void 266d4afb5ceSopenharmony_cicb_closing(struct lws_dbus_ctx *ctx) 267d4afb5ceSopenharmony_ci{ 268d4afb5ceSopenharmony_ci lwsl_err("%s: closing\n", __func__); 269d4afb5ceSopenharmony_ci destroy_dbus_server_conn(ctx); 270d4afb5ceSopenharmony_ci 271d4afb5ceSopenharmony_ci free(ctx); 272d4afb5ceSopenharmony_ci} 273d4afb5ceSopenharmony_ci 274d4afb5ceSopenharmony_ci 275d4afb5ceSopenharmony_cistatic void 276d4afb5ceSopenharmony_cinew_conn(DBusServer *server, DBusConnection *conn, void *data) 277d4afb5ceSopenharmony_ci{ 278d4afb5ceSopenharmony_ci struct lws_dbus_ctx *conn_ctx, *ctx = (struct lws_dbus_ctx *)data; 279d4afb5ceSopenharmony_ci 280d4afb5ceSopenharmony_ci lwsl_notice("%s: vh %s\n", __func__, lws_get_vhost_name(ctx->vh)); 281d4afb5ceSopenharmony_ci 282d4afb5ceSopenharmony_ci conn_ctx = malloc(sizeof(*conn_ctx)); 283d4afb5ceSopenharmony_ci if (!conn_ctx) 284d4afb5ceSopenharmony_ci return; 285d4afb5ceSopenharmony_ci 286d4afb5ceSopenharmony_ci memset(conn_ctx, 0, sizeof(*conn_ctx)); 287d4afb5ceSopenharmony_ci 288d4afb5ceSopenharmony_ci conn_ctx->tsi = ctx->tsi; 289d4afb5ceSopenharmony_ci conn_ctx->vh = ctx->vh; 290d4afb5ceSopenharmony_ci conn_ctx->conn = conn; 291d4afb5ceSopenharmony_ci 292d4afb5ceSopenharmony_ci if (lws_dbus_connection_setup(conn_ctx, conn, cb_closing)) { 293d4afb5ceSopenharmony_ci lwsl_err("%s: connection bind to lws failed\n", __func__); 294d4afb5ceSopenharmony_ci goto bail; 295d4afb5ceSopenharmony_ci } 296d4afb5ceSopenharmony_ci 297d4afb5ceSopenharmony_ci if (!dbus_connection_register_object_path(conn, THIS_OBJECT, 298d4afb5ceSopenharmony_ci &server_vtable, conn_ctx)) { 299d4afb5ceSopenharmony_ci lwsl_err("%s: Failed to register object path\n", __func__); 300d4afb5ceSopenharmony_ci goto bail; 301d4afb5ceSopenharmony_ci } 302d4afb5ceSopenharmony_ci 303d4afb5ceSopenharmony_ci lws_dll2_add_head(&conn_ctx->next, &ctx->owner); 304d4afb5ceSopenharmony_ci 305d4afb5ceSopenharmony_ci /* we take on responsibility for explicit close / unref with this... */ 306d4afb5ceSopenharmony_ci dbus_connection_ref(conn); 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_ci return; 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_cibail: 311d4afb5ceSopenharmony_ci free(conn_ctx); 312d4afb5ceSopenharmony_ci} 313d4afb5ceSopenharmony_ci 314d4afb5ceSopenharmony_cistatic int 315d4afb5ceSopenharmony_cicreate_dbus_listener(const char *ads) 316d4afb5ceSopenharmony_ci{ 317d4afb5ceSopenharmony_ci DBusError e; 318d4afb5ceSopenharmony_ci 319d4afb5ceSopenharmony_ci dbus_error_init(&e); 320d4afb5ceSopenharmony_ci 321d4afb5ceSopenharmony_ci if (!lws_dbus_server_listen(&ctx_listener, ads, &e, new_conn)) { 322d4afb5ceSopenharmony_ci lwsl_err("%s: failed\n", __func__); 323d4afb5ceSopenharmony_ci dbus_error_free(&e); 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci return 1; 326d4afb5ceSopenharmony_ci } 327d4afb5ceSopenharmony_ci 328d4afb5ceSopenharmony_ci return 0; 329d4afb5ceSopenharmony_ci} 330d4afb5ceSopenharmony_ci 331d4afb5ceSopenharmony_cistatic int 332d4afb5ceSopenharmony_cicreate_dbus_server_conn(struct lws_dbus_ctx *ctx, DBusBusType type) 333d4afb5ceSopenharmony_ci{ 334d4afb5ceSopenharmony_ci DBusError err; 335d4afb5ceSopenharmony_ci int rv; 336d4afb5ceSopenharmony_ci 337d4afb5ceSopenharmony_ci dbus_error_init(&err); 338d4afb5ceSopenharmony_ci 339d4afb5ceSopenharmony_ci /* connect to the daemon bus */ 340d4afb5ceSopenharmony_ci ctx->conn = dbus_bus_get(type, &err); 341d4afb5ceSopenharmony_ci if (!ctx->conn) { 342d4afb5ceSopenharmony_ci lwsl_err("%s: Failed to get a session DBus connection: %s\n", 343d4afb5ceSopenharmony_ci __func__, err.message); 344d4afb5ceSopenharmony_ci goto fail; 345d4afb5ceSopenharmony_ci } 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ci /* 348d4afb5ceSopenharmony_ci * by default dbus will call exit() when this connection closes... 349d4afb5ceSopenharmony_ci * we have to shut down other things cleanly, so disable that 350d4afb5ceSopenharmony_ci */ 351d4afb5ceSopenharmony_ci dbus_connection_set_exit_on_disconnect(ctx->conn, 0); 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ci rv = dbus_bus_request_name(ctx->conn, THIS_BUSNAME, 354d4afb5ceSopenharmony_ci DBUS_NAME_FLAG_REPLACE_EXISTING, &err); 355d4afb5ceSopenharmony_ci if (rv != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { 356d4afb5ceSopenharmony_ci lwsl_err("%s: Failed to request name on bus: %s\n", 357d4afb5ceSopenharmony_ci __func__, err.message); 358d4afb5ceSopenharmony_ci goto fail; 359d4afb5ceSopenharmony_ci } 360d4afb5ceSopenharmony_ci 361d4afb5ceSopenharmony_ci if (!dbus_connection_register_object_path(ctx->conn, THIS_OBJECT, 362d4afb5ceSopenharmony_ci &server_vtable, NULL)) { 363d4afb5ceSopenharmony_ci lwsl_err("%s: Failed to register object path for TestObject\n", 364d4afb5ceSopenharmony_ci __func__); 365d4afb5ceSopenharmony_ci dbus_bus_release_name(ctx->conn, THIS_BUSNAME, &err); 366d4afb5ceSopenharmony_ci goto fail; 367d4afb5ceSopenharmony_ci } 368d4afb5ceSopenharmony_ci 369d4afb5ceSopenharmony_ci /* 370d4afb5ceSopenharmony_ci * This is the part that binds the connection to lws watcher and 371d4afb5ceSopenharmony_ci * timeout handling provided by lws 372d4afb5ceSopenharmony_ci */ 373d4afb5ceSopenharmony_ci 374d4afb5ceSopenharmony_ci if (lws_dbus_connection_setup(ctx, ctx->conn, cb_closing)) { 375d4afb5ceSopenharmony_ci lwsl_err("%s: connection bind to lws failed\n", __func__); 376d4afb5ceSopenharmony_ci goto fail; 377d4afb5ceSopenharmony_ci } 378d4afb5ceSopenharmony_ci 379d4afb5ceSopenharmony_ci lwsl_notice("%s: created OK\n", __func__); 380d4afb5ceSopenharmony_ci 381d4afb5ceSopenharmony_ci return 0; 382d4afb5ceSopenharmony_ci 383d4afb5ceSopenharmony_cifail: 384d4afb5ceSopenharmony_ci dbus_error_free(&err); 385d4afb5ceSopenharmony_ci 386d4afb5ceSopenharmony_ci return 1; 387d4afb5ceSopenharmony_ci} 388d4afb5ceSopenharmony_ci 389d4afb5ceSopenharmony_ci/* 390d4afb5ceSopenharmony_ci * Cleanly release the connection 391d4afb5ceSopenharmony_ci */ 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_cistatic void 394d4afb5ceSopenharmony_cidestroy_dbus_server_listener(struct lws_dbus_ctx *ctx) 395d4afb5ceSopenharmony_ci{ 396d4afb5ceSopenharmony_ci dbus_server_disconnect(ctx->dbs); 397d4afb5ceSopenharmony_ci 398d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, rdt, nx, 399d4afb5ceSopenharmony_ci ctx->owner.head) { 400d4afb5ceSopenharmony_ci struct lws_dbus_ctx *r = 401d4afb5ceSopenharmony_ci lws_container_of(rdt, struct lws_dbus_ctx, next); 402d4afb5ceSopenharmony_ci 403d4afb5ceSopenharmony_ci dbus_connection_close(r->conn); 404d4afb5ceSopenharmony_ci dbus_connection_unref(r->conn); 405d4afb5ceSopenharmony_ci free(r); 406d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(rdt, nx); 407d4afb5ceSopenharmony_ci 408d4afb5ceSopenharmony_ci dbus_server_unref(ctx->dbs); 409d4afb5ceSopenharmony_ci} 410d4afb5ceSopenharmony_ci 411d4afb5ceSopenharmony_ci/* 412d4afb5ceSopenharmony_ci * DBUS can send messages outside the usual client-initiated RPC concept. 413d4afb5ceSopenharmony_ci * 414d4afb5ceSopenharmony_ci * You can receive them using a message filter. 415d4afb5ceSopenharmony_ci */ 416d4afb5ceSopenharmony_ci 417d4afb5ceSopenharmony_cistatic void 418d4afb5ceSopenharmony_cispam_connected_clients(struct lws_dbus_ctx *ctx) 419d4afb5ceSopenharmony_ci{ 420d4afb5ceSopenharmony_ci 421d4afb5ceSopenharmony_ci /* send connected clients an unsolicited message */ 422d4afb5ceSopenharmony_ci 423d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, rdt, nx, 424d4afb5ceSopenharmony_ci ctx->owner.head) { 425d4afb5ceSopenharmony_ci struct lws_dbus_ctx *r = 426d4afb5ceSopenharmony_ci lws_container_of(rdt, struct lws_dbus_ctx, next); 427d4afb5ceSopenharmony_ci 428d4afb5ceSopenharmony_ci 429d4afb5ceSopenharmony_ci DBusMessage *msg; 430d4afb5ceSopenharmony_ci const char *payload = "Unsolicited message"; 431d4afb5ceSopenharmony_ci 432d4afb5ceSopenharmony_ci msg = dbus_message_new(DBUS_NUM_MESSAGE_TYPES + 1); 433d4afb5ceSopenharmony_ci if (!msg) { 434d4afb5ceSopenharmony_ci lwsl_err("%s: new message failed\n", __func__); 435d4afb5ceSopenharmony_ci } 436d4afb5ceSopenharmony_ci 437d4afb5ceSopenharmony_ci dbus_message_append_args(msg, DBUS_TYPE_STRING, &payload, 438d4afb5ceSopenharmony_ci DBUS_TYPE_INVALID); 439d4afb5ceSopenharmony_ci if (!dbus_connection_send(r->conn, msg, NULL)) { 440d4afb5ceSopenharmony_ci lwsl_err("%s: unable to send\n", __func__); 441d4afb5ceSopenharmony_ci } 442d4afb5ceSopenharmony_ci 443d4afb5ceSopenharmony_ci lwsl_notice("%s\n", __func__); 444d4afb5ceSopenharmony_ci 445d4afb5ceSopenharmony_ci dbus_message_unref(msg); 446d4afb5ceSopenharmony_ci 447d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(rdt, nx); 448d4afb5ceSopenharmony_ci 449d4afb5ceSopenharmony_ci} 450d4afb5ceSopenharmony_ci 451d4afb5ceSopenharmony_ci 452d4afb5ceSopenharmony_civoid sigint_handler(int sig) 453d4afb5ceSopenharmony_ci{ 454d4afb5ceSopenharmony_ci interrupted = 1; 455d4afb5ceSopenharmony_ci} 456d4afb5ceSopenharmony_ci 457d4afb5ceSopenharmony_ciint main(int argc, const char **argv) 458d4afb5ceSopenharmony_ci{ 459d4afb5ceSopenharmony_ci struct lws_context_creation_info info; 460d4afb5ceSopenharmony_ci const char *p; 461d4afb5ceSopenharmony_ci int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE 462d4afb5ceSopenharmony_ci /* for LLL_ verbosity above NOTICE to be built into lws, 463d4afb5ceSopenharmony_ci * lws must have been configured and built with 464d4afb5ceSopenharmony_ci * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */ 465d4afb5ceSopenharmony_ci /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */ 466d4afb5ceSopenharmony_ci /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */ 467d4afb5ceSopenharmony_ci /* | LLL_DEBUG */ /* | LLL_THREAD */; 468d4afb5ceSopenharmony_ci 469d4afb5ceSopenharmony_ci signal(SIGINT, sigint_handler); 470d4afb5ceSopenharmony_ci 471d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-d"))) 472d4afb5ceSopenharmony_ci logs = atoi(p); 473d4afb5ceSopenharmony_ci 474d4afb5ceSopenharmony_ci lws_set_log_level(logs, NULL); 475d4afb5ceSopenharmony_ci lwsl_user("LWS minimal DBUS server\n"); 476d4afb5ceSopenharmony_ci 477d4afb5ceSopenharmony_ci memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 478d4afb5ceSopenharmony_ci info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS; 479d4afb5ceSopenharmony_ci context = lws_create_context(&info); 480d4afb5ceSopenharmony_ci if (!context) { 481d4afb5ceSopenharmony_ci lwsl_err("lws init failed\n"); 482d4afb5ceSopenharmony_ci return 1; 483d4afb5ceSopenharmony_ci } 484d4afb5ceSopenharmony_ci 485d4afb5ceSopenharmony_ci info.options |= 486d4afb5ceSopenharmony_ci LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; 487d4afb5ceSopenharmony_ci 488d4afb5ceSopenharmony_ci dbus_ctx.tsi = 0; 489d4afb5ceSopenharmony_ci ctx_listener.tsi = 0; 490d4afb5ceSopenharmony_ci ctx_listener.vh = dbus_ctx.vh = lws_create_vhost(context, &info); 491d4afb5ceSopenharmony_ci if (!dbus_ctx.vh) 492d4afb5ceSopenharmony_ci goto bail; 493d4afb5ceSopenharmony_ci 494d4afb5ceSopenharmony_ci session = !!lws_cmdline_option(argc, argv, "--session"); 495d4afb5ceSopenharmony_ci 496d4afb5ceSopenharmony_ci if (session) { 497d4afb5ceSopenharmony_ci /* create the dbus connection, loosely bound to our lws vhost */ 498d4afb5ceSopenharmony_ci 499d4afb5ceSopenharmony_ci if (create_dbus_server_conn(&dbus_ctx, DBUS_BUS_SESSION)) 500d4afb5ceSopenharmony_ci goto bail; 501d4afb5ceSopenharmony_ci } else { 502d4afb5ceSopenharmony_ci if (create_dbus_listener(THIS_LISTEN_PATH)) { 503d4afb5ceSopenharmony_ci lwsl_err("%s: create_dbus_listener failed\n", __func__); 504d4afb5ceSopenharmony_ci goto bail; 505d4afb5ceSopenharmony_ci } 506d4afb5ceSopenharmony_ci } 507d4afb5ceSopenharmony_ci 508d4afb5ceSopenharmony_ci /* lws event loop (default poll one) */ 509d4afb5ceSopenharmony_ci 510d4afb5ceSopenharmony_ci while (n >= 0 && !interrupted) { 511d4afb5ceSopenharmony_ci if (!session) 512d4afb5ceSopenharmony_ci spam_connected_clients(&ctx_listener); 513d4afb5ceSopenharmony_ci n = lws_service(context, 0); 514d4afb5ceSopenharmony_ci } 515d4afb5ceSopenharmony_ci 516d4afb5ceSopenharmony_ci if (session) 517d4afb5ceSopenharmony_ci destroy_dbus_server_conn(&dbus_ctx); 518d4afb5ceSopenharmony_ci else 519d4afb5ceSopenharmony_ci destroy_dbus_server_listener(&ctx_listener); 520d4afb5ceSopenharmony_ci 521d4afb5ceSopenharmony_ci /* this is required for valgrind-cleanliness */ 522d4afb5ceSopenharmony_ci dbus_shutdown(); 523d4afb5ceSopenharmony_ci lws_context_destroy(context); 524d4afb5ceSopenharmony_ci 525d4afb5ceSopenharmony_ci lwsl_notice("Exiting cleanly\n"); 526d4afb5ceSopenharmony_ci 527d4afb5ceSopenharmony_ci return 0; 528d4afb5ceSopenharmony_ci 529d4afb5ceSopenharmony_cibail: 530d4afb5ceSopenharmony_ci lwsl_err("%s: failed to start\n", __func__); 531d4afb5ceSopenharmony_ci 532d4afb5ceSopenharmony_ci lws_context_destroy(context); 533d4afb5ceSopenharmony_ci 534d4afb5ceSopenharmony_ci return 1; 535d4afb5ceSopenharmony_ci} 536