dbus-service.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149
  1. /*
  2. *
  3. * Embedded Linux library
  4. *
  5. * Copyright (C) 2011-2014 Intel Corporation. All rights reserved.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #define _GNU_SOURCE
  26. #include <string.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include "useful.h"
  30. #include "queue.h"
  31. #include "string.h"
  32. #include "hashmap.h"
  33. #include "dbus.h"
  34. #include "dbus-service.h"
  35. #include "dbus-private.h"
  36. #include "private.h"
  37. #include "idle.h"
  38. #define XML_ID "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
  39. #define XML_DTD "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
  40. #define XML_HEAD "<!DOCTYPE node PUBLIC \""XML_ID"\"\n\""XML_DTD"\">\n"
  41. static const char *static_introspectable =
  42. "\t<interface name=\"org.freedesktop.DBus.Introspectable\">\n"
  43. "\t\t<method name=\"Introspect\">\n"
  44. "\t\t\t<arg name=\"xml\" type=\"s\" direction=\"out\"/>\n"
  45. "\t\t</method>\n\t</interface>\n";
  46. struct _dbus_method {
  47. l_dbus_interface_method_cb_t cb;
  48. uint32_t flags;
  49. unsigned char name_len;
  50. char metainfo[];
  51. };
  52. struct _dbus_signal {
  53. uint32_t flags;
  54. unsigned char name_len;
  55. char metainfo[];
  56. };
  57. struct _dbus_property {
  58. l_dbus_property_get_cb_t getter;
  59. l_dbus_property_set_cb_t setter;
  60. uint32_t flags;
  61. unsigned char name_len;
  62. char metainfo[];
  63. };
  64. struct l_dbus_interface {
  65. struct l_queue *methods;
  66. struct l_queue *signals;
  67. struct l_queue *properties;
  68. bool handle_old_style_properties;
  69. void (*instance_destroy)(void *);
  70. char name[];
  71. };
  72. struct child_node {
  73. struct object_node *node;
  74. struct child_node *next;
  75. char subpath[];
  76. };
  77. struct interface_instance {
  78. struct l_dbus_interface *interface;
  79. void *user_data;
  80. };
  81. struct object_node {
  82. struct object_node *parent;
  83. struct l_queue *instances;
  84. struct child_node *children;
  85. void *user_data;
  86. void (*destroy) (void *);
  87. };
  88. struct object_manager {
  89. char *path;
  90. struct l_dbus *dbus;
  91. struct l_queue *announce_added;
  92. struct l_queue *announce_removed;
  93. };
  94. struct interface_add_record {
  95. char *path;
  96. struct object_node *object;
  97. struct l_queue *instances;
  98. };
  99. struct interface_remove_record {
  100. char *path;
  101. struct object_node *object;
  102. struct l_queue *interface_names;
  103. };
  104. struct property_change_record {
  105. char *path;
  106. struct object_node *object;
  107. struct interface_instance *instance;
  108. struct l_queue *properties;
  109. };
  110. struct _dbus_object_tree {
  111. struct l_hashmap *interfaces;
  112. struct l_hashmap *objects;
  113. struct object_node *root;
  114. struct l_queue *object_managers;
  115. struct l_queue *property_changes;
  116. struct l_idle *emit_signals_work;
  117. bool flushing;
  118. };
  119. void _dbus_method_introspection(struct _dbus_method *info,
  120. struct l_string *buf)
  121. {
  122. const char *sig;
  123. const char *end;
  124. const char *pname;
  125. unsigned int offset = info->name_len + 1;
  126. l_string_append_printf(buf, "\t\t<method name=\"%s\">\n",
  127. info->metainfo);
  128. sig = info->metainfo + offset;
  129. offset += strlen(sig) + 1;
  130. for (; *sig; sig++) {
  131. end = _dbus_signature_end(sig);
  132. pname = info->metainfo + offset;
  133. l_string_append_printf(buf, "\t\t\t<arg name=\"%s\" "
  134. "type=\"%.*s\" direction=\"in\"/>\n",
  135. pname, (int) (end - sig + 1), sig);
  136. sig = end;
  137. offset += strlen(pname) + 1;
  138. }
  139. sig = info->metainfo + offset;
  140. offset += strlen(sig) + 1;
  141. for (; *sig; sig++) {
  142. end = _dbus_signature_end(sig);
  143. pname = info->metainfo + offset;
  144. l_string_append_printf(buf, "\t\t\t<arg name=\"%s\" "
  145. "type=\"%.*s\" direction=\"out\"/>\n",
  146. pname, (int) (end - sig + 1), sig);
  147. sig = end;
  148. offset += strlen(pname) + 1;
  149. }
  150. if (info->flags & L_DBUS_METHOD_FLAG_DEPRECATED)
  151. l_string_append(buf, "\t\t\t<annotation name=\""
  152. "org.freedesktop.DBus.Deprecated\" "
  153. "value=\"true\"/>\n");
  154. if (info->flags & L_DBUS_METHOD_FLAG_NOREPLY)
  155. l_string_append(buf, "\t\t\t<annotation name=\""
  156. "org.freedesktop.DBus.Method.NoReply\" "
  157. "value=\"true\"/>\n");
  158. l_string_append(buf, "\t\t</method>\n");
  159. }
  160. void _dbus_signal_introspection(struct _dbus_signal *info,
  161. struct l_string *buf)
  162. {
  163. const char *sig;
  164. const char *end;
  165. const char *pname;
  166. unsigned int offset = info->name_len + 1;
  167. l_string_append_printf(buf, "\t\t<signal name=\"%s\">\n",
  168. info->metainfo);
  169. sig = info->metainfo + offset;
  170. offset += strlen(sig) + 1;
  171. for (; *sig; sig++) {
  172. end = _dbus_signature_end(sig);
  173. pname = info->metainfo + offset;
  174. l_string_append_printf(buf, "\t\t\t<arg name=\"%s\" "
  175. "type=\"%.*s\"/>\n",
  176. pname, (int) (end - sig + 1), sig);
  177. sig = end;
  178. offset += strlen(pname) + 1;
  179. }
  180. if (info->flags & L_DBUS_SIGNAL_FLAG_DEPRECATED)
  181. l_string_append(buf, "\t\t\t<annotation name=\""
  182. "org.freedesktop.DBus.Deprecated\" "
  183. "value=\"true\"/>\n");
  184. l_string_append(buf, "\t\t</signal>\n");
  185. }
  186. void _dbus_property_introspection(struct _dbus_property *info,
  187. struct l_string *buf)
  188. {
  189. unsigned int offset = info->name_len + 1;
  190. const char *signature = info->metainfo + offset;
  191. l_string_append_printf(buf, "\t\t<property name=\"%s\" type=\"%s\" ",
  192. info->metainfo, signature);
  193. if (info->setter)
  194. l_string_append(buf, "access=\"readwrite\"");
  195. else
  196. l_string_append(buf, "access=\"read\"");
  197. if (info->flags & L_DBUS_METHOD_FLAG_DEPRECATED) {
  198. l_string_append(buf, ">\n");
  199. l_string_append(buf, "\t\t\t<annotation name=\""
  200. "org.freedesktop.DBus.Deprecated\" "
  201. "value=\"true\"/>\n");
  202. l_string_append(buf, "\t\t</property>\n");
  203. } else
  204. l_string_append(buf, "/>\n");
  205. }
  206. void _dbus_interface_introspection(struct l_dbus_interface *interface,
  207. struct l_string *buf)
  208. {
  209. l_string_append_printf(buf, "\t<interface name=\"%s\">\n",
  210. interface->name);
  211. l_queue_foreach(interface->methods,
  212. (l_queue_foreach_func_t) _dbus_method_introspection, buf);
  213. l_queue_foreach(interface->signals,
  214. (l_queue_foreach_func_t) _dbus_signal_introspection, buf);
  215. l_queue_foreach(interface->properties,
  216. (l_queue_foreach_func_t) _dbus_property_introspection, buf);
  217. l_string_append(buf, "\t</interface>\n");
  218. }
  219. #define COPY_PARAMS(dest, signature, args) \
  220. do { \
  221. const char *pname; \
  222. const char *sig; \
  223. dest = stpcpy(dest, signature) + 1; \
  224. for (sig = signature; *sig; sig++) { \
  225. sig = _dbus_signature_end(sig); \
  226. pname = va_arg(args, const char *); \
  227. dest = stpcpy(dest, pname) + 1; \
  228. } \
  229. } while(0)
  230. #define SIZE_PARAMS(signature, args) \
  231. ({ \
  232. unsigned int len = strlen(signature) + 1; \
  233. const char *pname; \
  234. const char *sig; \
  235. for (sig = signature; *sig; sig++) { \
  236. sig = _dbus_signature_end(sig); \
  237. if (!sig) { \
  238. len = 0; \
  239. break; \
  240. } \
  241. pname = va_arg(args, const char *); \
  242. len += strlen(pname) + 1; \
  243. } \
  244. len; \
  245. })
  246. LIB_EXPORT bool l_dbus_interface_method(struct l_dbus_interface *interface,
  247. const char *name, uint32_t flags,
  248. l_dbus_interface_method_cb_t cb,
  249. const char *return_sig,
  250. const char *param_sig, ...)
  251. {
  252. va_list args;
  253. unsigned int return_info_len;
  254. unsigned int param_info_len;
  255. struct _dbus_method *info;
  256. char *p;
  257. if (!_dbus_valid_method(name))
  258. return false;
  259. if (unlikely(!return_sig || !param_sig))
  260. return false;
  261. if (return_sig[0] && !_dbus_valid_signature(return_sig))
  262. return false;
  263. if (param_sig[0] && !_dbus_valid_signature(param_sig))
  264. return false;
  265. /* Pre-calculate the needed meta-info length */
  266. va_start(args, param_sig);
  267. return_info_len = SIZE_PARAMS(return_sig, args);
  268. param_info_len = SIZE_PARAMS(param_sig, args);
  269. va_end(args);
  270. if (!return_info_len || !param_info_len)
  271. return false;
  272. info = l_malloc(sizeof(*info) + return_info_len +
  273. param_info_len + strlen(name) + 1);
  274. info->cb = cb;
  275. info->flags = flags;
  276. info->name_len = strlen(name);
  277. strcpy(info->metainfo, name);
  278. va_start(args, param_sig);
  279. /*
  280. * We store param signature + parameter names first, to speed up
  281. * lookups during the message dispatch procedures.
  282. */
  283. p = info->metainfo + info->name_len + param_info_len + 1;
  284. COPY_PARAMS(p, return_sig, args);
  285. p = info->metainfo + info->name_len + 1;
  286. COPY_PARAMS(p, param_sig, args);
  287. va_end(args);
  288. l_queue_push_tail(interface->methods, info);
  289. return true;
  290. }
  291. LIB_EXPORT bool l_dbus_interface_signal(struct l_dbus_interface *interface,
  292. const char *name, uint32_t flags,
  293. const char *signature, ...)
  294. {
  295. va_list args;
  296. unsigned int metainfo_len;
  297. struct _dbus_signal *info;
  298. char *p;
  299. if (!_dbus_valid_method(name))
  300. return false;
  301. if (unlikely(!signature))
  302. return false;
  303. if (signature[0] && !_dbus_valid_signature(signature))
  304. return false;
  305. /* Pre-calculate the needed meta-info length */
  306. va_start(args, signature);
  307. metainfo_len = SIZE_PARAMS(signature, args);
  308. va_end(args);
  309. if (!metainfo_len)
  310. return false;
  311. metainfo_len += strlen(name) + 1;
  312. info = l_malloc(sizeof(*info) + metainfo_len);
  313. info->flags = flags;
  314. info->name_len = strlen(name);
  315. p = stpcpy(info->metainfo, name) + 1;
  316. va_start(args, signature);
  317. COPY_PARAMS(p, signature, args);
  318. va_end(args);
  319. l_queue_push_tail(interface->signals, info);
  320. return true;
  321. }
  322. LIB_EXPORT bool l_dbus_interface_property(struct l_dbus_interface *interface,
  323. const char *name, uint32_t flags,
  324. const char *signature,
  325. l_dbus_property_get_cb_t getter,
  326. l_dbus_property_set_cb_t setter)
  327. {
  328. unsigned int metainfo_len;
  329. struct _dbus_property *info;
  330. char *p;
  331. if (!_dbus_valid_method(name))
  332. return false;
  333. if (unlikely(!signature || !getter))
  334. return false;
  335. if (_dbus_num_children(signature) != 1)
  336. return false;
  337. /* Pre-calculate the needed meta-info length */
  338. metainfo_len = strlen(name) + 1;
  339. metainfo_len += strlen(signature) + 1;
  340. info = l_malloc(sizeof(*info) + metainfo_len);
  341. info->flags = flags;
  342. info->name_len = strlen(name);
  343. info->getter = getter;
  344. info->setter = setter;
  345. p = stpcpy(info->metainfo, name) + 1;
  346. strcpy(p, signature);
  347. l_queue_push_tail(interface->properties, info);
  348. return true;
  349. }
  350. struct l_dbus_interface *_dbus_interface_new(const char *name)
  351. {
  352. struct l_dbus_interface *interface;
  353. interface = l_malloc(sizeof(*interface) + strlen(name) + 1);
  354. interface->methods = l_queue_new();
  355. interface->signals = l_queue_new();
  356. interface->properties = l_queue_new();
  357. strcpy(interface->name, name);
  358. return interface;
  359. }
  360. void _dbus_interface_free(struct l_dbus_interface *interface)
  361. {
  362. l_queue_destroy(interface->methods, l_free);
  363. l_queue_destroy(interface->signals, l_free);
  364. l_queue_destroy(interface->properties, l_free);
  365. l_free(interface);
  366. }
  367. static bool match_method(const void *a, const void *b)
  368. {
  369. const struct _dbus_method *method = a;
  370. const char *name = b;
  371. if (!strcmp(method->metainfo, name))
  372. return true;
  373. return false;
  374. }
  375. struct _dbus_method *_dbus_interface_find_method(struct l_dbus_interface *i,
  376. const char *method)
  377. {
  378. return l_queue_find(i->methods, match_method, (char *) method);
  379. }
  380. static bool match_signal(const void *a, const void *b)
  381. {
  382. const struct _dbus_signal *signal = a;
  383. const char *name = b;
  384. if (!strcmp(signal->metainfo, name))
  385. return true;
  386. return false;
  387. }
  388. struct _dbus_signal *_dbus_interface_find_signal(struct l_dbus_interface *i,
  389. const char *signal)
  390. {
  391. return l_queue_find(i->signals, match_signal, (char *) signal);
  392. }
  393. static bool match_property(const void *a, const void *b)
  394. {
  395. const struct _dbus_property *property = a;
  396. const char *name = b;
  397. if (!strcmp(property->metainfo, name))
  398. return true;
  399. return false;
  400. }
  401. struct _dbus_property *_dbus_interface_find_property(struct l_dbus_interface *i,
  402. const char *property)
  403. {
  404. return l_queue_find(i->properties, match_property, (char *) property);
  405. }
  406. static void interface_instance_free(struct interface_instance *instance)
  407. {
  408. if (instance->interface->instance_destroy)
  409. instance->interface->instance_destroy(instance->user_data);
  410. l_free(instance);
  411. }
  412. static bool match_interface_instance(const void *a, const void *b)
  413. {
  414. const struct interface_instance *instance = a;
  415. const char *name = b;
  416. if (!strcmp(instance->interface->name, name))
  417. return true;
  418. return false;
  419. }
  420. static bool match_interface_instance_ptr(const void *a, const void *b)
  421. {
  422. const struct interface_instance *instance = a;
  423. return instance->interface == b;
  424. }
  425. static void interface_add_record_free(void *data)
  426. {
  427. struct interface_add_record *rec = data;
  428. l_free(rec->path);
  429. l_queue_destroy(rec->instances, NULL);
  430. l_free(rec);
  431. }
  432. static void interface_removed_record_free(void *data)
  433. {
  434. struct interface_remove_record *rec = data;
  435. l_free(rec->path);
  436. l_queue_destroy(rec->interface_names, l_free);
  437. l_free(rec);
  438. }
  439. static void property_change_record_free(void *data)
  440. {
  441. struct property_change_record *rec = data;
  442. l_free(rec->path);
  443. l_queue_destroy(rec->properties, NULL);
  444. l_free(rec);
  445. }
  446. static void properties_setup_func(struct l_dbus_interface *);
  447. static void object_manager_setup_func(struct l_dbus_interface *);
  448. struct _dbus_object_tree *_dbus_object_tree_new()
  449. {
  450. struct _dbus_object_tree *tree;
  451. tree = l_new(struct _dbus_object_tree, 1);
  452. tree->interfaces = l_hashmap_new();
  453. l_hashmap_set_hash_function(tree->interfaces, l_str_hash);
  454. l_hashmap_set_compare_function(tree->interfaces,
  455. (l_hashmap_compare_func_t)strcmp);
  456. tree->objects = l_hashmap_string_new();
  457. tree->root = l_new(struct object_node, 1);
  458. tree->property_changes = l_queue_new();
  459. _dbus_object_tree_register_interface(tree, L_DBUS_INTERFACE_PROPERTIES,
  460. properties_setup_func, NULL,
  461. false);
  462. tree->object_managers = l_queue_new();
  463. _dbus_object_tree_register_interface(tree,
  464. L_DBUS_INTERFACE_OBJECT_MANAGER,
  465. object_manager_setup_func, NULL,
  466. false);
  467. return tree;
  468. }
  469. static void subtree_free(struct object_node *node)
  470. {
  471. struct child_node *child;
  472. while (node->children) {
  473. child = node->children;
  474. node->children = child->next;
  475. subtree_free(child->node);
  476. l_free(child);
  477. }
  478. l_queue_destroy(node->instances,
  479. (l_queue_destroy_func_t) interface_instance_free);
  480. if (node->destroy)
  481. node->destroy(node->user_data);
  482. l_free(node);
  483. }
  484. static void object_manager_free(void *data)
  485. {
  486. struct object_manager *manager = data;
  487. l_free(manager->path);
  488. l_queue_destroy(manager->announce_added, interface_add_record_free);
  489. l_queue_destroy(manager->announce_removed,
  490. interface_removed_record_free);
  491. l_free(manager);
  492. }
  493. void _dbus_object_tree_free(struct _dbus_object_tree *tree)
  494. {
  495. subtree_free(tree->root);
  496. l_hashmap_destroy(tree->interfaces,
  497. (l_hashmap_destroy_func_t) _dbus_interface_free);
  498. l_hashmap_destroy(tree->objects, NULL);
  499. l_queue_destroy(tree->object_managers, object_manager_free);
  500. l_queue_destroy(tree->property_changes, property_change_record_free);
  501. if (tree->emit_signals_work)
  502. l_idle_remove(tree->emit_signals_work);
  503. l_free(tree);
  504. }
  505. static struct object_node *makepath_recurse(struct object_node *node,
  506. const char *path)
  507. {
  508. const char *end;
  509. struct child_node *child;
  510. if (*path == '\0')
  511. return node;
  512. path += 1;
  513. end = strchrnul(path, '/');
  514. child = node->children;
  515. while (child) {
  516. if (!strncmp(child->subpath, path, end - path) &&
  517. child->subpath[end - path] == '\0')
  518. goto done;
  519. child = child->next;
  520. }
  521. child = l_malloc(sizeof(*child) + end - path + 1);
  522. child->node = l_new(struct object_node, 1);
  523. child->node->parent = node;
  524. memcpy(child->subpath, path, end - path);
  525. child->subpath[end-path] = '\0';
  526. child->next = node->children;
  527. node->children = child;
  528. done:
  529. return makepath_recurse(child->node, end);
  530. }
  531. struct object_node *_dbus_object_tree_makepath(struct _dbus_object_tree *tree,
  532. const char *path)
  533. {
  534. if (path[0] == '/' && path[1] == '\0')
  535. return tree->root;
  536. return makepath_recurse(tree->root, path);
  537. }
  538. static struct object_node *lookup_recurse(struct object_node *node,
  539. const char *path)
  540. {
  541. const char *end;
  542. struct child_node *child;
  543. if (*path == '\0')
  544. return node;
  545. path += 1;
  546. end = strchrnul(path, '/');
  547. child = node->children;
  548. while (child) {
  549. if (!strncmp(child->subpath, path, end - path) &&
  550. child->subpath[end - path] == '\0')
  551. return lookup_recurse(child->node, end);
  552. child = child->next;
  553. }
  554. return NULL;
  555. }
  556. struct object_node *_dbus_object_tree_lookup(struct _dbus_object_tree *tree,
  557. const char *path)
  558. {
  559. if (path[0] == '/' && path[1] == '\0')
  560. return tree->root;
  561. return lookup_recurse(tree->root, path);
  562. }
  563. void _dbus_object_tree_prune_node(struct object_node *node)
  564. {
  565. struct object_node *parent = node->parent;
  566. struct child_node *p = NULL, *c;
  567. while (parent) {
  568. for (c = parent->children, p = NULL; c; p = c, c = c->next) {
  569. if (c->node != node)
  570. continue;
  571. if (p)
  572. p->next = c->next;
  573. else
  574. parent->children = c->next;
  575. subtree_free(c->node);
  576. l_free(c);
  577. break;
  578. }
  579. if (parent->children != NULL)
  580. return;
  581. if (parent->instances)
  582. return;
  583. node = parent;
  584. parent = node->parent;
  585. }
  586. }
  587. struct object_node *_dbus_object_tree_new_object(struct _dbus_object_tree *tree,
  588. const char *path,
  589. void *user_data,
  590. void (*destroy) (void *))
  591. {
  592. struct object_node *node;
  593. if (!_dbus_valid_object_path(path))
  594. return NULL;
  595. if (l_hashmap_lookup(tree->objects, path))
  596. return NULL;
  597. node = _dbus_object_tree_makepath(tree, path);
  598. node->user_data = user_data;
  599. node->destroy = destroy;
  600. /*
  601. * Registered objects in the tree are marked by being present in the
  602. * tree->objects hash and having non-null node->instances. Remaining
  603. * nodes are intermediate path elements added and removed
  604. * automatically.
  605. */
  606. node->instances = l_queue_new();
  607. l_hashmap_insert(tree->objects, path, node);
  608. return node;
  609. }
  610. bool _dbus_object_tree_object_destroy(struct _dbus_object_tree *tree,
  611. const char *path)
  612. {
  613. struct object_node *node;
  614. const struct l_queue_entry *entry;
  615. const struct interface_instance *instance;
  616. node = l_hashmap_lookup(tree->objects, path);
  617. if (!node)
  618. return false;
  619. while ((entry = l_queue_get_entries(node->instances))) {
  620. instance = entry->data;
  621. if (!_dbus_object_tree_remove_interface(tree, path,
  622. instance->interface->name))
  623. return false;
  624. }
  625. l_hashmap_remove(tree->objects, path);
  626. l_queue_destroy(node->instances, NULL);
  627. node->instances = NULL;
  628. if (node->destroy) {
  629. node->destroy(node->user_data);
  630. node->destroy = NULL;
  631. }
  632. if (!node->children)
  633. _dbus_object_tree_prune_node(node);
  634. return true;
  635. }
  636. static bool get_properties_dict(struct l_dbus *dbus,
  637. struct l_dbus_message *message,
  638. struct l_dbus_message_builder *builder,
  639. const struct l_dbus_interface *interface,
  640. void *user_data)
  641. {
  642. const struct l_queue_entry *entry;
  643. const struct _dbus_property *property;
  644. const char *signature;
  645. l_dbus_message_builder_enter_array(builder, "{sv}");
  646. _dbus_message_builder_mark(builder);
  647. for (entry = l_queue_get_entries(interface->properties); entry;
  648. entry = entry->next) {
  649. property = entry->data;
  650. signature = property->metainfo + strlen(property->metainfo) + 1;
  651. l_dbus_message_builder_enter_dict(builder, "sv");
  652. l_dbus_message_builder_append_basic(builder, 's',
  653. property->metainfo);
  654. l_dbus_message_builder_enter_variant(builder, signature);
  655. if (!property->getter(dbus, message, builder, user_data)) {
  656. if (!_dbus_message_builder_rewind(builder))
  657. return false;
  658. continue;
  659. }
  660. l_dbus_message_builder_leave_variant(builder);
  661. l_dbus_message_builder_leave_dict(builder);
  662. _dbus_message_builder_mark(builder);
  663. }
  664. l_dbus_message_builder_leave_array(builder);
  665. return true;
  666. }
  667. static struct l_dbus_message *build_interfaces_removed_signal(
  668. const struct object_manager *manager,
  669. const struct interface_remove_record *rec)
  670. {
  671. struct l_dbus_message *signal;
  672. struct l_dbus_message_builder *builder;
  673. const struct l_queue_entry *entry;
  674. signal = l_dbus_message_new_signal(manager->dbus, manager->path,
  675. L_DBUS_INTERFACE_OBJECT_MANAGER,
  676. "InterfacesRemoved");
  677. builder = l_dbus_message_builder_new(signal);
  678. l_dbus_message_builder_append_basic(builder, 'o', rec->path);
  679. l_dbus_message_builder_enter_array(builder, "s");
  680. for (entry = l_queue_get_entries(rec->interface_names); entry;
  681. entry = entry->next)
  682. l_dbus_message_builder_append_basic(builder, 's', entry->data);
  683. l_dbus_message_builder_leave_array(builder);
  684. l_dbus_message_builder_finalize(builder);
  685. l_dbus_message_builder_destroy(builder);
  686. return signal;
  687. }
  688. static struct l_dbus_message *build_interfaces_added_signal(
  689. const struct object_manager *manager,
  690. const struct interface_add_record *rec)
  691. {
  692. struct l_dbus_message *signal;
  693. struct l_dbus_message_builder *builder;
  694. const struct l_queue_entry *entry;
  695. const struct interface_instance *instance;
  696. signal = l_dbus_message_new_signal(manager->dbus, manager->path,
  697. L_DBUS_INTERFACE_OBJECT_MANAGER,
  698. "InterfacesAdded");
  699. builder = l_dbus_message_builder_new(signal);
  700. l_dbus_message_builder_append_basic(builder, 'o', rec->path);
  701. l_dbus_message_builder_enter_array(builder, "{sa{sv}}");
  702. for (entry = l_queue_get_entries(rec->instances); entry;
  703. entry = entry->next) {
  704. instance = entry->data;
  705. l_dbus_message_builder_enter_dict(builder, "sa{sv}");
  706. l_dbus_message_builder_append_basic(builder, 's',
  707. instance->interface->name);
  708. if (!get_properties_dict(manager->dbus, signal, builder,
  709. instance->interface,
  710. instance->user_data)) {
  711. l_dbus_message_builder_destroy(builder);
  712. l_dbus_message_unref(signal);
  713. return NULL;
  714. }
  715. l_dbus_message_builder_leave_dict(builder);
  716. }
  717. l_dbus_message_builder_leave_array(builder);
  718. l_dbus_message_builder_finalize(builder);
  719. l_dbus_message_builder_destroy(builder);
  720. return signal;
  721. }
  722. static struct l_dbus_message *build_old_property_changed_signal(
  723. struct l_dbus *dbus,
  724. const struct property_change_record *rec,
  725. const struct _dbus_property *property)
  726. {
  727. struct l_dbus_message *signal;
  728. struct l_dbus_message_builder *builder;
  729. const char *signature;
  730. signature = property->metainfo + strlen(property->metainfo) + 1;
  731. signal = l_dbus_message_new_signal(dbus, rec->path,
  732. rec->instance->interface->name,
  733. "PropertyChanged");
  734. builder = l_dbus_message_builder_new(signal);
  735. l_dbus_message_builder_append_basic(builder, 's', property->metainfo);
  736. l_dbus_message_builder_enter_variant(builder, signature);
  737. if (!property->getter(dbus, signal, builder,
  738. rec->instance->user_data)) {
  739. l_dbus_message_builder_destroy(builder);
  740. l_dbus_message_unref(signal);
  741. return NULL;
  742. }
  743. l_dbus_message_builder_leave_variant(builder);
  744. l_dbus_message_builder_finalize(builder);
  745. l_dbus_message_builder_destroy(builder);
  746. return signal;
  747. }
  748. static struct l_dbus_message *build_properties_changed_signal(
  749. struct l_dbus *dbus,
  750. const struct property_change_record *rec)
  751. {
  752. struct l_dbus_message *signal;
  753. struct l_dbus_message_builder *builder;
  754. const struct l_queue_entry *entry;
  755. const struct _dbus_property *property;
  756. const char *signature;
  757. struct l_queue *invalidated;
  758. signal = l_dbus_message_new_signal(dbus, rec->path,
  759. L_DBUS_INTERFACE_PROPERTIES,
  760. "PropertiesChanged");
  761. builder = l_dbus_message_builder_new(signal);
  762. invalidated = l_queue_new();
  763. l_dbus_message_builder_append_basic(builder, 's',
  764. rec->instance->interface->name);
  765. l_dbus_message_builder_enter_array(builder, "{sv}");
  766. for (entry = l_queue_get_entries(rec->properties); entry;
  767. entry = entry->next) {
  768. property = entry->data;
  769. signature = property->metainfo + strlen(property->metainfo) + 1;
  770. _dbus_message_builder_mark(builder);
  771. l_dbus_message_builder_enter_dict(builder, "sv");
  772. l_dbus_message_builder_append_basic(builder, 's',
  773. property->metainfo);
  774. l_dbus_message_builder_enter_variant(builder, signature);
  775. if (!property->getter(dbus, signal, builder,
  776. rec->instance->user_data)) {
  777. if (!_dbus_message_builder_rewind(builder)) {
  778. l_dbus_message_unref(signal);
  779. signal = NULL;
  780. goto done;
  781. }
  782. l_queue_push_tail(invalidated, (void *) property);
  783. continue;
  784. }
  785. l_dbus_message_builder_leave_variant(builder);
  786. l_dbus_message_builder_leave_dict(builder);
  787. }
  788. l_dbus_message_builder_leave_array(builder);
  789. l_dbus_message_builder_enter_array(builder, "s");
  790. while ((property = l_queue_pop_head(invalidated)))
  791. l_dbus_message_builder_append_basic(builder, 's',
  792. property->metainfo);
  793. l_dbus_message_builder_leave_array(builder);
  794. l_dbus_message_builder_finalize(builder);
  795. done:
  796. l_dbus_message_builder_destroy(builder);
  797. l_queue_destroy(invalidated, NULL);
  798. return signal;
  799. }
  800. struct emit_signals_data {
  801. struct l_dbus *dbus;
  802. struct object_manager *manager;
  803. struct object_node *node;
  804. };
  805. static bool emit_interfaces_removed(void *data, void *user_data)
  806. {
  807. struct interface_remove_record *rec = data;
  808. struct emit_signals_data *es = user_data;
  809. struct l_dbus_message *signal;
  810. if (es->node && rec->object != es->node)
  811. return false;
  812. signal = build_interfaces_removed_signal(es->manager, rec);
  813. interface_removed_record_free(rec);
  814. if (signal)
  815. l_dbus_send(es->manager->dbus, signal);
  816. return true;
  817. }
  818. static bool emit_interfaces_added(void *data, void *user_data)
  819. {
  820. struct interface_add_record *rec = data;
  821. struct emit_signals_data *es = user_data;
  822. struct l_dbus_message *signal;
  823. if (es->node && rec->object != es->node)
  824. return false;
  825. signal = build_interfaces_added_signal(es->manager, rec);
  826. interface_add_record_free(rec);
  827. if (signal)
  828. l_dbus_send(es->manager->dbus, signal);
  829. return true;
  830. }
  831. static bool emit_properties_changed(void *data, void *user_data)
  832. {
  833. struct property_change_record *rec = data;
  834. struct emit_signals_data *es = user_data;
  835. struct l_dbus_message *signal;
  836. const struct l_queue_entry *entry;
  837. if (es->node && rec->object != es->node)
  838. return false;
  839. if (rec->instance->interface->handle_old_style_properties)
  840. for (entry = l_queue_get_entries(rec->properties);
  841. entry; entry = entry->next) {
  842. signal = build_old_property_changed_signal(es->dbus,
  843. rec, entry->data);
  844. if (signal)
  845. l_dbus_send(es->dbus, signal);
  846. }
  847. if (l_queue_find(rec->object->instances, match_interface_instance,
  848. L_DBUS_INTERFACE_PROPERTIES)) {
  849. signal = build_properties_changed_signal(es->dbus, rec);
  850. if (signal)
  851. l_dbus_send(es->dbus, signal);
  852. }
  853. property_change_record_free(rec);
  854. return true;
  855. }
  856. void _dbus_object_tree_signals_flush(struct l_dbus *dbus, const char *path)
  857. {
  858. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  859. const struct l_queue_entry *entry;
  860. struct emit_signals_data data;
  861. bool all_done = true;
  862. if (!tree->emit_signals_work || tree->flushing)
  863. return;
  864. tree->flushing = true;
  865. data.dbus = dbus;
  866. data.node = path ? _dbus_object_tree_lookup(tree, path) : NULL;
  867. for (entry = l_queue_get_entries(tree->object_managers); entry;
  868. entry = entry->next) {
  869. data.manager = entry->data;
  870. l_queue_foreach_remove(data.manager->announce_removed,
  871. emit_interfaces_removed, &data);
  872. if (!l_queue_isempty(data.manager->announce_removed))
  873. all_done = false;
  874. l_queue_foreach_remove(data.manager->announce_added,
  875. emit_interfaces_added, &data);
  876. if (!l_queue_isempty(data.manager->announce_added))
  877. all_done = false;
  878. }
  879. l_queue_foreach_remove(tree->property_changes,
  880. emit_properties_changed, &data);
  881. if (!l_queue_isempty(tree->property_changes))
  882. all_done = false;
  883. if (all_done) {
  884. l_idle_remove(tree->emit_signals_work);
  885. tree->emit_signals_work = NULL;
  886. }
  887. tree->flushing = false;
  888. }
  889. static void emit_signals(struct l_idle *idle, void *user_data)
  890. {
  891. struct l_dbus *dbus = user_data;
  892. _dbus_object_tree_signals_flush(dbus, NULL);
  893. }
  894. static void schedule_emit_signals(struct l_dbus *dbus)
  895. {
  896. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  897. if (tree->emit_signals_work)
  898. return;
  899. tree->emit_signals_work = l_idle_create(emit_signals, dbus, NULL);
  900. }
  901. static bool match_property_changes_instance(const void *a, const void *b)
  902. {
  903. const struct property_change_record *rec = a;
  904. return rec->instance == b;
  905. }
  906. static bool match_pointer(const void *a, const void *b)
  907. {
  908. return a == b;
  909. }
  910. bool _dbus_object_tree_property_changed(struct l_dbus *dbus,
  911. const char *path,
  912. const char *interface_name,
  913. const char *property_name)
  914. {
  915. struct property_change_record *rec;
  916. struct object_node *object;
  917. struct interface_instance *instance;
  918. struct _dbus_property *property;
  919. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  920. object = l_hashmap_lookup(tree->objects, path);
  921. if (!object)
  922. return false;
  923. instance = l_queue_find(object->instances, match_interface_instance,
  924. interface_name);
  925. if (!instance)
  926. return false;
  927. property = _dbus_interface_find_property(instance->interface,
  928. property_name);
  929. if (!property)
  930. return false;
  931. rec = l_queue_find(tree->property_changes,
  932. match_property_changes_instance, instance);
  933. if (rec) {
  934. if (l_queue_find(rec->properties, match_pointer, property))
  935. return true;
  936. } else {
  937. rec = l_new(struct property_change_record, 1);
  938. rec->path = l_strdup(path);
  939. rec->object = object;
  940. rec->instance = instance;
  941. rec->properties = l_queue_new();
  942. l_queue_push_tail(tree->property_changes, rec);
  943. }
  944. l_queue_push_tail(rec->properties, property);
  945. schedule_emit_signals(dbus);
  946. return true;
  947. }
  948. static void pending_property_set_done_common(struct l_dbus *dbus,
  949. struct l_dbus_message *message,
  950. struct l_dbus_message *reply,
  951. bool auto_emit)
  952. {
  953. const char *member;
  954. const char *interface_name;
  955. const char *property_name;
  956. struct l_dbus_message_iter variant;
  957. if (!reply) {
  958. reply = l_dbus_message_new_method_return(message);
  959. l_dbus_message_set_arguments(reply, "");
  960. }
  961. l_dbus_send(dbus, l_dbus_message_ref(reply));
  962. member = l_dbus_message_get_member(message);
  963. if (!strcmp(member, "SetProperty")) {
  964. if (!l_dbus_message_get_arguments(message, "sv",
  965. &property_name, &variant))
  966. goto done;
  967. interface_name = l_dbus_message_get_interface(message);
  968. } else if (strcmp(member, "Set") ||
  969. !l_dbus_message_get_arguments(message, "ssv",
  970. &interface_name,
  971. &property_name,
  972. &variant))
  973. goto done;
  974. if (auto_emit)
  975. _dbus_object_tree_property_changed(dbus,
  976. l_dbus_message_get_path(message),
  977. interface_name, property_name);
  978. done:
  979. l_dbus_message_unref(message);
  980. l_dbus_message_unref(reply);
  981. }
  982. static void pending_property_set_done_emit(struct l_dbus *dbus,
  983. struct l_dbus_message *message,
  984. struct l_dbus_message *reply)
  985. {
  986. pending_property_set_done_common(dbus, message, reply, true);
  987. }
  988. static void pending_property_set_done(struct l_dbus *dbus,
  989. struct l_dbus_message *message,
  990. struct l_dbus_message *reply)
  991. {
  992. pending_property_set_done_common(dbus, message, reply, false);
  993. }
  994. static struct l_dbus_message *old_set_property(struct l_dbus *dbus,
  995. struct l_dbus_message *message,
  996. void *user_data)
  997. {
  998. struct l_dbus_interface *interface;
  999. const char *property_name;
  1000. const struct _dbus_property *property;
  1001. struct l_dbus_message_iter variant;
  1002. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  1003. struct l_dbus_message *reply;
  1004. l_dbus_property_complete_cb_t complete_cb;
  1005. interface = l_hashmap_lookup(tree->interfaces,
  1006. l_dbus_message_get_interface(message));
  1007. /* If we got here the interface must exist */
  1008. if (!l_dbus_message_get_arguments(message, "sv", &property_name,
  1009. &variant))
  1010. return l_dbus_message_new_error(message,
  1011. "org.freedesktop.DBus.Error."
  1012. "InvalidArgs",
  1013. "Invalid arguments");
  1014. property = _dbus_interface_find_property(interface, property_name);
  1015. if (!property)
  1016. return l_dbus_message_new_error(message,
  1017. "org.freedesktop.DBus.Error."
  1018. "InvalidArgs",
  1019. "Unknown Property %s",
  1020. property_name);
  1021. if (!property->setter)
  1022. return l_dbus_message_new_error(message,
  1023. "org.freedesktop.DBus.Error."
  1024. "InvalidArgs",
  1025. "Property %s is read-only",
  1026. property_name);
  1027. if (property->flags & L_DBUS_PROPERTY_FLAG_AUTO_EMIT)
  1028. complete_cb = pending_property_set_done_emit;
  1029. else
  1030. complete_cb = pending_property_set_done;
  1031. reply = property->setter(dbus, l_dbus_message_ref(message), &variant,
  1032. complete_cb, user_data);
  1033. if (reply)
  1034. complete_cb(dbus, message, reply);
  1035. return NULL;
  1036. }
  1037. static struct l_dbus_message *old_get_properties(struct l_dbus *dbus,
  1038. struct l_dbus_message *message,
  1039. void *user_data)
  1040. {
  1041. const struct l_dbus_interface *interface;
  1042. struct l_dbus_message *reply;
  1043. struct l_dbus_message_builder *builder;
  1044. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  1045. interface = l_hashmap_lookup(tree->interfaces,
  1046. l_dbus_message_get_interface(message));
  1047. /* If we got here the interface must exist */
  1048. reply = l_dbus_message_new_method_return(message);
  1049. builder = l_dbus_message_builder_new(reply);
  1050. if (!get_properties_dict(dbus, message, builder, interface,
  1051. user_data)) {
  1052. l_dbus_message_unref(reply);
  1053. reply = l_dbus_message_new_error(message,
  1054. "org.freedesktop.DBus.Error."
  1055. "Failed",
  1056. "Getting properties failed");
  1057. } else
  1058. l_dbus_message_builder_finalize(builder);
  1059. l_dbus_message_builder_destroy(builder);
  1060. return reply;
  1061. }
  1062. bool _dbus_object_tree_register_interface(struct _dbus_object_tree *tree,
  1063. const char *interface,
  1064. void (*setup_func)(struct l_dbus_interface *),
  1065. void (*destroy) (void *),
  1066. bool old_style_properties)
  1067. {
  1068. struct l_dbus_interface *dbi;
  1069. if (!_dbus_valid_interface(interface))
  1070. return false;
  1071. /*
  1072. * Check to make sure we do not have this interface already
  1073. * registered
  1074. */
  1075. dbi = l_hashmap_lookup(tree->interfaces, interface);
  1076. if (dbi)
  1077. return false;
  1078. dbi = _dbus_interface_new(interface);
  1079. dbi->instance_destroy = destroy;
  1080. dbi->handle_old_style_properties = old_style_properties;
  1081. /* Add our methods first so we don't have to check for conflicts. */
  1082. if (old_style_properties) {
  1083. l_dbus_interface_method(dbi, "SetProperty", 0,
  1084. old_set_property, "", "sv",
  1085. "name", "value");
  1086. l_dbus_interface_method(dbi, "GetProperties", 0,
  1087. old_get_properties, "a{sv}", "",
  1088. "properties");
  1089. l_dbus_interface_signal(dbi, "PropertyChanged", 0, "sv",
  1090. "name", "value");
  1091. }
  1092. setup_func(dbi);
  1093. l_hashmap_insert(tree->interfaces, dbi->name, dbi);
  1094. return true;
  1095. }
  1096. struct interface_check {
  1097. struct _dbus_object_tree *tree;
  1098. const char *interface;
  1099. };
  1100. static void check_interface_used(const void *key, void *value, void *user_data)
  1101. {
  1102. const char *path = key;
  1103. struct object_node *node = value;
  1104. struct interface_check *state = user_data;
  1105. if (!l_queue_find(node->instances, match_interface_instance,
  1106. (char *) state->interface))
  1107. return;
  1108. _dbus_object_tree_remove_interface(state->tree, path, state->interface);
  1109. }
  1110. bool _dbus_object_tree_unregister_interface(struct _dbus_object_tree *tree,
  1111. const char *interface_name)
  1112. {
  1113. struct l_dbus_interface *interface;
  1114. struct interface_check state = { tree, interface_name };
  1115. interface = l_hashmap_lookup(tree->interfaces, interface_name);
  1116. if (!interface)
  1117. return false;
  1118. /* Check that the interface is not in use */
  1119. l_hashmap_foreach(tree->objects, check_interface_used, &state);
  1120. l_hashmap_remove(tree->interfaces, interface_name);
  1121. _dbus_interface_free(interface);
  1122. return true;
  1123. }
  1124. static void collect_instances(struct object_node *node,
  1125. const char *path,
  1126. struct l_queue *announce)
  1127. {
  1128. const struct l_queue_entry *entry;
  1129. struct interface_add_record *change_rec;
  1130. const struct child_node *child;
  1131. if (!node->instances)
  1132. goto recurse;
  1133. change_rec = l_new(struct interface_add_record, 1);
  1134. change_rec->path = l_strdup(path);
  1135. change_rec->object = node;
  1136. change_rec->instances = l_queue_new();
  1137. for (entry = l_queue_get_entries(node->instances); entry;
  1138. entry = entry->next)
  1139. l_queue_push_tail(change_rec->instances, entry->data);
  1140. l_queue_push_tail(announce, change_rec);
  1141. recurse:
  1142. if (!strcmp(path, "/"))
  1143. path = "";
  1144. for (child = node->children; child; child = child->next) {
  1145. char *child_path;
  1146. child_path = l_strdup_printf("%s/%s", path, child->subpath);
  1147. collect_instances(child->node, child_path, announce);
  1148. l_free(child_path);
  1149. }
  1150. }
  1151. static bool match_interfaces_added_object(const void *a, const void *b)
  1152. {
  1153. const struct interface_add_record *rec = a;
  1154. return rec->object == b;
  1155. }
  1156. static bool match_interfaces_removed_object(const void *a, const void *b)
  1157. {
  1158. const struct interface_remove_record *rec = a;
  1159. return rec->object == b;
  1160. }
  1161. bool _dbus_object_tree_add_interface(struct _dbus_object_tree *tree,
  1162. const char *path, const char *interface,
  1163. void *user_data)
  1164. {
  1165. struct object_node *object;
  1166. struct l_dbus_interface *dbi;
  1167. struct interface_instance *instance;
  1168. const struct l_queue_entry *entry;
  1169. struct object_manager *manager;
  1170. size_t path_len;
  1171. struct interface_add_record *change_rec;
  1172. dbi = l_hashmap_lookup(tree->interfaces, interface);
  1173. if (!dbi)
  1174. return false;
  1175. object = l_hashmap_lookup(tree->objects, path);
  1176. if (!object) {
  1177. object = _dbus_object_tree_new_object(tree, path, NULL, NULL);
  1178. if (!object)
  1179. return false;
  1180. }
  1181. /*
  1182. * Check to make sure we do not have this interface already
  1183. * registered for this object
  1184. */
  1185. if (l_queue_find(object->instances, match_interface_instance_ptr, dbi))
  1186. return false;
  1187. instance = l_new(struct interface_instance, 1);
  1188. instance->interface = dbi;
  1189. instance->user_data = user_data;
  1190. l_queue_push_tail(object->instances, instance);
  1191. for (entry = l_queue_get_entries(tree->object_managers); entry;
  1192. entry = entry->next) {
  1193. manager = entry->data;
  1194. path_len = strlen(manager->path);
  1195. if (strncmp(path, manager->path, path_len) ||
  1196. (path[path_len] != '\0' &&
  1197. path[path_len] != '/' && path_len > 1))
  1198. continue;
  1199. change_rec = l_queue_find(manager->announce_added,
  1200. match_interfaces_added_object,
  1201. object);
  1202. if (!change_rec) {
  1203. change_rec = l_new(struct interface_add_record, 1);
  1204. change_rec->path = l_strdup(path);
  1205. change_rec->object = object;
  1206. change_rec->instances = l_queue_new();
  1207. l_queue_push_tail(manager->announce_added, change_rec);
  1208. }
  1209. /* No need to check for duplicates here */
  1210. l_queue_push_tail(change_rec->instances, instance);
  1211. schedule_emit_signals(manager->dbus);
  1212. }
  1213. if (!strcmp(interface, L_DBUS_INTERFACE_OBJECT_MANAGER)) {
  1214. manager = l_new(struct object_manager, 1);
  1215. manager->path = l_strdup(path);
  1216. manager->dbus = instance->user_data;
  1217. manager->announce_added = l_queue_new();
  1218. manager->announce_removed = l_queue_new();
  1219. l_queue_push_tail(tree->object_managers, manager);
  1220. /* Emit InterfacesAdded for interfaces added before OM */
  1221. collect_instances(object, path, manager->announce_added);
  1222. if (manager->dbus && !l_queue_isempty(manager->announce_added))
  1223. schedule_emit_signals(manager->dbus);
  1224. }
  1225. return true;
  1226. }
  1227. void *_dbus_object_tree_get_interface_data(struct _dbus_object_tree *tree,
  1228. const char *path,
  1229. const char *interface)
  1230. {
  1231. struct object_node *object;
  1232. struct interface_instance *instance;
  1233. object = l_hashmap_lookup(tree->objects, path);
  1234. if (!object)
  1235. return NULL;
  1236. instance = l_queue_find(object->instances, match_interface_instance,
  1237. (char *) interface);
  1238. if (!instance)
  1239. return NULL;
  1240. return instance->user_data;
  1241. }
  1242. static bool match_object_manager_path(const void *a, const void *b)
  1243. {
  1244. const struct object_manager *manager = a;
  1245. return !strcmp(manager->path, b);
  1246. }
  1247. bool _dbus_object_tree_remove_interface(struct _dbus_object_tree *tree,
  1248. const char *path, const char *interface)
  1249. {
  1250. struct object_node *node;
  1251. struct interface_instance *instance;
  1252. const struct l_queue_entry *entry;
  1253. struct object_manager *manager;
  1254. size_t path_len;
  1255. struct interface_add_record *interfaces_added_rec;
  1256. struct interface_remove_record *interfaces_removed_rec;
  1257. struct property_change_record *property_change_rec;
  1258. node = l_hashmap_lookup(tree->objects, path);
  1259. if (!node)
  1260. return false;
  1261. instance = l_queue_remove_if(node->instances,
  1262. match_interface_instance, (char *) interface);
  1263. if (!instance)
  1264. return false;
  1265. if (!strcmp(interface, L_DBUS_INTERFACE_OBJECT_MANAGER)) {
  1266. manager = l_queue_remove_if(tree->object_managers,
  1267. match_object_manager_path,
  1268. (char *) path);
  1269. if (manager)
  1270. object_manager_free(manager);
  1271. }
  1272. for (entry = l_queue_get_entries(tree->object_managers); entry;
  1273. entry = entry->next) {
  1274. manager = entry->data;
  1275. path_len = strlen(manager->path);
  1276. if (strncmp(path, manager->path, path_len) ||
  1277. (path[path_len] != '\0' &&
  1278. path[path_len] != '/' && path_len > 1))
  1279. continue;
  1280. interfaces_added_rec = l_queue_find(manager->announce_added,
  1281. match_interfaces_added_object,
  1282. node);
  1283. if (interfaces_added_rec && l_queue_remove(
  1284. interfaces_added_rec->instances,
  1285. instance)) {
  1286. if (l_queue_isempty(interfaces_added_rec->instances))
  1287. l_queue_remove(manager->announce_added,
  1288. interfaces_added_rec);
  1289. interface_add_record_free(interfaces_added_rec);
  1290. continue;
  1291. }
  1292. interfaces_removed_rec = l_queue_find(manager->announce_removed,
  1293. match_interfaces_removed_object,
  1294. node);
  1295. if (!interfaces_removed_rec) {
  1296. interfaces_removed_rec =
  1297. l_new(struct interface_remove_record, 1);
  1298. interfaces_removed_rec->path = l_strdup(path);
  1299. interfaces_removed_rec->object = node;
  1300. interfaces_removed_rec->interface_names =
  1301. l_queue_new();
  1302. l_queue_push_tail(manager->announce_removed,
  1303. interfaces_removed_rec);
  1304. }
  1305. /* No need to check for duplicates here */
  1306. l_queue_push_tail(interfaces_removed_rec->interface_names,
  1307. l_strdup(interface));
  1308. schedule_emit_signals(manager->dbus);
  1309. }
  1310. property_change_rec = l_queue_remove_if(tree->property_changes,
  1311. match_property_changes_instance,
  1312. instance);
  1313. if (property_change_rec)
  1314. property_change_record_free(property_change_rec);
  1315. interface_instance_free(instance);
  1316. return true;
  1317. }
  1318. static void generate_interface_instance(void *data, void *user)
  1319. {
  1320. struct interface_instance *instance = data;
  1321. struct l_string *buf = user;
  1322. _dbus_interface_introspection(instance->interface, buf);
  1323. }
  1324. void _dbus_object_tree_introspect(struct _dbus_object_tree *tree,
  1325. const char *path, struct l_string *buf)
  1326. {
  1327. struct object_node *node;
  1328. struct child_node *child;
  1329. bool path_is_object = true;
  1330. node = l_hashmap_lookup(tree->objects, path);
  1331. if (!node) {
  1332. path_is_object = false;
  1333. node = _dbus_object_tree_lookup(tree, path);
  1334. }
  1335. l_string_append(buf, XML_HEAD);
  1336. l_string_append(buf, "<node>\n");
  1337. if (node) {
  1338. /*
  1339. * We emit org.freedesktop.DBus.Introspectable only in case the
  1340. * object node corresponds to a registered object, i.e.
  1341. * exposes anything other than:
  1342. * - org.freedesktop.DBus.Introspectable
  1343. * - org.freedesktop.DBus.Peer
  1344. * - org.freedesktop.DBus.Properties
  1345. */
  1346. if (path_is_object)
  1347. l_string_append(buf, static_introspectable);
  1348. l_queue_foreach(node->instances,
  1349. generate_interface_instance, buf);
  1350. for (child = node->children; child; child = child->next)
  1351. l_string_append_printf(buf, "\t<node name=\"%s\"/>\n",
  1352. child->subpath);
  1353. }
  1354. l_string_append(buf, "</node>\n");
  1355. }
  1356. bool _dbus_object_tree_dispatch(struct _dbus_object_tree *tree,
  1357. struct l_dbus *dbus,
  1358. struct l_dbus_message *message)
  1359. {
  1360. const char *path;
  1361. const char *interface;
  1362. const char *member;
  1363. const char *msg_sig;
  1364. const char *sig;
  1365. struct object_node *node;
  1366. struct interface_instance *instance;
  1367. struct _dbus_method *method;
  1368. struct l_dbus_message *reply;
  1369. path = l_dbus_message_get_path(message);
  1370. interface = l_dbus_message_get_interface(message);
  1371. member = l_dbus_message_get_member(message);
  1372. msg_sig = l_dbus_message_get_signature(message);
  1373. /*
  1374. * Nothing in the spec explicitly forbids this, but handling of such
  1375. * messages is left up to the implementation.
  1376. *
  1377. * TODO: Another route is to go looking for a matching method under this
  1378. * object and call it.
  1379. */
  1380. if (!interface)
  1381. return false;
  1382. if (!msg_sig)
  1383. msg_sig = "";
  1384. if (!strcmp(interface, "org.freedesktop.DBus.Introspectable") &&
  1385. !strcmp(member, "Introspect") &&
  1386. !strcmp(msg_sig, "")) {
  1387. struct l_string *buf;
  1388. char *xml;
  1389. buf = l_string_new(0);
  1390. _dbus_object_tree_introspect(tree, path, buf);
  1391. xml = l_string_unwrap(buf);
  1392. reply = l_dbus_message_new_method_return(message);
  1393. l_dbus_message_set_arguments(reply, "s", xml);
  1394. l_dbus_send(dbus, reply);
  1395. l_free(xml);
  1396. return true;
  1397. }
  1398. node = l_hashmap_lookup(tree->objects, path);
  1399. if (!node)
  1400. return false;
  1401. instance = l_queue_find(node->instances,
  1402. match_interface_instance, (char *) interface);
  1403. if (!instance)
  1404. return false;
  1405. method = _dbus_interface_find_method(instance->interface, member);
  1406. if (!method)
  1407. return false;
  1408. sig = method->metainfo + method->name_len + 1;
  1409. if (strcmp(msg_sig, sig))
  1410. return false;
  1411. reply = method->cb(dbus, message, instance->user_data);
  1412. if (reply)
  1413. l_dbus_send(dbus, reply);
  1414. return true;
  1415. }
  1416. LIB_EXPORT bool l_dbus_property_changed(struct l_dbus *dbus, const char *path,
  1417. const char *interface,
  1418. const char *property)
  1419. {
  1420. return _dbus_object_tree_property_changed(dbus, path, interface,
  1421. property);
  1422. }
  1423. static struct l_dbus_message *properties_get(struct l_dbus *dbus,
  1424. struct l_dbus_message *message,
  1425. void *user_data)
  1426. {
  1427. const struct interface_instance *instance;
  1428. const char *interface_name, *property_name, *signature;
  1429. const struct _dbus_property *property;
  1430. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  1431. const struct object_node *object;
  1432. struct l_dbus_message *reply;
  1433. struct l_dbus_message_builder *builder;
  1434. if (!l_dbus_message_get_arguments(message, "ss", &interface_name,
  1435. &property_name))
  1436. return l_dbus_message_new_error(message,
  1437. "org.freedesktop.DBus.Error."
  1438. "InvalidArgs",
  1439. "Invalid arguments");
  1440. object = l_hashmap_lookup(tree->objects,
  1441. l_dbus_message_get_path(message));
  1442. /* If we got here the object must exist */
  1443. instance = l_queue_find(object->instances,
  1444. match_interface_instance,
  1445. (char *) interface_name);
  1446. if (!instance)
  1447. return l_dbus_message_new_error(message,
  1448. "org.freedesktop.DBus.Error."
  1449. "InvalidArgs",
  1450. "Object has no interface %s",
  1451. interface_name);
  1452. property = _dbus_interface_find_property(instance->interface,
  1453. property_name);
  1454. if (!property)
  1455. return l_dbus_message_new_error(message,
  1456. "org.freedesktop.DBus.Error."
  1457. "InvalidArgs",
  1458. "Unknown Property %s",
  1459. property_name);
  1460. reply = l_dbus_message_new_method_return(message);
  1461. builder = l_dbus_message_builder_new(reply);
  1462. signature = property->metainfo + strlen(property->metainfo) + 1;
  1463. l_dbus_message_builder_enter_variant(builder, signature);
  1464. if (property->getter(dbus, message, builder, instance->user_data)) {
  1465. l_dbus_message_builder_leave_variant(builder);
  1466. l_dbus_message_builder_finalize(builder);
  1467. } else {
  1468. l_dbus_message_unref(reply);
  1469. reply = l_dbus_message_new_error(message,
  1470. "org.freedesktop.DBus.Error."
  1471. "Failed",
  1472. "Getting property value "
  1473. "failed");
  1474. }
  1475. l_dbus_message_builder_destroy(builder);
  1476. return reply;
  1477. }
  1478. static struct l_dbus_message *properties_set(struct l_dbus *dbus,
  1479. struct l_dbus_message *message,
  1480. void *user_data)
  1481. {
  1482. struct l_dbus_interface *interface;
  1483. const struct interface_instance *instance;
  1484. const char *interface_name, *property_name;
  1485. const struct _dbus_property *property;
  1486. struct l_dbus_message_iter variant;
  1487. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  1488. const struct object_node *object;
  1489. struct l_dbus_message *reply;
  1490. l_dbus_property_complete_cb_t complete_cb;
  1491. if (!l_dbus_message_get_arguments(message, "ssv", &interface_name,
  1492. &property_name, &variant))
  1493. return l_dbus_message_new_error(message,
  1494. "org.freedesktop.DBus.Error."
  1495. "InvalidArgs",
  1496. "Invalid arguments");
  1497. interface = l_hashmap_lookup(tree->interfaces, interface_name);
  1498. if (!interface)
  1499. return l_dbus_message_new_error(message,
  1500. "org.freedesktop.DBus.Error."
  1501. "InvalidArgs",
  1502. "Unknown Interface %s",
  1503. interface_name);
  1504. property = _dbus_interface_find_property(interface, property_name);
  1505. if (!property)
  1506. return l_dbus_message_new_error(message,
  1507. "org.freedesktop.DBus.Error."
  1508. "InvalidArgs",
  1509. "Unknown Property %s",
  1510. property_name);
  1511. if (!property->setter)
  1512. return l_dbus_message_new_error(message,
  1513. "org.freedesktop.DBus.Error."
  1514. "InvalidArgs",
  1515. "Property %s is read-only",
  1516. property_name);
  1517. object = l_hashmap_lookup(tree->objects,
  1518. l_dbus_message_get_path(message));
  1519. /* If we got here the object must exist */
  1520. instance = l_queue_find(object->instances,
  1521. match_interface_instance_ptr, interface);
  1522. if (!instance)
  1523. return l_dbus_message_new_error(message,
  1524. "org.freedesktop.DBus.Error."
  1525. "InvalidArgs",
  1526. "Object has no interface %s",
  1527. interface_name);
  1528. if (property->flags & L_DBUS_PROPERTY_FLAG_AUTO_EMIT)
  1529. complete_cb = pending_property_set_done_emit;
  1530. else
  1531. complete_cb = pending_property_set_done;
  1532. reply = property->setter(dbus, l_dbus_message_ref(message), &variant,
  1533. complete_cb, instance->user_data);
  1534. if (reply)
  1535. complete_cb(dbus, message, reply);
  1536. return NULL;
  1537. }
  1538. static struct l_dbus_message *properties_get_all(struct l_dbus *dbus,
  1539. struct l_dbus_message *message,
  1540. void *user_data)
  1541. {
  1542. const struct interface_instance *instance;
  1543. const char *interface_name;
  1544. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  1545. const struct object_node *object;
  1546. struct l_dbus_message *reply;
  1547. struct l_dbus_message_builder *builder;
  1548. if (!l_dbus_message_get_arguments(message, "s", &interface_name))
  1549. return l_dbus_message_new_error(message,
  1550. "org.freedesktop.DBus.Error."
  1551. "InvalidArgs",
  1552. "Invalid arguments");
  1553. object = l_hashmap_lookup(tree->objects,
  1554. l_dbus_message_get_path(message));
  1555. /* If we got here the object must exist */
  1556. instance = l_queue_find(object->instances,
  1557. match_interface_instance,
  1558. (char *) interface_name);
  1559. if (!instance)
  1560. return l_dbus_message_new_error(message,
  1561. "org.freedesktop.DBus.Error."
  1562. "InvalidArgs",
  1563. "Object has no interface %s",
  1564. interface_name);
  1565. reply = l_dbus_message_new_method_return(message);
  1566. builder = l_dbus_message_builder_new(reply);
  1567. if (!get_properties_dict(dbus, message, builder, instance->interface,
  1568. instance->user_data)) {
  1569. l_dbus_message_unref(reply);
  1570. reply = l_dbus_message_new_error(message,
  1571. "org.freedesktop.DBus.Error."
  1572. "Failed",
  1573. "Getting property values "
  1574. "failed");
  1575. } else
  1576. l_dbus_message_builder_finalize(builder);
  1577. l_dbus_message_builder_destroy(builder);
  1578. return reply;
  1579. }
  1580. static void properties_setup_func(struct l_dbus_interface *interface)
  1581. {
  1582. l_dbus_interface_method(interface, "Get", 0,
  1583. properties_get, "v", "ss",
  1584. "value", "interface_name", "property_name");
  1585. l_dbus_interface_method(interface, "Set", 0,
  1586. properties_set, "", "ssv",
  1587. "interface_name", "property_name", "value");
  1588. l_dbus_interface_method(interface, "GetAll", 0,
  1589. properties_get_all, "a{sv}", "s",
  1590. "props", "interface_name");
  1591. l_dbus_interface_signal(interface, "PropertiesChanged", 0, "sa{sv}as",
  1592. "interface_name", "changed_properties",
  1593. "invalidated_properties");
  1594. }
  1595. static bool collect_objects(struct l_dbus *dbus, struct l_dbus_message *message,
  1596. struct l_dbus_message_builder *builder,
  1597. const struct object_node *node,
  1598. const char *path)
  1599. {
  1600. const struct l_queue_entry *entry;
  1601. const struct child_node *child;
  1602. char *child_path;
  1603. const struct interface_instance *instance;
  1604. bool r;
  1605. if (!node->instances)
  1606. goto recurse;
  1607. l_dbus_message_builder_enter_dict(builder, "oa{sa{sv}}");
  1608. l_dbus_message_builder_append_basic(builder, 'o', path);
  1609. l_dbus_message_builder_enter_array(builder, "{sa{sv}}");
  1610. for (entry = l_queue_get_entries(node->instances); entry;
  1611. entry = entry->next) {
  1612. instance = entry->data;
  1613. l_dbus_message_builder_enter_dict(builder, "sa{sv}");
  1614. l_dbus_message_builder_append_basic(builder, 's',
  1615. instance->interface->name);
  1616. if (!get_properties_dict(dbus, message, builder,
  1617. instance->interface,
  1618. instance->user_data))
  1619. return false;
  1620. l_dbus_message_builder_leave_dict(builder);
  1621. }
  1622. l_dbus_message_builder_leave_array(builder);
  1623. l_dbus_message_builder_leave_dict(builder);
  1624. recurse:
  1625. if (!strcmp(path, "/"))
  1626. path = "";
  1627. for (child = node->children; child; child = child->next) {
  1628. child_path = l_strdup_printf("%s/%s", path, child->subpath);
  1629. r = collect_objects(dbus, message, builder,
  1630. child->node, child_path);
  1631. l_free(child_path);
  1632. if (!r)
  1633. return false;
  1634. }
  1635. return true;
  1636. }
  1637. struct l_dbus_message *_dbus_object_tree_get_objects(
  1638. struct _dbus_object_tree *tree,
  1639. struct l_dbus *dbus,
  1640. const char *path,
  1641. struct l_dbus_message *message)
  1642. {
  1643. const struct object_node *node;
  1644. struct l_dbus_message *reply;
  1645. struct l_dbus_message_builder *builder;
  1646. node = l_hashmap_lookup(tree->objects, path);
  1647. reply = l_dbus_message_new_method_return(message);
  1648. builder = l_dbus_message_builder_new(reply);
  1649. l_dbus_message_builder_enter_array(builder, "{oa{sa{sv}}}");
  1650. if (!collect_objects(dbus, message, builder, node, path)) {
  1651. l_dbus_message_builder_destroy(builder);
  1652. l_dbus_message_unref(reply);
  1653. return l_dbus_message_new_error(message,
  1654. "org.freedesktop.DBus.Error."
  1655. "Failed",
  1656. "Getting property values "
  1657. "failed");
  1658. }
  1659. l_dbus_message_builder_leave_array(builder);
  1660. l_dbus_message_builder_finalize(builder);
  1661. l_dbus_message_builder_destroy(builder);
  1662. return reply;
  1663. }
  1664. static struct l_dbus_message *get_managed_objects(struct l_dbus *dbus,
  1665. struct l_dbus_message *message,
  1666. void *user_data)
  1667. {
  1668. struct _dbus_object_tree *tree = _dbus_get_tree(dbus);
  1669. const char *path = l_dbus_message_get_path(message);
  1670. return _dbus_object_tree_get_objects(tree, dbus, path, message);
  1671. }
  1672. static void object_manager_setup_func(struct l_dbus_interface *interface)
  1673. {
  1674. l_dbus_interface_method(interface, "GetManagedObjects", 0,
  1675. get_managed_objects, "a{oa{sa{sv}}}", "",
  1676. "objpath_interfaces_and_properties");
  1677. l_dbus_interface_signal(interface, "InterfacesAdded", 0, "oa{sa{sv}}",
  1678. "object_path", "interfaces_and_properties");
  1679. l_dbus_interface_signal(interface, "InterfacesRemoved", 0, "oas",
  1680. "object_path", "interfaces");
  1681. }