data.c 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2009, Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
  5. *
  6. * See http://www.asterisk.org for more information about
  7. * the Asterisk project. Please do not directly contact
  8. * any of the maintainers of this project for assistance;
  9. * the project provides a web site, mailing lists and IRC
  10. * channels for your use.
  11. *
  12. * This program is free software, distributed under the terms of
  13. * the GNU General Public License Version 2. See the LICENSE file
  14. * at the top of the source tree.
  15. */
  16. /*! \file
  17. *
  18. * \brief Data retrieval API.
  19. *
  20. * \author Brett Bryant <brettbryant@gmail.com>
  21. * \author Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
  22. */
  23. /*** MODULEINFO
  24. <support_level>core</support_level>
  25. ***/
  26. #include "asterisk.h"
  27. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  28. #include "asterisk/_private.h"
  29. #include <regex.h>
  30. #include "asterisk/module.h"
  31. #include "asterisk/utils.h"
  32. #include "asterisk/lock.h"
  33. #include "asterisk/data.h"
  34. #include "asterisk/astobj2.h"
  35. #include "asterisk/xml.h"
  36. #include "asterisk/cli.h"
  37. #include "asterisk/term.h"
  38. #include "asterisk/manager.h"
  39. #include "asterisk/test.h"
  40. #include "asterisk/frame.h"
  41. #include "asterisk/codec.h"
  42. /*** DOCUMENTATION
  43. <manager name="DataGet" language="en_US">
  44. <synopsis>
  45. Retrieve the data api tree.
  46. </synopsis>
  47. <syntax>
  48. <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
  49. <parameter name="Path" required="true" />
  50. <parameter name="Search" />
  51. <parameter name="Filter" />
  52. </syntax>
  53. <description>
  54. <para>Retrieve the data api tree.</para>
  55. </description>
  56. </manager>
  57. ***/
  58. #define NUM_DATA_NODE_BUCKETS 59
  59. #define NUM_DATA_RESULT_BUCKETS 59
  60. #define NUM_DATA_SEARCH_BUCKETS 59
  61. #define NUM_DATA_FILTER_BUCKETS 59
  62. /*! \brief The last compatible version. */
  63. static const uint32_t latest_handler_compatible_version = 0;
  64. /*! \brief The last compatible version. */
  65. static const uint32_t latest_query_compatible_version = 0;
  66. /*! \brief Current handler structure version. */
  67. static const uint32_t current_handler_version = AST_DATA_HANDLER_VERSION;
  68. /*! \brief Current query structure version. */
  69. static const uint32_t current_query_version = AST_DATA_QUERY_VERSION;
  70. /*! \brief The data tree to be returned by the callbacks and
  71. managed by functions local to this file. */
  72. struct ast_data {
  73. enum ast_data_type type;
  74. /*! \brief The node content. */
  75. union {
  76. int32_t sint;
  77. uint32_t uint;
  78. double dbl;
  79. unsigned int boolean;
  80. char *str;
  81. char character;
  82. struct in_addr ipaddr;
  83. void *ptr;
  84. } payload;
  85. /*! \brief The filter node that depends on the current node,
  86. * this is used only when creating the result tree. */
  87. const struct data_filter *filter;
  88. /*! \brief The list of nodes inside this node. */
  89. struct ao2_container *children;
  90. /*! \brief The name of the node. */
  91. char name[0];
  92. };
  93. /*! \brief Type of comparisons allow in the search string. */
  94. enum data_search_comparison {
  95. DATA_CMP_UNKNOWN,
  96. DATA_CMP_EQ, /* = */
  97. DATA_CMP_NEQ, /* != */
  98. DATA_CMP_GT, /* > */
  99. DATA_CMP_GE, /* >= */
  100. DATA_CMP_LT, /* < */
  101. DATA_CMP_LE /* <= */
  102. };
  103. /*! \brief The list of nodes with their search requirement. */
  104. struct ast_data_search {
  105. /*! \brief The value of the comparison. */
  106. char *value;
  107. /*! \brief The type of comparison. */
  108. enum data_search_comparison cmp_type;
  109. /*! \brief reference another node. */
  110. struct ao2_container *children;
  111. /*! \brief The name of the node we are trying to compare. */
  112. char name[0];
  113. };
  114. struct data_filter;
  115. /*! \brief The filter node. */
  116. struct data_filter {
  117. /*! \brief node childrens. */
  118. struct ao2_container *children;
  119. /*! \brief glob list */
  120. AST_LIST_HEAD_NOLOCK(glob_list_t, data_filter) glob_list;
  121. /*! \brief glob list entry */
  122. AST_LIST_ENTRY(data_filter) list;
  123. /*! \brief node name. */
  124. char name[0];
  125. };
  126. /*! \brief A data container node pointing to the registered handler. */
  127. struct data_provider {
  128. /*! \brief node content handler. */
  129. const struct ast_data_handler *handler;
  130. /*! \brief Module providing this handler. */
  131. struct ast_module *module;
  132. /*! \brief children nodes. */
  133. struct ao2_container *children;
  134. /*! \brief Who registered this node. */
  135. const char *registrar;
  136. /*! \brief Node name. */
  137. char name[0];
  138. };
  139. /*! \brief This structure is used by the iterator. */
  140. struct ast_data_iterator {
  141. /*! \brief The internal iterator. */
  142. struct ao2_iterator internal_iterator;
  143. /*! \brief The last returned node. */
  144. struct ast_data *last;
  145. /*! \brief The iterator pattern. */
  146. const char *pattern;
  147. /*! \brief The compiled patter. */
  148. regex_t regex_pattern;
  149. /*! \brief is a regular expression. */
  150. unsigned int is_pattern:1;
  151. };
  152. struct {
  153. /*! \brief The asterisk data main content structure. */
  154. struct ao2_container *container;
  155. /*! \brief asterisk data locking mechanism. */
  156. ast_rwlock_t lock;
  157. } root_data;
  158. static void __data_result_print_cli(int fd, const struct ast_data *root, uint32_t depth);
  159. /*!
  160. * \internal
  161. * \brief Common string hash function.
  162. * \see ast_data_init
  163. */
  164. static int data_provider_hash(const void *obj, const int flags)
  165. {
  166. const struct data_provider *node = obj;
  167. return ast_str_case_hash(node->name);
  168. }
  169. /*!
  170. * \internal
  171. * \brief Compare two data_provider's.
  172. * \see ast_data_init
  173. */
  174. static int data_provider_cmp(void *obj1, void *obj2, int flags)
  175. {
  176. struct data_provider *node1 = obj1, *node2 = obj2;
  177. return strcasecmp(node1->name, node2->name) ? 0 : CMP_MATCH;
  178. }
  179. /*!
  180. * \internal
  181. * \brief Common string hash function for data nodes
  182. */
  183. static int data_result_hash(const void *obj, const int flags)
  184. {
  185. const struct ast_data *node = obj;
  186. return ast_str_hash(node->name);
  187. }
  188. /*!
  189. * \internal
  190. * \brief Common string comparison function
  191. */
  192. static int data_result_cmp(void *obj, void *arg, int flags)
  193. {
  194. struct ast_data *node1 = obj, *node2 = arg;
  195. return strcasecmp(node1->name, node2->name) ? 0 : CMP_MATCH;
  196. }
  197. /*!
  198. * \internal
  199. * \brief Lock the data registered handlers structure for writing.
  200. * \see data_unlock
  201. */
  202. #define data_write_lock() ast_rwlock_wrlock(&root_data.lock)
  203. /*!
  204. * \internal
  205. * \brief Lock the data registered handlers structure for reading.
  206. * \see data_unlock
  207. */
  208. #define data_read_lock() ast_rwlock_rdlock(&root_data.lock)
  209. /*!
  210. * \internal
  211. * \brief Unlock the data registered handlers structure.
  212. */
  213. #define data_unlock() ast_rwlock_unlock(&root_data.lock)
  214. /*!
  215. * \internal
  216. * \brief Check if a version is compatible with the current core.
  217. * \param[in] structure_version The current structure version.
  218. * \param[in] latest_compatible The latest compatible version.
  219. * \param[in] current The current Data API version.
  220. * \retval 1 If the module is compatible.
  221. * \retval 0 If the module is NOT compatible.
  222. */
  223. static int data_structure_compatible(int structure_version, uint32_t latest_compatible,
  224. uint32_t current)
  225. {
  226. if (structure_version >= latest_compatible && structure_version <= current) {
  227. return 1;
  228. }
  229. ast_log(LOG_ERROR, "A module is not compatible with the"
  230. "current data api version\n");
  231. return 0;
  232. }
  233. /*!
  234. * \internal
  235. * \brief Get the next node name in a path (/node1/node2)
  236. * Avoid null nodes like //node1//node2/node3.
  237. * \param[in] path The path where we are going to search for the next node name.
  238. * \retval The next node name we found inside the given path.
  239. * \retval NULL if there are no more node names.
  240. */
  241. static char *next_node_name(char **path)
  242. {
  243. char *res;
  244. do {
  245. res = strsep(path, "/");
  246. } while (res && ast_strlen_zero(res));
  247. return res;
  248. }
  249. /*!
  250. * \internal
  251. * \brief Release the memory allocated by a call to ao2_alloc.
  252. */
  253. static void data_provider_destructor(void *obj)
  254. {
  255. struct data_provider *provider = obj;
  256. ao2_ref(provider->children, -1);
  257. }
  258. /*!
  259. * \internal
  260. * \brief Create a new data node.
  261. * \param[in] name The name of the node we are going to create.
  262. * \param[in] handler The handler registered for this node.
  263. * \param[in] registrar The name of the registrar.
  264. * \retval NULL on error.
  265. * \retval The allocated data node structure.
  266. */
  267. static struct data_provider *data_provider_new(const char *name,
  268. const struct ast_data_handler *handler, const char *registrar)
  269. {
  270. struct data_provider *node;
  271. size_t namelen;
  272. namelen = strlen(name) + 1;
  273. node = ao2_alloc(sizeof(*node) + namelen, data_provider_destructor);
  274. if (!node) {
  275. return NULL;
  276. }
  277. node->handler = handler;
  278. node->registrar = registrar;
  279. strcpy(node->name, name);
  280. /* initialize the childrens container. */
  281. if (!(node->children = ao2_container_alloc(NUM_DATA_NODE_BUCKETS,
  282. data_provider_hash, data_provider_cmp))) {
  283. ao2_ref(node, -1);
  284. return NULL;
  285. }
  286. return node;
  287. }
  288. /*!
  289. * \internal
  290. * \brief Add a child node named 'name' to the 'parent' node.
  291. * \param[in] parent Where to add the child node.
  292. * \param[in] name The name of the child node.
  293. * \param[in] handler The handler structure.
  294. * \param[in] registrar Who registered this node.
  295. * \retval NULL on error.
  296. * \retval A newly allocated child in parent.
  297. */
  298. static struct data_provider *data_provider_add_child(struct ao2_container *parent,
  299. const char *name, const struct ast_data_handler *handler, const char *registrar)
  300. {
  301. struct data_provider *child;
  302. child = data_provider_new(name, handler, registrar);
  303. if (!child) {
  304. return NULL;
  305. }
  306. ao2_link(parent, child);
  307. return child;
  308. }
  309. /*!
  310. * \internal
  311. * \brief Find a child node, based on his name.
  312. * \param[in] parent Where to find the node.
  313. * \param[in] name The node name to find.
  314. * \param[in] registrar Also check if the node was being used by this registrar.
  315. * \retval NULL if a node wasn't found.
  316. * \retval The node found.
  317. * \note Remember to decrement the ref count of the returned node after using it.
  318. */
  319. static struct data_provider *data_provider_find(struct ao2_container *parent,
  320. const char *name, const char *registrar)
  321. {
  322. struct data_provider *find_node, *found;
  323. /* XXX avoid allocating a new data node for searching... */
  324. find_node = data_provider_new(name, NULL, NULL);
  325. if (!find_node) {
  326. return NULL;
  327. }
  328. found = ao2_find(parent, find_node, OBJ_POINTER);
  329. /* free the created node used for searching. */
  330. ao2_ref(find_node, -1);
  331. if (found && found->registrar && registrar) {
  332. if (strcmp(found->registrar, registrar)) {
  333. /* if the name doesn't match, do not return this node. */
  334. ast_debug(1, "Registrar doesn't match, node was registered"
  335. " by '%s' and we are searching for '%s'\n",
  336. found->registrar, registrar);
  337. ao2_ref(found, -1);
  338. return NULL;
  339. }
  340. }
  341. return found;
  342. }
  343. /*!
  344. * \internal
  345. * \brief Release a group of nodes.
  346. * \param[in] parent The parent node.
  347. * \param[in] path The path of nodes to release.
  348. * \param[in] registrar Who registered this node.
  349. * \retval <0 on error.
  350. * \retval 0 on success.
  351. * \see data_provider_create
  352. */
  353. static int data_provider_release(struct ao2_container *parent, const char *path,
  354. const char *registrar)
  355. {
  356. char *node_name, *rpath;
  357. struct data_provider *child;
  358. int ret = 0;
  359. rpath = ast_strdupa(path);
  360. node_name = next_node_name(&rpath);
  361. if (!node_name) {
  362. return -1;
  363. }
  364. child = data_provider_find(parent, node_name, registrar);
  365. if (!child) {
  366. return -1;
  367. }
  368. /* if this is not a terminal node. */
  369. if (!child->handler && rpath) {
  370. ret = data_provider_release(child->children, rpath, registrar);
  371. }
  372. /* if this node is empty, unlink it. */
  373. if (!ret && !ao2_container_count(child->children)) {
  374. ao2_unlink(parent, child);
  375. }
  376. ao2_ref(child, -1);
  377. return ret;
  378. }
  379. /*!
  380. * \internal
  381. * \brief Release every node registered by 'registrar'.
  382. * \param[in] parent The parent node.
  383. * \param[in] registrar
  384. * \see __ast_data_unregister
  385. */
  386. static void data_provider_release_all(struct ao2_container *parent,
  387. const char *registrar)
  388. {
  389. struct ao2_iterator i;
  390. struct data_provider *node;
  391. i = ao2_iterator_init(parent, 0);
  392. while ((node = ao2_iterator_next(&i))) {
  393. if (!node->handler) {
  394. /* this is a non-terminal node, go inside it. */
  395. data_provider_release_all(node->children, registrar);
  396. if (!ao2_container_count(node->children)) {
  397. /* if this node was left empty, unlink it. */
  398. ao2_unlink(parent, node);
  399. }
  400. } else {
  401. if (!strcmp(node->registrar, registrar)) {
  402. /* if the registrars match, release it! */
  403. ao2_unlink(parent, node);
  404. }
  405. }
  406. ao2_ref(node, -1);
  407. }
  408. ao2_iterator_destroy(&i);
  409. }
  410. /*!
  411. * \internal
  412. * \brief Create the middle nodes for the specified path (asterisk/testnode1/childnode)
  413. * \param[in] parent Where to add the middle nodes structure.
  414. * \param[in] path The path of nodes to add.
  415. * \param[in] registrar Who is trying to create this node provider.
  416. * \retval NULL on error.
  417. * \retval The created node.
  418. * \see data_provider_release
  419. */
  420. static struct data_provider *data_provider_create(struct ao2_container *parent,
  421. const char *path, const char *registrar)
  422. {
  423. char *rpath, *node_name;
  424. struct data_provider *child, *ret = NULL;
  425. rpath = ast_strdupa(path);
  426. node_name = next_node_name(&rpath);
  427. if (!node_name) {
  428. /* no more nodes to create. */
  429. return NULL;
  430. }
  431. child = data_provider_find(parent, node_name, NULL);
  432. if (!child) {
  433. /* nodes without handler are non-terminal nodes. */
  434. child = data_provider_add_child(parent, node_name, NULL, registrar);
  435. }
  436. if (rpath) {
  437. ret = data_provider_create(child->children, rpath, registrar);
  438. if (ret) {
  439. ao2_ref(child, -1);
  440. }
  441. }
  442. return ret ? ret : child;
  443. }
  444. int __ast_data_register(const char *path, const struct ast_data_handler *handler,
  445. const char *registrar, struct ast_module *mod)
  446. {
  447. struct data_provider *node;
  448. if (!path) {
  449. return -1;
  450. }
  451. /* check if the handler structure is compatible. */
  452. if (!data_structure_compatible(handler->version,
  453. latest_handler_compatible_version,
  454. current_handler_version)) {
  455. return -1;
  456. }
  457. /* create the node structure for the registered handler. */
  458. data_write_lock();
  459. node = data_provider_create(root_data.container, path, registrar);
  460. if (!node) {
  461. ast_log(LOG_ERROR, "Unable to create the specified path (%s) "
  462. "for '%s'.\n", path, registrar);
  463. data_unlock();
  464. return -1;
  465. }
  466. if (ao2_container_count(node->children) || node->handler) {
  467. ast_log(LOG_ERROR, "The node '%s' was already registered. "
  468. "We were unable to register '%s' for registrar '%s'.\n",
  469. node->name, path, registrar);
  470. ao2_ref(node, -1);
  471. data_unlock();
  472. return -1;
  473. }
  474. /* add handler to that node. */
  475. node->handler = handler;
  476. node->module = mod;
  477. ao2_ref(node, -1);
  478. data_unlock();
  479. return 0;
  480. }
  481. int __ast_data_register_multiple(const struct ast_data_entry *data_entries,
  482. size_t entries, const char *registrar, struct ast_module *mod)
  483. {
  484. int i, res;
  485. for (i = 0; i < entries; i++) {
  486. res = __ast_data_register(data_entries[i].path, data_entries[i].handler,
  487. registrar, mod);
  488. if (res) {
  489. /* unregister all the already registered nodes, and make
  490. * this an atomic action. */
  491. while ((--i) >= 0) {
  492. __ast_data_unregister(data_entries[i].path, registrar);
  493. }
  494. return -1;
  495. }
  496. }
  497. return 0;
  498. }
  499. int __ast_data_unregister(const char *path, const char *registrar)
  500. {
  501. int ret = 0;
  502. data_write_lock();
  503. if (path) {
  504. ret = data_provider_release(root_data.container, path, registrar);
  505. } else {
  506. data_provider_release_all(root_data.container, registrar);
  507. }
  508. data_unlock();
  509. if (path && ret) {
  510. ast_log(LOG_ERROR, "Unable to unregister '%s' for '%s'\n",
  511. path, registrar);
  512. }
  513. return ret;
  514. }
  515. /*!
  516. * \internal
  517. * \brief Is a char used to specify a comparison?
  518. * \param[in] a Character to evaluate.
  519. * \retval 1 It is a char used to specify a comparison.
  520. * \retval 0 It is NOT a char used to specify a comparison.
  521. */
  522. static int data_search_comparison_char(char a)
  523. {
  524. switch (a) {
  525. case '!':
  526. case '=':
  527. case '<':
  528. case '>':
  529. return 1;
  530. }
  531. return 0;
  532. }
  533. /*!
  534. * \internal
  535. * \brief Get the type of comparison.
  536. */
  537. static enum data_search_comparison data_search_comparison_type(const char *comparison)
  538. {
  539. if (!strcmp(comparison, "=")) {
  540. return DATA_CMP_EQ;
  541. } else if (!strcmp(comparison, "!=")) {
  542. return DATA_CMP_NEQ;
  543. } else if (!strcmp(comparison, "<")) {
  544. return DATA_CMP_LT;
  545. } else if (!strcmp(comparison, ">")) {
  546. return DATA_CMP_GT;
  547. } else if (!strcmp(comparison, "<=")) {
  548. return DATA_CMP_LE;
  549. } else if (!strcmp(comparison, ">=")) {
  550. return DATA_CMP_GE;
  551. }
  552. return DATA_CMP_UNKNOWN;
  553. }
  554. /*!
  555. * \internal
  556. * \brief Common string hash function for data nodes
  557. */
  558. static int data_search_hash(const void *obj, const int flags)
  559. {
  560. const struct ast_data_search *node = obj;
  561. return ast_str_hash(node->name);
  562. }
  563. /*!
  564. * \internal
  565. * \brief Common string comparison function
  566. */
  567. static int data_search_cmp(void *obj, void *arg, int flags)
  568. {
  569. struct ast_data_search *node1 = obj, *node2 = arg;
  570. return strcasecmp(node1->name, node2->name) ? 0 : CMP_MATCH;
  571. }
  572. /*!
  573. * \internal
  574. * \brief Destroy the ao2 search node.
  575. */
  576. static void data_search_destructor(void *obj)
  577. {
  578. struct ast_data_search *node = obj;
  579. if (node->value) {
  580. ast_free(node->value);
  581. }
  582. ao2_ref(node->children, -1);
  583. }
  584. /*!
  585. * \internal
  586. * \brief Allocate a search node.
  587. * \retval NULL on error.
  588. * \retval non-NULL The allocated search node structure.
  589. */
  590. static struct ast_data_search *data_search_alloc(const char *name)
  591. {
  592. struct ast_data_search *res;
  593. size_t name_len = strlen(name) + 1;
  594. res = ao2_alloc(sizeof(*res) + name_len, data_search_destructor);
  595. if (!res) {
  596. return NULL;
  597. }
  598. res->children = ao2_container_alloc(NUM_DATA_SEARCH_BUCKETS, data_search_hash,
  599. data_search_cmp);
  600. if (!res->children) {
  601. ao2_ref(res, -1);
  602. return NULL;
  603. }
  604. strcpy(res->name, name);
  605. return res;
  606. }
  607. /*!
  608. * \internal
  609. * \brief Find a child node, based on his name.
  610. * \param[in] parent Where to find the node.
  611. * \param[in] name The node name to find.
  612. * \retval NULL if a node wasn't found.
  613. * \retval The node found.
  614. * \note Remember to decrement the ref count of the returned node after using it.
  615. */
  616. static struct ast_data_search *data_search_find(struct ao2_container *parent,
  617. const char *name)
  618. {
  619. struct ast_data_search *find_node, *found;
  620. find_node = data_search_alloc(name);
  621. if (!find_node) {
  622. return NULL;
  623. }
  624. found = ao2_find(parent, find_node, OBJ_POINTER);
  625. /* free the created node used for searching. */
  626. ao2_ref(find_node, -1);
  627. return found;
  628. }
  629. /*!
  630. * \internal
  631. * \brief Add a child node named 'name' to the 'parent' node.
  632. * \param[in] parent Where to add the child node.
  633. * \param[in] name The name of the child node.
  634. * \retval NULL on error.
  635. * \retval A newly allocated child in parent.
  636. */
  637. static struct ast_data_search *data_search_add_child(struct ao2_container *parent,
  638. const char *name)
  639. {
  640. struct ast_data_search *child;
  641. child = data_search_alloc(name);
  642. if (!child) {
  643. return NULL;
  644. }
  645. ao2_link(parent, child);
  646. return child;
  647. }
  648. /*!
  649. * \internal
  650. * \brief Create the middle nodes for the specified path (asterisk/testnode1/childnode)
  651. * \param[in] parent Where to add the middle nodes structure.
  652. * \param[in] path The path of nodes to add.
  653. * \retval NULL on error.
  654. * \retval The created node.
  655. */
  656. static struct ast_data_search *data_search_create(struct ao2_container *parent,
  657. const char *path)
  658. {
  659. char *rpath, *node_name;
  660. struct ast_data_search *child = NULL;
  661. struct ao2_container *current = parent;
  662. rpath = ast_strdupa(path);
  663. node_name = next_node_name(&rpath);
  664. while (node_name) {
  665. child = data_search_find(current, node_name);
  666. if (!child) {
  667. child = data_search_add_child(current, node_name);
  668. }
  669. ao2_ref(child, -1);
  670. current = child->children;
  671. node_name = next_node_name(&rpath);
  672. }
  673. return child;
  674. }
  675. /*!
  676. * \internal
  677. * \brief Allocate a tree with the search string parsed.
  678. * \param[in] search_string The search string.
  679. * \retval NULL on error.
  680. * \retval non-NULL A dynamically allocated search tree.
  681. */
  682. static struct ast_data_search *data_search_generate(const char *search_string)
  683. {
  684. struct ast_str *name, *value, *comparison;
  685. char *elements, *search_string_dup, *saveptr;
  686. int i;
  687. struct ast_data_search *root, *child;
  688. enum data_search_comparison cmp_type;
  689. size_t search_string_len;
  690. if (!search_string) {
  691. ast_log(LOG_ERROR, "You must pass a valid search string.\n");
  692. return NULL;
  693. }
  694. search_string_len = strlen(search_string);
  695. name = ast_str_create(search_string_len);
  696. if (!name) {
  697. return NULL;
  698. }
  699. value = ast_str_create(search_string_len);
  700. if (!value) {
  701. ast_free(name);
  702. return NULL;
  703. }
  704. comparison = ast_str_create(search_string_len);
  705. if (!comparison) {
  706. ast_free(name);
  707. ast_free(value);
  708. return NULL;
  709. }
  710. search_string_dup = ast_strdupa(search_string);
  711. /* Create the root node (just used as a container) */
  712. root = data_search_alloc("/");
  713. if (!root) {
  714. ast_free(name);
  715. ast_free(value);
  716. ast_free(comparison);
  717. return NULL;
  718. }
  719. for (elements = strtok_r(search_string_dup, ",", &saveptr); elements;
  720. elements = strtok_r(NULL, ",", &saveptr)) {
  721. /* Parse the name */
  722. ast_str_reset(name);
  723. for (i = 0; !data_search_comparison_char(elements[i]) &&
  724. elements[i]; i++) {
  725. ast_str_append(&name, 0, "%c", elements[i]);
  726. }
  727. /* check if the syntax is ok. */
  728. if (!data_search_comparison_char(elements[i])) {
  729. /* if this is the end of the string, then this is
  730. * an error! */
  731. ast_log(LOG_ERROR, "Invalid search string!\n");
  732. continue;
  733. }
  734. /* parse the comparison string. */
  735. ast_str_reset(comparison);
  736. for (; data_search_comparison_char(elements[i]) && elements[i]; i++) {
  737. ast_str_append(&comparison, 0, "%c", elements[i]);
  738. }
  739. /* parse the value string. */
  740. ast_str_reset(value);
  741. for (; elements[i]; i++) {
  742. ast_str_append(&value, 0, "%c", elements[i]);
  743. }
  744. cmp_type = data_search_comparison_type(ast_str_buffer(comparison));
  745. if (cmp_type == DATA_CMP_UNKNOWN) {
  746. ast_log(LOG_ERROR, "Invalid comparison '%s'\n",
  747. ast_str_buffer(comparison));
  748. continue;
  749. }
  750. /* add this node to the tree. */
  751. child = data_search_create(root->children, ast_str_buffer(name));
  752. if (child) {
  753. child->cmp_type = cmp_type;
  754. child->value = ast_strdup(ast_str_buffer(value));
  755. }
  756. }
  757. ast_free(name);
  758. ast_free(value);
  759. ast_free(comparison);
  760. return root;
  761. }
  762. /*!
  763. * \internal
  764. * \brief Release the allocated memory for the search tree.
  765. * \param[in] search The search tree root node.
  766. */
  767. static void data_search_release(struct ast_data_search *search)
  768. {
  769. ao2_ref(search, -1);
  770. }
  771. /*!
  772. * \internal
  773. * \brief Based on the kind of comparison and the result in cmpval, return
  774. * if it matches.
  775. * \param[in] cmpval A result returned by a strcmp() for example.
  776. * \param[in] comparison_type The kind of comparison (<,>,=,!=,...)
  777. * \retval 1 If the comparison doesn't match.
  778. * \retval 0 If the comparison matches.
  779. */
  780. static inline int data_search_comparison_result(int cmpval,
  781. enum data_search_comparison comparison_type)
  782. {
  783. switch (comparison_type) {
  784. case DATA_CMP_GE:
  785. if (cmpval >= 0) {
  786. return 0;
  787. }
  788. break;
  789. case DATA_CMP_LE:
  790. if (cmpval <= 0) {
  791. return 0;
  792. }
  793. break;
  794. case DATA_CMP_EQ:
  795. if (cmpval == 0) {
  796. return 0;
  797. }
  798. break;
  799. case DATA_CMP_NEQ:
  800. if (cmpval != 0) {
  801. return 0;
  802. }
  803. break;
  804. case DATA_CMP_LT:
  805. if (cmpval < 0) {
  806. return 0;
  807. }
  808. break;
  809. case DATA_CMP_GT:
  810. if (cmpval > 0) {
  811. return 0;
  812. }
  813. break;
  814. case DATA_CMP_UNKNOWN:
  815. break;
  816. }
  817. return 1;
  818. }
  819. /*!
  820. * \internal
  821. * \brief Get an internal node, from the search tree.
  822. * \param[in] node A node container.
  823. * \param[in] path The path to the needed internal node.
  824. * \retval NULL if the internal node is not found.
  825. * \retval non-NULL the internal node with path 'path'.
  826. */
  827. static struct ast_data_search *data_search_get_node(const struct ast_data_search *node,
  828. const char *path)
  829. {
  830. char *savepath, *node_name;
  831. struct ast_data_search *child, *current = (struct ast_data_search *) node;
  832. if (!node) {
  833. return NULL;
  834. }
  835. savepath = ast_strdupa(path);
  836. node_name = next_node_name(&savepath);
  837. while (node_name) {
  838. child = data_search_find(current->children, node_name);
  839. if (current != node) {
  840. ao2_ref(current, -1);
  841. }
  842. if (!child) {
  843. return NULL;
  844. };
  845. current = child;
  846. node_name = next_node_name(&savepath);
  847. }
  848. return current;
  849. }
  850. /*!
  851. * \internal
  852. * \brief Based on a search tree, evaluate the specified 'name' inside the tree with the
  853. * current string value.
  854. * .search = "somename=somestring"
  855. * name = "somename"
  856. * value is the current value of something and will be evaluated against "somestring".
  857. * \param[in] root The root node pointer of the search tree.
  858. * \param[in] name The name of the specific.
  859. * \param[in] value The value to compare.
  860. * \returns The strcmp return value.
  861. */
  862. static int data_search_cmp_string(const struct ast_data_search *root, const char *name,
  863. char *value)
  864. {
  865. struct ast_data_search *child;
  866. enum data_search_comparison cmp_type;
  867. int ret;
  868. child = data_search_get_node(root, name);
  869. if (!child) {
  870. return 0;
  871. }
  872. ret = strcmp(value, child->value);
  873. cmp_type = child->cmp_type;
  874. ao2_ref(child, -1);
  875. return data_search_comparison_result(ret, cmp_type);
  876. }
  877. /*!
  878. * \internal
  879. * \brief Based on a search tree, evaluate the specified 'name' inside the tree with the
  880. * current pointer address value.
  881. * .search = "something=0x32323232"
  882. * name = "something"
  883. * value is the current value of something and will be evaluated against "0x32323232".
  884. * \param[in] root The root node pointer of the search tree.
  885. * \param[in] name The name of the specific.
  886. * \param[in] ptr The pointer address to compare.
  887. * \returns The (value - current_value) result.
  888. */
  889. static int data_search_cmp_ptr(const struct ast_data_search *root, const char *name,
  890. void *ptr)
  891. {
  892. struct ast_data_search *child;
  893. enum data_search_comparison cmp_type;
  894. void *node_ptr;
  895. child = data_search_get_node(root, name);
  896. if (!child) {
  897. return 0;
  898. }
  899. cmp_type = child->cmp_type;
  900. if (sscanf(child->value, "%p", &node_ptr) <= 0) {
  901. ao2_ref(child, -1);
  902. return 1;
  903. }
  904. ao2_ref(child, -1);
  905. return data_search_comparison_result((node_ptr - ptr), cmp_type);
  906. }
  907. /*!
  908. * \internal
  909. * \brief Based on a search tree, evaluate the specified 'name' inside the tree with the
  910. * current ipv4 address value.
  911. * .search = "something=192.168.2.2"
  912. * name = "something"
  913. * value is the current value of something and will be evaluated against "192.168.2.2".
  914. * \param[in] root The root node pointer of the search tree.
  915. * \param[in] name The name of the specific.
  916. * \param[in] addr The ipv4 address value to compare.
  917. * \returns The (value - current_value) result.
  918. */
  919. static int data_search_cmp_ipaddr(const struct ast_data_search *root, const char *name,
  920. struct in_addr addr)
  921. {
  922. struct ast_data_search *child;
  923. enum data_search_comparison cmp_type;
  924. struct in_addr node_addr;
  925. child = data_search_get_node(root, name);
  926. if (!child) {
  927. return 0;
  928. }
  929. cmp_type = child->cmp_type;
  930. inet_aton(child->value, &node_addr);
  931. ao2_ref(child, -1);
  932. return data_search_comparison_result((node_addr.s_addr - addr.s_addr), cmp_type);
  933. }
  934. /*!
  935. * \internal
  936. * \brief Based on a search tree, evaluate the specified 'name' inside the tree with the
  937. * current boolean value.
  938. * .search = "something=true"
  939. * name = "something"
  940. * value is the current value of something and will be evaluated against "true".
  941. * \param[in] root The root node pointer of the search tree.
  942. * \param[in] name The name of the specific.
  943. * \param[in] value The boolean value to compare.
  944. * \returns The (value - current_value) result.
  945. */
  946. static int data_search_cmp_bool(const struct ast_data_search *root, const char *name,
  947. unsigned int value)
  948. {
  949. struct ast_data_search *child;
  950. unsigned int node_value;
  951. enum data_search_comparison cmp_type;
  952. child = data_search_get_node(root, name);
  953. if (!child) {
  954. return 0;
  955. }
  956. node_value = abs(ast_true(child->value));
  957. cmp_type = child->cmp_type;
  958. ao2_ref(child, -1);
  959. return data_search_comparison_result(value - node_value, cmp_type);
  960. }
  961. /*!
  962. * \internal
  963. * \brief Based on a search tree, evaluate the specified 'name' inside the tree with the
  964. * current double value.
  965. * .search = "something=222"
  966. * name = "something"
  967. * value is the current value of something and will be evaluated against "222".
  968. * \param[in] root The root node pointer of the search tree.
  969. * \param[in] name The name of the specific.
  970. * \param[in] value The double value to compare.
  971. * \returns The (value - current_value) result.
  972. */
  973. static int data_search_cmp_dbl(const struct ast_data_search *root, const char *name,
  974. double value)
  975. {
  976. struct ast_data_search *child;
  977. double node_value;
  978. enum data_search_comparison cmp_type;
  979. child = data_search_get_node(root, name);
  980. if (!child) {
  981. return 0;
  982. }
  983. node_value = strtod(child->value, NULL);
  984. cmp_type = child->cmp_type;
  985. ao2_ref(child, -1);
  986. return data_search_comparison_result(value - node_value, cmp_type);
  987. }
  988. /*!
  989. * \internal
  990. * \brief Based on a search tree, evaluate the specified 'name' inside the tree with the
  991. * current unsigned integer value.
  992. * .search = "something=10"
  993. * name = "something"
  994. * value is the current value of something and will be evaluated against "10".
  995. * \param[in] root The root node pointer of the search tree.
  996. * \param[in] name The name of the specific.
  997. * \param[in] value The unsigned value to compare.
  998. * \returns The strcmp return value.
  999. */
  1000. static int data_search_cmp_uint(const struct ast_data_search *root, const char *name,
  1001. unsigned int value)
  1002. {
  1003. struct ast_data_search *child;
  1004. unsigned int node_value;
  1005. enum data_search_comparison cmp_type;
  1006. child = data_search_get_node(root, name);
  1007. if (!child) {
  1008. return 0;
  1009. }
  1010. node_value = atoi(child->value);
  1011. cmp_type = child->cmp_type;
  1012. ao2_ref(child, -1);
  1013. return data_search_comparison_result(value - node_value, cmp_type);
  1014. }
  1015. /*!
  1016. * \internal
  1017. * \brief Based on a search tree, evaluate the specified 'name' inside the tree with the
  1018. * current signed integer value.
  1019. * .search = "something=10"
  1020. * name = "something"
  1021. * value is the current value of something and will be evaluated against "10".
  1022. * \param[in] root The root node pointer of the search tree.
  1023. * \param[in] name The name of the specific.
  1024. * \param[in] value The value to compare.
  1025. * \returns The strcmp return value.
  1026. */
  1027. static int data_search_cmp_int(const struct ast_data_search *root, const char *name,
  1028. int value)
  1029. {
  1030. struct ast_data_search *child;
  1031. int node_value;
  1032. enum data_search_comparison cmp_type;
  1033. child = data_search_get_node(root, name);
  1034. if (!child) {
  1035. return 0;
  1036. }
  1037. node_value = atoi(child->value);
  1038. cmp_type = child->cmp_type;
  1039. ao2_ref(child, -1);
  1040. return data_search_comparison_result(value - node_value, cmp_type);
  1041. }
  1042. /*!
  1043. * \internal
  1044. * \brief Based on a search tree, evaluate the specified 'name' inside the tree with the
  1045. * current character value.
  1046. * .search = "something=c"
  1047. * name = "something"
  1048. * value is the current value of something and will be evaluated against "c".
  1049. * \param[in] root The root node pointer of the search tree.
  1050. * \param[in] name The name of the specific.
  1051. * \param[in] value The boolean value to compare.
  1052. * \returns The (value - current_value) result.
  1053. */
  1054. static int data_search_cmp_char(const struct ast_data_search *root, const char *name,
  1055. char value)
  1056. {
  1057. struct ast_data_search *child;
  1058. char node_value;
  1059. enum data_search_comparison cmp_type;
  1060. child = data_search_get_node(root, name);
  1061. if (!child) {
  1062. return 0;
  1063. }
  1064. node_value = *(child->value);
  1065. cmp_type = child->cmp_type;
  1066. ao2_ref(child, -1);
  1067. return data_search_comparison_result(value - node_value, cmp_type);
  1068. }
  1069. /*!
  1070. * \internal
  1071. * \brief Get the member pointer, from a mapping structure, based on its name.
  1072. * \XXX We will need to improve performance here!!.
  1073. * \retval <0 if the member was not found.
  1074. * \retval >=0 The member position in the mapping structure.
  1075. */
  1076. static inline int data_search_mapping_find(const struct ast_data_mapping_structure *map,
  1077. size_t mapping_len,
  1078. const char *member_name)
  1079. {
  1080. int i;
  1081. for (i = 0; i < mapping_len; i++) {
  1082. if (!strcmp(map[i].name, member_name)) {
  1083. return i;
  1084. }
  1085. }
  1086. return -1;
  1087. }
  1088. int __ast_data_search_cmp_structure(const struct ast_data_search *search,
  1089. const struct ast_data_mapping_structure *mapping, size_t mapping_len,
  1090. void *structure, const char *structure_name)
  1091. {
  1092. struct ao2_iterator i;
  1093. struct ast_data_search *node, *struct_children;
  1094. int member, notmatch = 0;
  1095. if (!search) {
  1096. return 0;
  1097. }
  1098. struct_children = data_search_get_node(search, structure_name);
  1099. if (!struct_children) {
  1100. return 0;
  1101. }
  1102. i = ao2_iterator_init(struct_children->children, 0);
  1103. while ((node = ao2_iterator_next(&i))) {
  1104. member = data_search_mapping_find(mapping, mapping_len, node->name);
  1105. if (member < 0) {
  1106. /* the structure member name doesn't match! */
  1107. ao2_ref(node, -1);
  1108. ao2_ref(struct_children, -1);
  1109. ao2_iterator_destroy(&i);
  1110. return 0;
  1111. }
  1112. notmatch = 0;
  1113. switch (mapping[member].type) {
  1114. case AST_DATA_PASSWORD:
  1115. notmatch = data_search_cmp_string(struct_children,
  1116. node->name,
  1117. mapping[member].get.AST_DATA_PASSWORD(structure));
  1118. break;
  1119. case AST_DATA_TIMESTAMP:
  1120. notmatch = data_search_cmp_uint(struct_children,
  1121. node->name,
  1122. mapping[member].get.AST_DATA_TIMESTAMP(structure));
  1123. break;
  1124. case AST_DATA_SECONDS:
  1125. notmatch = data_search_cmp_uint(struct_children,
  1126. node->name,
  1127. mapping[member].get.AST_DATA_SECONDS(structure));
  1128. break;
  1129. case AST_DATA_MILLISECONDS:
  1130. notmatch = data_search_cmp_uint(struct_children,
  1131. node->name,
  1132. mapping[member].get.AST_DATA_MILLISECONDS(structure));
  1133. break;
  1134. case AST_DATA_STRING:
  1135. notmatch = data_search_cmp_string(struct_children,
  1136. node->name,
  1137. mapping[member].get.AST_DATA_STRING(structure));
  1138. break;
  1139. case AST_DATA_CHARACTER:
  1140. notmatch = data_search_cmp_char(struct_children,
  1141. node->name,
  1142. mapping[member].get.AST_DATA_CHARACTER(structure));
  1143. break;
  1144. case AST_DATA_INTEGER:
  1145. notmatch = data_search_cmp_int(struct_children,
  1146. node->name,
  1147. mapping[member].get.AST_DATA_INTEGER(structure));
  1148. break;
  1149. case AST_DATA_BOOLEAN:
  1150. notmatch = data_search_cmp_bool(struct_children,
  1151. node->name,
  1152. mapping[member].get.AST_DATA_BOOLEAN(structure));
  1153. break;
  1154. case AST_DATA_UNSIGNED_INTEGER:
  1155. notmatch = data_search_cmp_uint(struct_children,
  1156. node->name,
  1157. mapping[member].get.AST_DATA_UNSIGNED_INTEGER(structure));
  1158. break;
  1159. case AST_DATA_DOUBLE:
  1160. notmatch = data_search_cmp_dbl(struct_children,
  1161. node->name,
  1162. mapping[member].get.AST_DATA_DOUBLE(structure));
  1163. break;
  1164. case AST_DATA_IPADDR:
  1165. notmatch = data_search_cmp_ipaddr(struct_children,
  1166. node->name,
  1167. mapping[member].get.AST_DATA_IPADDR(structure));
  1168. break;
  1169. case AST_DATA_POINTER:
  1170. notmatch = data_search_cmp_ptr(struct_children,
  1171. node->name,
  1172. mapping[member].get.AST_DATA_POINTER(structure));
  1173. break;
  1174. case AST_DATA_CONTAINER:
  1175. break;
  1176. }
  1177. ao2_ref(node, -1);
  1178. }
  1179. ao2_iterator_destroy(&i);
  1180. ao2_ref(struct_children, -1);
  1181. return notmatch;
  1182. }
  1183. /*!
  1184. * \internal
  1185. * \brief Release the memory allocated by a call to ao2_alloc.
  1186. */
  1187. static void data_result_destructor(void *obj)
  1188. {
  1189. struct ast_data *root = obj;
  1190. switch (root->type) {
  1191. case AST_DATA_PASSWORD:
  1192. case AST_DATA_STRING:
  1193. ast_free(root->payload.str);
  1194. ao2_ref(root->children, -1);
  1195. break;
  1196. case AST_DATA_POINTER:
  1197. case AST_DATA_CHARACTER:
  1198. case AST_DATA_CONTAINER:
  1199. case AST_DATA_INTEGER:
  1200. case AST_DATA_TIMESTAMP:
  1201. case AST_DATA_SECONDS:
  1202. case AST_DATA_MILLISECONDS:
  1203. case AST_DATA_UNSIGNED_INTEGER:
  1204. case AST_DATA_DOUBLE:
  1205. case AST_DATA_BOOLEAN:
  1206. case AST_DATA_IPADDR:
  1207. ao2_ref(root->children, -1);
  1208. break;
  1209. }
  1210. }
  1211. static struct ast_data *data_result_create(const char *name)
  1212. {
  1213. struct ast_data *res;
  1214. size_t namelen;
  1215. namelen = ast_strlen_zero(name) ? 1 : strlen(name) + 1;
  1216. res = ao2_alloc(sizeof(*res) + namelen, data_result_destructor);
  1217. if (!res) {
  1218. return NULL;
  1219. }
  1220. strcpy(res->name, namelen ? name : "");
  1221. /* initialize the children container */
  1222. res->children = ao2_container_alloc(NUM_DATA_RESULT_BUCKETS, data_result_hash,
  1223. data_result_cmp);
  1224. if (!res->children) {
  1225. ao2_ref(res, -1);
  1226. return NULL;
  1227. }
  1228. /* set this node as a container. */
  1229. res->type = AST_DATA_CONTAINER;
  1230. return res;
  1231. }
  1232. /*!
  1233. * \internal
  1234. * \brief Find a child node, based on its name.
  1235. * \param[in] root The starting point.
  1236. * \param[in] name The child name.
  1237. * \retval NULL if the node wasn't found.
  1238. * \retval non-NULL the node we were looking for.
  1239. */
  1240. static struct ast_data *data_result_find_child(struct ast_data *root, const char *name)
  1241. {
  1242. struct ast_data *found, *find_node;
  1243. find_node = data_result_create(name);
  1244. if (!find_node) {
  1245. return NULL;
  1246. }
  1247. found = ao2_find(root->children, find_node, OBJ_POINTER);
  1248. /* release the temporary created node used for searching. */
  1249. ao2_ref(find_node, -1);
  1250. return found;
  1251. }
  1252. int ast_data_search_match(const struct ast_data_search *search, struct ast_data *data)
  1253. {
  1254. struct ao2_iterator i, ii;
  1255. struct ast_data_search *s, *s_child;
  1256. struct ast_data *d_child;
  1257. int notmatch = 1;
  1258. if (!search) {
  1259. return 1;
  1260. }
  1261. s_child = data_search_find(search->children, data->name);
  1262. if (!s_child) {
  1263. /* nothing to compare */
  1264. ao2_ref(s_child, -1);
  1265. return 1;
  1266. }
  1267. i = ao2_iterator_init(s_child->children, 0);
  1268. while ((s = ao2_iterator_next(&i))) {
  1269. if (!ao2_container_count(s->children)) {
  1270. /* compare this search node with every data node */
  1271. d_child = data_result_find_child(data, s->name);
  1272. if (!d_child) {
  1273. ao2_ref(s, -1);
  1274. notmatch = 1;
  1275. continue;
  1276. }
  1277. switch (d_child->type) {
  1278. case AST_DATA_PASSWORD:
  1279. case AST_DATA_STRING:
  1280. notmatch = data_search_cmp_string(s_child, d_child->name,
  1281. d_child->payload.str);
  1282. break;
  1283. case AST_DATA_CHARACTER:
  1284. notmatch = data_search_cmp_char(s_child, d_child->name,
  1285. d_child->payload.character);
  1286. break;
  1287. case AST_DATA_INTEGER:
  1288. notmatch = data_search_cmp_int(s_child, d_child->name,
  1289. d_child->payload.sint);
  1290. break;
  1291. case AST_DATA_BOOLEAN:
  1292. notmatch = data_search_cmp_bool(s_child, d_child->name,
  1293. d_child->payload.boolean);
  1294. break;
  1295. case AST_DATA_UNSIGNED_INTEGER:
  1296. notmatch = data_search_cmp_uint(s_child, d_child->name,
  1297. d_child->payload.uint);
  1298. break;
  1299. case AST_DATA_TIMESTAMP:
  1300. case AST_DATA_SECONDS:
  1301. case AST_DATA_MILLISECONDS:
  1302. case AST_DATA_DOUBLE:
  1303. notmatch = data_search_cmp_uint(s_child, d_child->name,
  1304. d_child->payload.dbl);
  1305. break;
  1306. case AST_DATA_IPADDR:
  1307. notmatch = data_search_cmp_ipaddr(s_child, d_child->name,
  1308. d_child->payload.ipaddr);
  1309. break;
  1310. case AST_DATA_POINTER:
  1311. notmatch = data_search_cmp_ptr(s_child, d_child->name,
  1312. d_child->payload.ptr);
  1313. break;
  1314. case AST_DATA_CONTAINER:
  1315. break;
  1316. }
  1317. ao2_ref(d_child, -1);
  1318. } else {
  1319. ii = ao2_iterator_init(data->children, 0);
  1320. while ((d_child = ao2_iterator_next(&ii))) {
  1321. if (strcmp(d_child->name, s->name)) {
  1322. ao2_ref(d_child, -1);
  1323. continue;
  1324. }
  1325. if (!(notmatch = !ast_data_search_match(s_child, d_child))) {
  1326. /* do not continue if we have a match. */
  1327. ao2_ref(d_child, -1);
  1328. break;
  1329. }
  1330. ao2_ref(d_child, -1);
  1331. }
  1332. ao2_iterator_destroy(&ii);
  1333. }
  1334. ao2_ref(s, -1);
  1335. if (notmatch) {
  1336. /* do not continue if we don't have a match. */
  1337. break;
  1338. }
  1339. }
  1340. ao2_iterator_destroy(&i);
  1341. ao2_ref(s_child, -1);
  1342. return !notmatch;
  1343. }
  1344. /*!
  1345. * \internal
  1346. * \brief Get an internal node, from the result set.
  1347. * \param[in] node A node container.
  1348. * \param[in] path The path to the needed internal node.
  1349. * \retval NULL if the internal node is not found.
  1350. * \retval non-NULL the internal node with path 'path'.
  1351. */
  1352. static struct ast_data *data_result_get_node(struct ast_data *node,
  1353. const char *path)
  1354. {
  1355. char *savepath, *node_name;
  1356. struct ast_data *child, *current = node;
  1357. savepath = ast_strdupa(path);
  1358. node_name = next_node_name(&savepath);
  1359. while (node_name) {
  1360. child = data_result_find_child(current, node_name);
  1361. if (current != node) {
  1362. ao2_ref(current, -1);
  1363. }
  1364. if (!child) {
  1365. return NULL;
  1366. }
  1367. current = child;
  1368. node_name = next_node_name(&savepath);
  1369. }
  1370. /* do not increment the refcount of the returned object. */
  1371. if (current != node) {
  1372. ao2_ref(current, -1);
  1373. }
  1374. return current;
  1375. }
  1376. /*!
  1377. * \internal
  1378. * \brief Add a child to the specified root node.
  1379. * \param[in] root The root node pointer.
  1380. * \param[in] child The child to add to the root node.
  1381. */
  1382. static void data_result_add_child(struct ast_data *root, struct ast_data *child)
  1383. {
  1384. ao2_link(root->children, child);
  1385. }
  1386. /*!
  1387. * \internal
  1388. * \brief Common string hash function for data nodes
  1389. */
  1390. static int data_filter_hash(const void *obj, const int flags)
  1391. {
  1392. const struct data_filter *node = obj;
  1393. return ast_str_hash(node->name);
  1394. }
  1395. /*!
  1396. * \internal
  1397. * \brief Common string comparison function
  1398. */
  1399. static int data_filter_cmp(void *obj, void *arg, int flags)
  1400. {
  1401. struct data_filter *node1 = obj, *node2 = arg;
  1402. return strcasecmp(node1->name, node2->name) ? 0 : CMP_MATCH;
  1403. }
  1404. /*!
  1405. * \internal
  1406. * \brief Destroy a data filter tree.
  1407. * \param[in] obj Data filter list to be destroyed.
  1408. */
  1409. static void data_filter_destructor(void *obj)
  1410. {
  1411. struct data_filter *filter = obj, *globres;
  1412. while ((globres = AST_LIST_REMOVE_HEAD(&(filter->glob_list), list))) {
  1413. ao2_ref(globres, -1);
  1414. }
  1415. ao2_ref(filter->children, -1);
  1416. }
  1417. /*!
  1418. * \internal
  1419. * \brief Allocate a filter node.
  1420. * \retval NULL on error.
  1421. * \retval non-NULL The allocated search node structure.
  1422. */
  1423. static struct data_filter *data_filter_alloc(const char *name)
  1424. {
  1425. char *globname, *token;
  1426. struct data_filter *res, *globfilter;
  1427. size_t name_len = strlen(name) + 1;
  1428. res = ao2_alloc(sizeof(*res) + name_len, data_filter_destructor);
  1429. if (!res) {
  1430. return NULL;
  1431. }
  1432. res->children = ao2_container_alloc(NUM_DATA_FILTER_BUCKETS, data_filter_hash,
  1433. data_filter_cmp);
  1434. if (!res->children) {
  1435. ao2_ref(res, -1);
  1436. return NULL;
  1437. }
  1438. strcpy(res->name, name);
  1439. if (strchr(res->name, '*')) {
  1440. globname = ast_strdupa(res->name);
  1441. while ((token = strsep(&globname, "*"))) {
  1442. globfilter = data_filter_alloc(token);
  1443. AST_LIST_INSERT_TAIL(&(res->glob_list), globfilter, list);
  1444. }
  1445. }
  1446. return res;
  1447. }
  1448. /*!
  1449. * \internal
  1450. * \brief Release a filter tree.
  1451. * \param[in] filter The filter tree root node.
  1452. */
  1453. static void data_filter_release(struct data_filter *filter)
  1454. {
  1455. ao2_ref(filter, -1);
  1456. }
  1457. /*!
  1458. * \internal
  1459. * \brief Find a child node, based on his name.
  1460. * \param[in] parent Where to find the node.
  1461. * \param[in] name The node name to find.
  1462. * \retval NULL if a node wasn't found.
  1463. * \retval The node found.
  1464. * \note Remember to decrement the ref count of the returned node after using it.
  1465. */
  1466. static struct data_filter *data_filter_find(struct ao2_container *parent,
  1467. const char *name)
  1468. {
  1469. int i, olend, orend, globfound;
  1470. size_t name_len = strlen(name), glob_len;
  1471. struct ao2_iterator iter;
  1472. struct data_filter *find_node, *found, *globres;
  1473. find_node = data_filter_alloc(name);
  1474. if (!find_node) {
  1475. return NULL;
  1476. }
  1477. found = ao2_find(parent, find_node, OBJ_POINTER);
  1478. /* free the created node used for searching. */
  1479. ao2_ref(find_node, -1);
  1480. if (found) {
  1481. return found;
  1482. }
  1483. iter = ao2_iterator_init(parent, 0);
  1484. while ((found = ao2_iterator_next(&iter))) {
  1485. if (!AST_LIST_EMPTY(&(found->glob_list))) {
  1486. i = 0;
  1487. globfound = 1;
  1488. olend = ast_strlen_zero(AST_LIST_FIRST(&(found->glob_list))->name);
  1489. orend = ast_strlen_zero(AST_LIST_LAST(&(found->glob_list))->name);
  1490. AST_LIST_TRAVERSE(&(found->glob_list), globres, list) {
  1491. if (!*globres->name) {
  1492. continue;
  1493. }
  1494. glob_len = strlen(globres->name);
  1495. if (!i && !olend) {
  1496. if (strncasecmp(name, globres->name, glob_len)) {
  1497. globfound = 0;
  1498. break;
  1499. }
  1500. i += glob_len;
  1501. continue;
  1502. }
  1503. for (globfound = 0; name_len - i >= glob_len; ++i) {
  1504. if (!strncasecmp(name + i, globres->name, glob_len)) {
  1505. globfound = 1;
  1506. i += glob_len;
  1507. break;
  1508. }
  1509. }
  1510. if (!globfound) {
  1511. break;
  1512. }
  1513. }
  1514. if (globfound && (i == name_len || orend)) {
  1515. ao2_iterator_destroy(&iter);
  1516. return found;
  1517. }
  1518. }
  1519. ao2_ref(found, -1);
  1520. }
  1521. ao2_iterator_destroy(&iter);
  1522. return NULL;
  1523. }
  1524. /*!
  1525. * \internal
  1526. * \brief Add a child to the specified node.
  1527. * \param[in] root The root node where to add the child.
  1528. * \param[in] name The name of the node to add.
  1529. * \note Remember to decrement the ref count after using the returned node.
  1530. */
  1531. static struct data_filter *data_filter_add_child(struct ao2_container *root,
  1532. char *name)
  1533. {
  1534. struct data_filter *node;
  1535. node = data_filter_find(root, name);
  1536. if (node) {
  1537. return node;
  1538. }
  1539. node = data_filter_alloc(name);
  1540. if (!node) {
  1541. return NULL;
  1542. }
  1543. ao2_link(root, node);
  1544. return node;
  1545. }
  1546. /*!
  1547. * \internal
  1548. * \brief Add a node to a filter list from a path
  1549. * \param[in] Filter list to add the path onto.
  1550. * \param[in] The path to add into the filter list.
  1551. * \retval NULL on error.
  1552. * \retval non-NULL A tree with the wanted nodes.
  1553. */
  1554. static int data_filter_add_nodes(struct ao2_container *root, char *path)
  1555. {
  1556. struct data_filter *node;
  1557. char *savepath, *saveptr, *token, *node_name;
  1558. int ret = 0;
  1559. if (!path) {
  1560. return 0;
  1561. }
  1562. savepath = ast_strdupa(path);
  1563. node_name = next_node_name(&savepath);
  1564. if (!node_name) {
  1565. return 0;
  1566. }
  1567. for (token = strtok_r(node_name, "|", &saveptr);
  1568. token; token = strtok_r(NULL, "|", &saveptr)) {
  1569. node = data_filter_add_child(root, token);
  1570. if (!node) {
  1571. continue;
  1572. }
  1573. data_filter_add_nodes(node->children, savepath);
  1574. ret = 1;
  1575. ao2_ref(node, -1);
  1576. }
  1577. return ret;
  1578. }
  1579. /*!
  1580. * \internal
  1581. * \brief Generate a filter list based on a filter string provided by the API user.
  1582. * \param[in] A filter string to create a filter from.
  1583. */
  1584. static struct data_filter *data_filter_generate(const char *constfilter)
  1585. {
  1586. struct data_filter *filter = NULL;
  1587. char *strfilter, *token, *saveptr;
  1588. int node_added = 0;
  1589. if (!constfilter) {
  1590. return NULL;
  1591. }
  1592. strfilter = ast_strdupa(constfilter);
  1593. filter = data_filter_alloc("/");
  1594. if (!filter) {
  1595. return NULL;
  1596. }
  1597. for (token = strtok_r(strfilter, ",", &saveptr); token;
  1598. token = strtok_r(NULL, ",", &saveptr)) {
  1599. node_added = data_filter_add_nodes(filter->children, token);
  1600. }
  1601. if (!node_added) {
  1602. ao2_ref(filter, -1);
  1603. return NULL;
  1604. }
  1605. return filter;
  1606. }
  1607. /*!
  1608. * \internal
  1609. * \brief Generate all the tree from a specified provider.
  1610. * \param[in] query The query executed.
  1611. * \param[in] root_provider The provider specified in the path of the query.
  1612. * \param[in] parent_node_name The root node name.
  1613. * \retval NULL on error.
  1614. * \retval non-NULL The generated result tree.
  1615. */
  1616. static struct ast_data *data_result_generate_node(const struct ast_data_query *query,
  1617. const struct data_provider *root_provider,
  1618. const char *parent_node_name,
  1619. const struct ast_data_search *search,
  1620. const struct data_filter *filter)
  1621. {
  1622. struct ast_data *generated, *node;
  1623. struct ao2_iterator i;
  1624. struct data_provider *provider;
  1625. struct ast_data_search *search_child = NULL;
  1626. struct data_filter *filter_child;
  1627. node = data_result_create(parent_node_name);
  1628. if (!node) {
  1629. ast_log(LOG_ERROR, "Unable to allocate '%s' node\n", parent_node_name);
  1630. return NULL;
  1631. }
  1632. if (root_provider->module) {
  1633. ast_module_ref(root_provider->module);
  1634. }
  1635. /* if this is a terminal node, just run the callback function. */
  1636. if (root_provider->handler && root_provider->handler->get) {
  1637. node->filter = filter;
  1638. root_provider->handler->get(search, node);
  1639. if (root_provider->module) {
  1640. ast_module_unref(root_provider->module);
  1641. }
  1642. return node;
  1643. }
  1644. if (root_provider->module) {
  1645. ast_module_unref(root_provider->module);
  1646. }
  1647. /* if this is not a terminal node, generate every child node. */
  1648. i = ao2_iterator_init(root_provider->children, 0);
  1649. while ((provider = ao2_iterator_next(&i))) {
  1650. filter_child = NULL;
  1651. generated = NULL;
  1652. /* get the internal search node. */
  1653. if (search) {
  1654. search_child = data_search_find(search->children, provider->name);
  1655. }
  1656. /* get the internal filter node. */
  1657. if (filter) {
  1658. filter_child = data_filter_find(filter->children, provider->name);
  1659. }
  1660. if (!filter || filter_child) {
  1661. /* only generate the internal node, if we have something to
  1662. * generate based on the filtering string. */
  1663. generated = data_result_generate_node(query, provider,
  1664. provider->name,
  1665. search_child, filter_child);
  1666. }
  1667. /* decrement the refcount of the internal search node. */
  1668. if (search_child) {
  1669. ao2_ref(search_child, -1);
  1670. }
  1671. /* decrement the refcount of the internal filter node. */
  1672. if (filter_child) {
  1673. ao2_ref(filter_child, -1);
  1674. }
  1675. if (generated) {
  1676. data_result_add_child(node, generated);
  1677. ao2_ref(generated, -1);
  1678. }
  1679. ao2_ref(provider, -1);
  1680. }
  1681. ao2_iterator_destroy(&i);
  1682. return node;
  1683. }
  1684. /*!
  1685. * \internal
  1686. * \brief Generate a result tree based on a query.
  1687. * \param[in] query The complete query structure.
  1688. * \param[in] search_path The path to retrieve.
  1689. * \retval NULL on error.
  1690. * \retval non-NULL The generated data result.
  1691. */
  1692. static struct ast_data *data_result_generate(const struct ast_data_query *query,
  1693. const char *search_path)
  1694. {
  1695. char *node_name, *tmp_path;
  1696. struct data_provider *provider_child, *tmp_provider_child;
  1697. struct ast_data *result, *result_filtered;
  1698. struct ast_data_search *search = NULL, *search_child = NULL;
  1699. struct data_filter *filter = NULL, *filter_child = NULL;
  1700. if (!search_path) {
  1701. /* generate all the trees?. */
  1702. return NULL;
  1703. }
  1704. tmp_path = ast_strdupa(search_path);
  1705. /* start searching the root node name */
  1706. node_name = next_node_name(&tmp_path);
  1707. if (!node_name) {
  1708. return NULL;
  1709. }
  1710. provider_child = data_provider_find(root_data.container, node_name, NULL);
  1711. /* continue with the rest of the path. */
  1712. while (provider_child) {
  1713. node_name = next_node_name(&tmp_path);
  1714. if (!node_name) {
  1715. break;
  1716. }
  1717. tmp_provider_child = data_provider_find(provider_child->children,
  1718. node_name, NULL);
  1719. /* release the reference from this child */
  1720. ao2_ref(provider_child, -1);
  1721. provider_child = tmp_provider_child;
  1722. }
  1723. if (!provider_child) {
  1724. ast_log(LOG_ERROR, "Invalid path '%s', '%s' not found.\n",
  1725. tmp_path, node_name);
  1726. return NULL;
  1727. }
  1728. /* generate the search tree. */
  1729. if (query->search) {
  1730. search = data_search_generate(query->search);
  1731. if (search) {
  1732. search_child = data_search_find(search->children,
  1733. provider_child->name);
  1734. }
  1735. }
  1736. /* generate the filter tree. */
  1737. if (query->filter) {
  1738. filter = data_filter_generate(query->filter);
  1739. if (filter) {
  1740. filter_child = data_filter_find(filter->children,
  1741. provider_child->name);
  1742. }
  1743. }
  1744. result = data_result_generate_node(query, provider_child, provider_child->name,
  1745. search_child, filter_child);
  1746. /* release the requested provider. */
  1747. ao2_ref(provider_child, -1);
  1748. /* release the generated search tree. */
  1749. if (search_child) {
  1750. ao2_ref(search_child, -1);
  1751. }
  1752. if (filter_child) {
  1753. ao2_ref(filter_child, -1);
  1754. }
  1755. if (search) {
  1756. data_search_release(search);
  1757. }
  1758. result_filtered = result;
  1759. /* release the generated filter tree. */
  1760. if (filter) {
  1761. data_filter_release(filter);
  1762. }
  1763. return result_filtered;
  1764. }
  1765. struct ast_data *ast_data_get(const struct ast_data_query *query)
  1766. {
  1767. struct ast_data *res;
  1768. /* check compatibility */
  1769. if (!data_structure_compatible(query->version, latest_query_compatible_version,
  1770. current_query_version)) {
  1771. return NULL;
  1772. }
  1773. data_read_lock();
  1774. res = data_result_generate(query, query->path);
  1775. data_unlock();
  1776. if (!res) {
  1777. ast_log(LOG_ERROR, "Unable to get data from %s\n", query->path);
  1778. return NULL;
  1779. }
  1780. return res;
  1781. }
  1782. #ifdef HAVE_LIBXML2
  1783. /*!
  1784. * \internal
  1785. * \brief Helper function to move an ast_data tree to xml.
  1786. * \param[in] parent_data The initial ast_data node to be passed to xml.
  1787. * \param[out] parent_xml The root node to insert the xml.
  1788. */
  1789. static void data_get_xml_add_child(struct ast_data *parent_data,
  1790. struct ast_xml_node *parent_xml)
  1791. {
  1792. struct ao2_iterator i;
  1793. struct ast_data *node;
  1794. struct ast_xml_node *child_xml;
  1795. char node_content[256];
  1796. i = ao2_iterator_init(parent_data->children, 0);
  1797. while ((node = ao2_iterator_next(&i))) {
  1798. child_xml = ast_xml_new_node(node->name);
  1799. if (!child_xml) {
  1800. ao2_ref(node, -1);
  1801. continue;
  1802. }
  1803. switch (node->type) {
  1804. case AST_DATA_CONTAINER:
  1805. data_get_xml_add_child(node, child_xml);
  1806. break;
  1807. case AST_DATA_PASSWORD:
  1808. ast_xml_set_text(child_xml, node->payload.str);
  1809. break;
  1810. case AST_DATA_TIMESTAMP:
  1811. snprintf(node_content, sizeof(node_content), "%u",
  1812. node->payload.uint);
  1813. ast_xml_set_text(child_xml, node_content);
  1814. break;
  1815. case AST_DATA_SECONDS:
  1816. snprintf(node_content, sizeof(node_content), "%u",
  1817. node->payload.uint);
  1818. ast_xml_set_text(child_xml, node_content);
  1819. break;
  1820. case AST_DATA_MILLISECONDS:
  1821. snprintf(node_content, sizeof(node_content), "%u",
  1822. node->payload.uint);
  1823. ast_xml_set_text(child_xml, node_content);
  1824. break;
  1825. case AST_DATA_STRING:
  1826. ast_xml_set_text(child_xml, node->payload.str);
  1827. break;
  1828. case AST_DATA_CHARACTER:
  1829. snprintf(node_content, sizeof(node_content), "%c",
  1830. node->payload.character);
  1831. ast_xml_set_text(child_xml, node_content);
  1832. break;
  1833. case AST_DATA_INTEGER:
  1834. snprintf(node_content, sizeof(node_content), "%d",
  1835. node->payload.sint);
  1836. ast_xml_set_text(child_xml, node_content);
  1837. break;
  1838. case AST_DATA_UNSIGNED_INTEGER:
  1839. snprintf(node_content, sizeof(node_content), "%u",
  1840. node->payload.uint);
  1841. ast_xml_set_text(child_xml, node_content);
  1842. break;
  1843. case AST_DATA_DOUBLE:
  1844. snprintf(node_content, sizeof(node_content), "%f",
  1845. node->payload.dbl);
  1846. ast_xml_set_text(child_xml, node_content);
  1847. break;
  1848. case AST_DATA_BOOLEAN:
  1849. if (node->payload.boolean) {
  1850. ast_xml_set_text(child_xml, "true");
  1851. } else {
  1852. ast_xml_set_text(child_xml, "false");
  1853. }
  1854. break;
  1855. case AST_DATA_POINTER:
  1856. snprintf(node_content, sizeof(node_content), "%p",
  1857. node->payload.ptr);
  1858. ast_xml_set_text(child_xml, node_content);
  1859. break;
  1860. case AST_DATA_IPADDR:
  1861. snprintf(node_content, sizeof(node_content), "%s",
  1862. ast_inet_ntoa(node->payload.ipaddr));
  1863. ast_xml_set_text(child_xml, node_content);
  1864. break;
  1865. }
  1866. ast_xml_add_child(parent_xml, child_xml);
  1867. ao2_ref(node, -1);
  1868. }
  1869. ao2_iterator_destroy(&i);
  1870. }
  1871. struct ast_xml_doc *ast_data_get_xml(const struct ast_data_query *query)
  1872. {
  1873. struct ast_xml_doc *doc;
  1874. struct ast_xml_node *root;
  1875. struct ast_data *res;
  1876. res = ast_data_get(query);
  1877. if (!res) {
  1878. return NULL;
  1879. }
  1880. doc = ast_xml_new();
  1881. if (!doc) {
  1882. ast_data_free(res);
  1883. return NULL;
  1884. }
  1885. root = ast_xml_new_node(res->name);
  1886. if (!root) {
  1887. ast_xml_close(doc);
  1888. }
  1889. ast_xml_set_root(doc, root);
  1890. data_get_xml_add_child(res, root);
  1891. ast_data_free(res);
  1892. return doc;
  1893. }
  1894. #endif
  1895. enum ast_data_type ast_data_retrieve_type(struct ast_data *node, const char *path)
  1896. {
  1897. struct ast_data *internal;
  1898. internal = data_result_get_node(node, path);
  1899. if (!internal) {
  1900. return -1;
  1901. }
  1902. return internal->type;
  1903. }
  1904. char *ast_data_retrieve_name(struct ast_data *node)
  1905. {
  1906. return node->name;
  1907. }
  1908. /*!
  1909. * \internal
  1910. * \brief Insert a child node inside a passed parent node.
  1911. * \param root Where we are going to insert the child node.
  1912. * \param name The name of the child node to add.
  1913. * \param type The type of content inside the child node.
  1914. * \param ptr The actual content of the child node.
  1915. * \retval NULL on error.
  1916. * \retval non-NULL The added child node pointer.
  1917. */
  1918. static struct ast_data *__ast_data_add(struct ast_data *root, const char *name,
  1919. enum ast_data_type type, void *ptr)
  1920. {
  1921. struct ast_data *node;
  1922. struct data_filter *filter, *filter_child = NULL;
  1923. if (!root || !root->children) {
  1924. /* invalid data result node. */
  1925. return NULL;
  1926. }
  1927. /* check if we need to add this node, based on the filter. */
  1928. if (root->filter) {
  1929. filter = data_filter_find(root->filter->children, name);
  1930. if (!filter) {
  1931. return NULL;
  1932. }
  1933. ao2_ref(filter, -1);
  1934. }
  1935. node = data_result_create(name);
  1936. if (!node) {
  1937. return NULL;
  1938. }
  1939. node->type = type;
  1940. switch (type) {
  1941. case AST_DATA_BOOLEAN:
  1942. node->payload.boolean = *(unsigned int *) ptr;
  1943. break;
  1944. case AST_DATA_INTEGER:
  1945. node->payload.sint = *(int *) ptr;
  1946. break;
  1947. case AST_DATA_TIMESTAMP:
  1948. case AST_DATA_SECONDS:
  1949. case AST_DATA_MILLISECONDS:
  1950. case AST_DATA_UNSIGNED_INTEGER:
  1951. node->payload.uint = *(unsigned int *) ptr;
  1952. break;
  1953. case AST_DATA_DOUBLE:
  1954. node->payload.dbl = *(double *) ptr;
  1955. break;
  1956. case AST_DATA_PASSWORD:
  1957. case AST_DATA_STRING:
  1958. node->payload.str = (char *) ptr;
  1959. break;
  1960. case AST_DATA_CHARACTER:
  1961. node->payload.character = *(char *) ptr;
  1962. break;
  1963. case AST_DATA_POINTER:
  1964. node->payload.ptr = ptr;
  1965. break;
  1966. case AST_DATA_IPADDR:
  1967. node->payload.ipaddr = *(struct in_addr *) ptr;
  1968. break;
  1969. case AST_DATA_CONTAINER:
  1970. if (root->filter) {
  1971. filter_child = data_filter_find(root->filter->children, name);
  1972. if (filter_child) {
  1973. /* do not increment the refcount because it is not neccesary. */
  1974. ao2_ref(filter_child, -1);
  1975. }
  1976. }
  1977. node->filter = filter_child;
  1978. break;
  1979. default:
  1980. break;
  1981. }
  1982. data_result_add_child(root, node);
  1983. ao2_ref(node, -1);
  1984. return node;
  1985. }
  1986. struct ast_data *ast_data_add_node(struct ast_data *root, const char *name)
  1987. {
  1988. return __ast_data_add(root, name, AST_DATA_CONTAINER, NULL);
  1989. }
  1990. struct ast_data *ast_data_add_int(struct ast_data *root, const char *name, int value)
  1991. {
  1992. return __ast_data_add(root, name, AST_DATA_INTEGER, &value);
  1993. }
  1994. struct ast_data *ast_data_add_char(struct ast_data *root, const char *name, char value)
  1995. {
  1996. return __ast_data_add(root, name, AST_DATA_CHARACTER, &value);
  1997. }
  1998. struct ast_data *ast_data_add_uint(struct ast_data *root, const char *name,
  1999. unsigned int value)
  2000. {
  2001. return __ast_data_add(root, name, AST_DATA_UNSIGNED_INTEGER, &value);
  2002. }
  2003. struct ast_data *ast_data_add_dbl(struct ast_data *root, const char *childname,
  2004. double dbl)
  2005. {
  2006. return __ast_data_add(root, childname, AST_DATA_DOUBLE, &dbl);
  2007. }
  2008. struct ast_data *ast_data_add_bool(struct ast_data *root, const char *childname,
  2009. unsigned int boolean)
  2010. {
  2011. return __ast_data_add(root, childname, AST_DATA_BOOLEAN, &boolean);
  2012. }
  2013. struct ast_data *ast_data_add_ipaddr(struct ast_data *root, const char *childname,
  2014. struct in_addr addr)
  2015. {
  2016. return __ast_data_add(root, childname, AST_DATA_IPADDR, &addr);
  2017. }
  2018. struct ast_data *ast_data_add_ptr(struct ast_data *root, const char *childname,
  2019. void *ptr)
  2020. {
  2021. return __ast_data_add(root, childname, AST_DATA_POINTER, ptr);
  2022. }
  2023. struct ast_data *ast_data_add_timestamp(struct ast_data *root, const char *childname,
  2024. unsigned int timestamp)
  2025. {
  2026. return __ast_data_add(root, childname, AST_DATA_TIMESTAMP, &timestamp);
  2027. }
  2028. struct ast_data *ast_data_add_seconds(struct ast_data *root, const char *childname,
  2029. unsigned int seconds)
  2030. {
  2031. return __ast_data_add(root, childname, AST_DATA_SECONDS, &seconds);
  2032. }
  2033. struct ast_data *ast_data_add_milliseconds(struct ast_data *root, const char *childname,
  2034. unsigned int milliseconds)
  2035. {
  2036. return __ast_data_add(root, childname, AST_DATA_MILLISECONDS, &milliseconds);
  2037. }
  2038. struct ast_data *ast_data_add_password(struct ast_data *root, const char *childname,
  2039. const char *value)
  2040. {
  2041. char *name;
  2042. size_t namelen = 1 + (ast_strlen_zero(value) ? 0 : strlen(value));
  2043. struct ast_data *res;
  2044. if (!(name = ast_malloc(namelen))) {
  2045. return NULL;
  2046. }
  2047. strcpy(name, (ast_strlen_zero(value) ? "" : value));
  2048. res = __ast_data_add(root, childname, AST_DATA_PASSWORD, name);
  2049. if (!res) {
  2050. ast_free(name);
  2051. }
  2052. return res;
  2053. }
  2054. struct ast_data *ast_data_add_str(struct ast_data *root, const char *childname,
  2055. const char *value)
  2056. {
  2057. char *name;
  2058. size_t namelen = 1 + (ast_strlen_zero(value) ? 0 : strlen(value));
  2059. struct ast_data *res;
  2060. if (!(name = ast_malloc(namelen))) {
  2061. return NULL;
  2062. }
  2063. strcpy(name, (ast_strlen_zero(value) ? "" : value));
  2064. res = __ast_data_add(root, childname, AST_DATA_STRING, name);
  2065. if (!res) {
  2066. ast_free(name);
  2067. }
  2068. return res;
  2069. }
  2070. int __ast_data_add_structure(struct ast_data *root,
  2071. const struct ast_data_mapping_structure *mapping, size_t mapping_len,
  2072. void *structure)
  2073. {
  2074. int i;
  2075. for (i = 0; i < mapping_len; i++) {
  2076. switch (mapping[i].type) {
  2077. case AST_DATA_INTEGER:
  2078. ast_data_add_int(root, mapping[i].name,
  2079. mapping[i].get.AST_DATA_INTEGER(structure));
  2080. break;
  2081. case AST_DATA_UNSIGNED_INTEGER:
  2082. ast_data_add_uint(root, mapping[i].name,
  2083. mapping[i].get.AST_DATA_UNSIGNED_INTEGER(structure));
  2084. break;
  2085. case AST_DATA_DOUBLE:
  2086. ast_data_add_dbl(root, mapping[i].name,
  2087. mapping[i].get.AST_DATA_DOUBLE(structure));
  2088. break;
  2089. case AST_DATA_BOOLEAN:
  2090. ast_data_add_bool(root, mapping[i].name,
  2091. mapping[i].get.AST_DATA_BOOLEAN(structure));
  2092. break;
  2093. case AST_DATA_PASSWORD:
  2094. ast_data_add_password(root, mapping[i].name,
  2095. mapping[i].get.AST_DATA_PASSWORD(structure));
  2096. break;
  2097. case AST_DATA_TIMESTAMP:
  2098. ast_data_add_timestamp(root, mapping[i].name,
  2099. mapping[i].get.AST_DATA_TIMESTAMP(structure));
  2100. break;
  2101. case AST_DATA_SECONDS:
  2102. ast_data_add_seconds(root, mapping[i].name,
  2103. mapping[i].get.AST_DATA_SECONDS(structure));
  2104. break;
  2105. case AST_DATA_MILLISECONDS:
  2106. ast_data_add_milliseconds(root, mapping[i].name,
  2107. mapping[i].get.AST_DATA_MILLISECONDS(structure));
  2108. break;
  2109. case AST_DATA_STRING:
  2110. ast_data_add_str(root, mapping[i].name,
  2111. mapping[i].get.AST_DATA_STRING(structure));
  2112. break;
  2113. case AST_DATA_CHARACTER:
  2114. ast_data_add_char(root, mapping[i].name,
  2115. mapping[i].get.AST_DATA_CHARACTER(structure));
  2116. break;
  2117. case AST_DATA_CONTAINER:
  2118. break;
  2119. case AST_DATA_IPADDR:
  2120. ast_data_add_ipaddr(root, mapping[i].name,
  2121. mapping[i].get.AST_DATA_IPADDR(structure));
  2122. break;
  2123. case AST_DATA_POINTER:
  2124. ast_data_add_ptr(root, mapping[i].name,
  2125. mapping[i].get.AST_DATA_POINTER(structure));
  2126. break;
  2127. }
  2128. }
  2129. return 0;
  2130. }
  2131. void ast_data_remove_node(struct ast_data *root, struct ast_data *child)
  2132. {
  2133. ao2_unlink(root->children, child);
  2134. }
  2135. void ast_data_free(struct ast_data *root)
  2136. {
  2137. /* destroy it, this will destroy all the internal nodes. */
  2138. ao2_ref(root, -1);
  2139. }
  2140. struct ast_data_iterator *ast_data_iterator_init(struct ast_data *tree,
  2141. const char *elements)
  2142. {
  2143. struct ast_data_iterator *iterator;
  2144. struct ao2_iterator i;
  2145. struct ast_data *internal = tree;
  2146. char *path, *ptr = NULL;
  2147. if (!elements) {
  2148. return NULL;
  2149. }
  2150. /* tree is the node we want to use to iterate? or we are going
  2151. * to iterate thow an internal node? */
  2152. path = ast_strdupa(elements);
  2153. ptr = strrchr(path, '/');
  2154. if (ptr) {
  2155. *ptr = '\0';
  2156. internal = data_result_get_node(tree, path);
  2157. if (!internal) {
  2158. return NULL;
  2159. }
  2160. }
  2161. iterator = ast_calloc(1, sizeof(*iterator));
  2162. if (!iterator) {
  2163. return NULL;
  2164. }
  2165. i = ao2_iterator_init(internal->children, 0);
  2166. iterator->pattern = (ptr ? strrchr(elements, '/') + 1 : elements);
  2167. /* is the last node a regular expression?, compile it! */
  2168. if (!regcomp(&(iterator->regex_pattern), iterator->pattern,
  2169. REG_EXTENDED | REG_NOSUB | REG_ICASE)) {
  2170. iterator->is_pattern = 1;
  2171. }
  2172. iterator->internal_iterator = i;
  2173. return iterator;
  2174. }
  2175. void ast_data_iterator_end(struct ast_data_iterator *iterator)
  2176. {
  2177. /* decrement the reference counter. */
  2178. if (iterator->last) {
  2179. ao2_ref(iterator->last, -1);
  2180. }
  2181. /* release the generated pattern. */
  2182. if (iterator->is_pattern) {
  2183. regfree(&(iterator->regex_pattern));
  2184. }
  2185. ao2_iterator_destroy(&(iterator->internal_iterator));
  2186. ast_free(iterator);
  2187. iterator = NULL;
  2188. }
  2189. struct ast_data *ast_data_iterator_next(struct ast_data_iterator *iterator)
  2190. {
  2191. struct ast_data *res;
  2192. if (iterator->last) {
  2193. /* release the last retrieved node reference. */
  2194. ao2_ref(iterator->last, -1);
  2195. }
  2196. while ((res = ao2_iterator_next(&iterator->internal_iterator))) {
  2197. /* if there is no node name pattern specified, return
  2198. * the next node. */
  2199. if (!iterator->pattern) {
  2200. break;
  2201. }
  2202. /* if the pattern is a regular expression, check if this node
  2203. * matches. */
  2204. if (iterator->is_pattern && !regexec(&(iterator->regex_pattern),
  2205. res->name, 0, NULL, 0)) {
  2206. break;
  2207. }
  2208. /* if there is a pattern specified, check if this node matches
  2209. * the wanted node names. */
  2210. if (!iterator->is_pattern && (iterator->pattern &&
  2211. !strcasecmp(res->name, iterator->pattern))) {
  2212. break;
  2213. }
  2214. ao2_ref(res, -1);
  2215. }
  2216. iterator->last = res;
  2217. return res;
  2218. }
  2219. int ast_data_retrieve(struct ast_data *tree, const char *path,
  2220. struct ast_data_retrieve *content)
  2221. {
  2222. struct ast_data *node;
  2223. if (!content) {
  2224. return -1;
  2225. }
  2226. node = data_result_get_node(tree, path);
  2227. if (!node) {
  2228. ast_log(LOG_ERROR, "Invalid internal node %s\n", path);
  2229. return -1;
  2230. }
  2231. content->type = node->type;
  2232. switch (node->type) {
  2233. case AST_DATA_STRING:
  2234. content->value.AST_DATA_STRING = node->payload.str;
  2235. break;
  2236. case AST_DATA_PASSWORD:
  2237. content->value.AST_DATA_PASSWORD = node->payload.str;
  2238. break;
  2239. case AST_DATA_TIMESTAMP:
  2240. content->value.AST_DATA_TIMESTAMP = node->payload.uint;
  2241. break;
  2242. case AST_DATA_SECONDS:
  2243. content->value.AST_DATA_SECONDS = node->payload.uint;
  2244. break;
  2245. case AST_DATA_MILLISECONDS:
  2246. content->value.AST_DATA_MILLISECONDS = node->payload.uint;
  2247. break;
  2248. case AST_DATA_CHARACTER:
  2249. content->value.AST_DATA_CHARACTER = node->payload.character;
  2250. break;
  2251. case AST_DATA_INTEGER:
  2252. content->value.AST_DATA_INTEGER = node->payload.sint;
  2253. break;
  2254. case AST_DATA_UNSIGNED_INTEGER:
  2255. content->value.AST_DATA_UNSIGNED_INTEGER = node->payload.uint;
  2256. break;
  2257. case AST_DATA_BOOLEAN:
  2258. content->value.AST_DATA_BOOLEAN = node->payload.boolean;
  2259. break;
  2260. case AST_DATA_IPADDR:
  2261. content->value.AST_DATA_IPADDR = node->payload.ipaddr;
  2262. break;
  2263. case AST_DATA_DOUBLE:
  2264. content->value.AST_DATA_DOUBLE = node->payload.dbl;
  2265. break;
  2266. case AST_DATA_CONTAINER:
  2267. break;
  2268. case AST_DATA_POINTER:
  2269. content->value.AST_DATA_POINTER = node->payload.ptr;
  2270. break;
  2271. }
  2272. return 0;
  2273. }
  2274. /*!
  2275. * \internal
  2276. * \brief One color for each node type.
  2277. */
  2278. static const struct {
  2279. enum ast_data_type type;
  2280. int color;
  2281. } data_result_color[] = {
  2282. { AST_DATA_STRING, COLOR_BLUE },
  2283. { AST_DATA_PASSWORD, COLOR_BRBLUE },
  2284. { AST_DATA_TIMESTAMP, COLOR_CYAN },
  2285. { AST_DATA_SECONDS, COLOR_MAGENTA },
  2286. { AST_DATA_MILLISECONDS, COLOR_BRMAGENTA },
  2287. { AST_DATA_CHARACTER, COLOR_GRAY },
  2288. { AST_DATA_INTEGER, COLOR_RED },
  2289. { AST_DATA_UNSIGNED_INTEGER, COLOR_RED },
  2290. { AST_DATA_DOUBLE, COLOR_RED },
  2291. { AST_DATA_BOOLEAN, COLOR_BRRED },
  2292. { AST_DATA_CONTAINER, COLOR_GREEN },
  2293. { AST_DATA_IPADDR, COLOR_BROWN },
  2294. { AST_DATA_POINTER, COLOR_YELLOW },
  2295. };
  2296. /*!
  2297. * \internal
  2298. * \brief Get the color configured for a specific node type.
  2299. * \param[in] type The node type.
  2300. * \returns The color specified for the passed type.
  2301. */
  2302. static int data_result_get_color(enum ast_data_type type)
  2303. {
  2304. int i;
  2305. for (i = 0; i < ARRAY_LEN(data_result_color); i++) {
  2306. if (data_result_color[i].type == type) {
  2307. return data_result_color[i].color;
  2308. }
  2309. }
  2310. return COLOR_BLUE;
  2311. }
  2312. /*!
  2313. * \internal
  2314. * \brief Print a node to the CLI.
  2315. * \param[in] fd The CLI file descriptor.
  2316. * \param[in] node The node to print.
  2317. * \param[in] depth The actual node depth in the tree.
  2318. */
  2319. static void data_result_print_cli_node(int fd, const struct ast_data *node, uint32_t depth)
  2320. {
  2321. int i;
  2322. struct ast_str *tabs, *output;
  2323. tabs = ast_str_create(depth * 10 + 1);
  2324. if (!tabs) {
  2325. return;
  2326. }
  2327. ast_str_reset(tabs);
  2328. for (i = 0; i < depth; i++) {
  2329. ast_str_append(&tabs, 0, " ");
  2330. }
  2331. output = ast_str_create(20);
  2332. if (!output) {
  2333. ast_free(tabs);
  2334. return;
  2335. }
  2336. ast_str_reset(output);
  2337. ast_term_color_code(&output, data_result_get_color(node->type), 0);
  2338. switch (node->type) {
  2339. case AST_DATA_POINTER:
  2340. ast_str_append(&output, 0, "%s%s: %p\n", ast_str_buffer(tabs),
  2341. node->name, node->payload.ptr);
  2342. break;
  2343. case AST_DATA_PASSWORD:
  2344. ast_str_append(&output, 0, "%s%s: \"%s\"\n",
  2345. ast_str_buffer(tabs),
  2346. node->name,
  2347. node->payload.str);
  2348. break;
  2349. case AST_DATA_STRING:
  2350. ast_str_append(&output, 0, "%s%s: \"%s\"\n",
  2351. ast_str_buffer(tabs),
  2352. node->name,
  2353. node->payload.str);
  2354. break;
  2355. case AST_DATA_CHARACTER:
  2356. ast_str_append(&output, 0, "%s%s: \'%c\'\n",
  2357. ast_str_buffer(tabs),
  2358. node->name,
  2359. node->payload.character);
  2360. break;
  2361. case AST_DATA_CONTAINER:
  2362. ast_str_append(&output, 0, "%s%s\n", ast_str_buffer(tabs),
  2363. node->name);
  2364. break;
  2365. case AST_DATA_TIMESTAMP:
  2366. ast_str_append(&output, 0, "%s%s: %u\n", ast_str_buffer(tabs),
  2367. node->name,
  2368. node->payload.uint);
  2369. break;
  2370. case AST_DATA_SECONDS:
  2371. ast_str_append(&output, 0, "%s%s: %u\n", ast_str_buffer(tabs),
  2372. node->name,
  2373. node->payload.uint);
  2374. break;
  2375. case AST_DATA_MILLISECONDS:
  2376. ast_str_append(&output, 0, "%s%s: %u\n", ast_str_buffer(tabs),
  2377. node->name,
  2378. node->payload.uint);
  2379. break;
  2380. case AST_DATA_INTEGER:
  2381. ast_str_append(&output, 0, "%s%s: %d\n", ast_str_buffer(tabs),
  2382. node->name,
  2383. node->payload.sint);
  2384. break;
  2385. case AST_DATA_UNSIGNED_INTEGER:
  2386. ast_str_append(&output, 0, "%s%s: %u\n", ast_str_buffer(tabs),
  2387. node->name,
  2388. node->payload.uint);
  2389. break;
  2390. case AST_DATA_DOUBLE:
  2391. ast_str_append(&output, 0, "%s%s: %lf\n", ast_str_buffer(tabs),
  2392. node->name,
  2393. node->payload.dbl);
  2394. break;
  2395. case AST_DATA_BOOLEAN:
  2396. ast_str_append(&output, 0, "%s%s: %s\n", ast_str_buffer(tabs),
  2397. node->name,
  2398. ((node->payload.boolean) ? "True" : "False"));
  2399. break;
  2400. case AST_DATA_IPADDR:
  2401. ast_str_append(&output, 0, "%s%s: %s\n", ast_str_buffer(tabs),
  2402. node->name,
  2403. ast_inet_ntoa(node->payload.ipaddr));
  2404. break;
  2405. }
  2406. ast_free(tabs);
  2407. ast_term_color_code(&output, 0, 0);
  2408. ast_cli(fd, "%s", ast_str_buffer(output));
  2409. ast_free(output);
  2410. if (node->type == AST_DATA_CONTAINER) {
  2411. __data_result_print_cli(fd, node, depth + 1);
  2412. }
  2413. }
  2414. /*!
  2415. * \internal
  2416. * \brief Print out an ast_data tree to the CLI.
  2417. * \param[in] fd The CLI file descriptor.
  2418. * \param[in] root The root node of the tree.
  2419. * \param[in] depth Actual depth.
  2420. */
  2421. static void __data_result_print_cli(int fd, const struct ast_data *root, uint32_t depth)
  2422. {
  2423. struct ao2_iterator iter;
  2424. struct ast_data *node;
  2425. if (root->type == AST_DATA_CONTAINER) {
  2426. iter = ao2_iterator_init(root->children, 0);
  2427. while ((node = ao2_iterator_next(&iter))) {
  2428. data_result_print_cli_node(fd, node, depth + 1);
  2429. ao2_ref(node, -1);
  2430. }
  2431. ao2_iterator_destroy(&iter);
  2432. } else {
  2433. data_result_print_cli_node(fd, root, depth);
  2434. }
  2435. }
  2436. /*!
  2437. * \internal
  2438. * \brief
  2439. * \param[in] fd The CLI file descriptor.
  2440. * \param[in] root The root node of the tree.
  2441. */
  2442. static void data_result_print_cli(int fd, const struct ast_data *root)
  2443. {
  2444. ast_cli(fd, COLORIZE_FMT "\n", COLORIZE(data_result_get_color(root->type), 0, root->name));
  2445. __data_result_print_cli(fd, root, 0);
  2446. ast_cli(fd, "\n");
  2447. }
  2448. /*!
  2449. * \internal
  2450. * \brief Handle the CLI command "data get".
  2451. */
  2452. static char *handle_cli_data_get(struct ast_cli_entry *e, int cmd,
  2453. struct ast_cli_args *a)
  2454. {
  2455. struct ast_data_query query = {
  2456. .version = AST_DATA_QUERY_VERSION
  2457. };
  2458. struct ast_data *tree;
  2459. switch (cmd) {
  2460. case CLI_INIT:
  2461. e->command = "data get";
  2462. e->usage = ""
  2463. "Usage: data get <path> [<search> [<filter>]]\n"
  2464. " Get the tree based on a path.\n";
  2465. return NULL;
  2466. case CLI_GENERATE:
  2467. return NULL;
  2468. }
  2469. if (a->argc < e->args + 1) {
  2470. return CLI_SHOWUSAGE;
  2471. }
  2472. query.path = (char *) a->argv[e->args];
  2473. if (a->argc > e->args + 1) {
  2474. query.search = (char *) a->argv[e->args + 1];
  2475. }
  2476. if (a->argc > e->args + 2) {
  2477. query.filter = (char *) a->argv[e->args + 2];
  2478. }
  2479. tree = ast_data_get(&query);
  2480. if (!tree) {
  2481. return CLI_FAILURE;
  2482. }
  2483. data_result_print_cli(a->fd, tree);
  2484. ast_data_free(tree);
  2485. return CLI_SUCCESS;
  2486. }
  2487. /*!
  2488. * \internal
  2489. * \brief Print the list of data providers.
  2490. * \param[in] fd The CLI file descriptor.
  2491. * \param[in] name The last node visited name.
  2492. * \param[in] container The childrens of the last node.
  2493. * \param[in] path The path to the current node.
  2494. */
  2495. static void data_provider_print_cli(int fd, const char *name,
  2496. struct ao2_container *container, struct ast_str *path)
  2497. {
  2498. struct ao2_iterator i;
  2499. struct ast_str *current_path;
  2500. struct data_provider *provider;
  2501. current_path = ast_str_create(60);
  2502. if (!current_path) {
  2503. return;
  2504. }
  2505. ast_str_reset(current_path);
  2506. if (path) {
  2507. ast_str_set(&current_path, 0, "%s/%s", ast_str_buffer(path), name);
  2508. } else {
  2509. ast_str_set(&current_path, 0, "%s", name);
  2510. }
  2511. i = ao2_iterator_init(container, 0);
  2512. while ((provider = ao2_iterator_next(&i))) {
  2513. if (provider->handler) {
  2514. /* terminal node, print it. */
  2515. ast_cli(fd, "%s/%s (", ast_str_buffer(current_path),
  2516. provider->name);
  2517. if (provider->handler->get) {
  2518. ast_cli(fd, "get");
  2519. }
  2520. ast_cli(fd, ") [%s]\n", provider->registrar);
  2521. }
  2522. data_provider_print_cli(fd, provider->name, provider->children,
  2523. current_path);
  2524. ao2_ref(provider, -1);
  2525. }
  2526. ao2_iterator_destroy(&i);
  2527. ast_free(current_path);
  2528. }
  2529. /*!
  2530. * \internal
  2531. * \brief Handle CLI command "data show providers"
  2532. */
  2533. static char *handle_cli_data_show_providers(struct ast_cli_entry *e, int cmd,
  2534. struct ast_cli_args *a)
  2535. {
  2536. switch (cmd) {
  2537. case CLI_INIT:
  2538. e->command = "data show providers";
  2539. e->usage = ""
  2540. "Usage: data show providers\n"
  2541. " Show the list of registered providers\n";
  2542. return NULL;
  2543. case CLI_GENERATE:
  2544. return NULL;
  2545. }
  2546. data_read_lock();
  2547. data_provider_print_cli(a->fd, "", root_data.container, NULL);
  2548. data_unlock();
  2549. return CLI_SUCCESS;
  2550. }
  2551. /*!
  2552. * \internal
  2553. * \brief Data API CLI commands.
  2554. */
  2555. static struct ast_cli_entry cli_data[] = {
  2556. AST_CLI_DEFINE(handle_cli_data_get, "Data API get"),
  2557. AST_CLI_DEFINE(handle_cli_data_show_providers, "Show data providers")
  2558. };
  2559. /*!
  2560. * \internal
  2561. * \brief Output a tree to the AMI.
  2562. * \param[in] s AMI session.
  2563. * \param[in] name The root node name.
  2564. * \param[in] container The root container.
  2565. * \param[in] path The current path.
  2566. */
  2567. static void data_result_manager_output(struct mansession *s, const char *name,
  2568. struct ao2_container *container, struct ast_str *path, int id)
  2569. {
  2570. struct ao2_iterator i;
  2571. struct ast_str *current_path;
  2572. struct ast_data *node;
  2573. int current_id = id;
  2574. current_path = ast_str_create(60);
  2575. if (!current_path) {
  2576. return;
  2577. }
  2578. ast_str_reset(current_path);
  2579. if (path) {
  2580. ast_str_set(&current_path, 0, "%s.%s", ast_str_buffer(path), name);
  2581. } else {
  2582. ast_str_set(&current_path, 0, "%s", name);
  2583. }
  2584. i = ao2_iterator_init(container, 0);
  2585. while ((node = ao2_iterator_next(&i))) {
  2586. /* terminal node, print it. */
  2587. if (node->type != AST_DATA_CONTAINER) {
  2588. astman_append(s, "%d-%s.%s", id, ast_str_buffer(current_path),
  2589. node->name);
  2590. }
  2591. switch (node->type) {
  2592. case AST_DATA_CONTAINER:
  2593. data_result_manager_output(s, node->name, node->children, current_path, ++current_id);
  2594. break;
  2595. case AST_DATA_INTEGER:
  2596. astman_append(s, ": %d\r\n", node->payload.sint);
  2597. break;
  2598. case AST_DATA_TIMESTAMP:
  2599. case AST_DATA_SECONDS:
  2600. case AST_DATA_MILLISECONDS:
  2601. case AST_DATA_UNSIGNED_INTEGER:
  2602. astman_append(s, ": %u\r\n", node->payload.uint);
  2603. break;
  2604. case AST_DATA_PASSWORD:
  2605. astman_append(s, ": %s\r\n", node->payload.str);
  2606. break;
  2607. case AST_DATA_STRING:
  2608. astman_append(s, ": %s\r\n", node->payload.str);
  2609. break;
  2610. case AST_DATA_CHARACTER:
  2611. astman_append(s, ": %c\r\n", node->payload.character);
  2612. break;
  2613. case AST_DATA_IPADDR:
  2614. astman_append(s, ": %s\r\n", ast_inet_ntoa(node->payload.ipaddr));
  2615. break;
  2616. case AST_DATA_POINTER:
  2617. break;
  2618. case AST_DATA_DOUBLE:
  2619. astman_append(s, ": %f\r\n", node->payload.dbl);
  2620. break;
  2621. case AST_DATA_BOOLEAN:
  2622. astman_append(s, ": %s\r\n",
  2623. (node->payload.boolean ? "True" : "False"));
  2624. break;
  2625. }
  2626. ao2_ref(node, -1);
  2627. }
  2628. ao2_iterator_destroy(&i);
  2629. ast_free(current_path);
  2630. }
  2631. /*!
  2632. * \internal
  2633. * \brief Implements the manager action: "DataGet".
  2634. */
  2635. static int manager_data_get(struct mansession *s, const struct message *m)
  2636. {
  2637. const char *path = astman_get_header(m, "Path");
  2638. const char *search = astman_get_header(m, "Search");
  2639. const char *filter = astman_get_header(m, "Filter");
  2640. const char *id = astman_get_header(m, "ActionID");
  2641. struct ast_data *res;
  2642. struct ast_data_query query = {
  2643. .version = AST_DATA_QUERY_VERSION,
  2644. .path = (char *) path,
  2645. .search = (char *) search,
  2646. .filter = (char *) filter,
  2647. };
  2648. if (ast_strlen_zero(path)) {
  2649. astman_send_error(s, m, "'Path' parameter not specified");
  2650. return 0;
  2651. }
  2652. res = ast_data_get(&query);
  2653. if (!res) {
  2654. astman_send_error(s, m, "No data returned");
  2655. return 0;
  2656. }
  2657. astman_append(s, "Event: DataGet Tree\r\n");
  2658. if (!ast_strlen_zero(id)) {
  2659. astman_append(s, "ActionID: %s\r\n", id);
  2660. }
  2661. data_result_manager_output(s, res->name, res->children, NULL, 0);
  2662. astman_append(s, "\r\n");
  2663. ast_data_free(res);
  2664. return RESULT_SUCCESS;
  2665. }
  2666. static int data_add_codec(struct ast_data *codecs, struct ast_format *format) {
  2667. struct ast_data *codec;
  2668. struct ast_codec *tmp;
  2669. tmp = ast_codec_get_by_id(ast_format_get_codec_id(format));
  2670. if (!tmp) {
  2671. return -1;
  2672. }
  2673. codec = ast_data_add_node(codecs, "codec");
  2674. if (!codec) {
  2675. ao2_ref(tmp, -1);
  2676. return -1;
  2677. }
  2678. ast_data_add_str(codec, "name", tmp->name);
  2679. ast_data_add_int(codec, "samplespersecond", tmp->sample_rate);
  2680. ast_data_add_str(codec, "description", tmp->description);
  2681. ast_data_add_int(codec, "frame_length", tmp->minimum_bytes);
  2682. ao2_ref(tmp, -1);
  2683. return 0;
  2684. }
  2685. int ast_data_add_codec(struct ast_data *root, const char *node_name, struct ast_format *format)
  2686. {
  2687. struct ast_data *codecs;
  2688. codecs = ast_data_add_node(root, node_name);
  2689. if (!codecs) {
  2690. return -1;
  2691. }
  2692. return data_add_codec(codecs, format);
  2693. }
  2694. int ast_data_add_codecs(struct ast_data *root, const char *node_name, struct ast_format_cap *cap)
  2695. {
  2696. struct ast_data *codecs;
  2697. size_t i;
  2698. size_t count;
  2699. codecs = ast_data_add_node(root, node_name);
  2700. if (!codecs) {
  2701. return -1;
  2702. }
  2703. count = ast_format_cap_count(cap);
  2704. for (i = 0; i < count; ++i) {
  2705. struct ast_format *fmt;
  2706. fmt = ast_format_cap_get_format(cap, i);
  2707. if (!fmt) {
  2708. return -1;
  2709. }
  2710. if (data_add_codec(codecs, fmt)) {
  2711. ao2_ref(fmt, -1);
  2712. return -1;
  2713. }
  2714. ao2_ref(fmt, -1);
  2715. }
  2716. return 0;
  2717. }
  2718. #ifdef TEST_FRAMEWORK
  2719. /*!
  2720. * \internal
  2721. * \brief Structure used to test how to add a complete structure,
  2722. * and how to compare it.
  2723. */
  2724. struct test_structure {
  2725. int a_int;
  2726. unsigned int b_bool:1;
  2727. char *c_str;
  2728. unsigned int a_uint;
  2729. };
  2730. /*!
  2731. * \internal
  2732. * \brief test_structure mapping.
  2733. */
  2734. #define DATA_EXPORT_TEST_STRUCTURE(MEMBER) \
  2735. MEMBER(test_structure, a_int, AST_DATA_INTEGER) \
  2736. MEMBER(test_structure, b_bool, AST_DATA_BOOLEAN) \
  2737. MEMBER(test_structure, c_str, AST_DATA_STRING) \
  2738. MEMBER(test_structure, a_uint, AST_DATA_UNSIGNED_INTEGER)
  2739. AST_DATA_STRUCTURE(test_structure, DATA_EXPORT_TEST_STRUCTURE);
  2740. /*!
  2741. * \internal
  2742. * \brief Callback implementation.
  2743. */
  2744. static int test_data_full_provider(const struct ast_data_search *search,
  2745. struct ast_data *root)
  2746. {
  2747. struct ast_data *test_structure;
  2748. struct test_structure local_test_structure = {
  2749. .a_int = 10,
  2750. .b_bool = 1,
  2751. .c_str = "test string",
  2752. .a_uint = 20
  2753. };
  2754. test_structure = ast_data_add_node(root, "test_structure");
  2755. if (!test_structure) {
  2756. ast_debug(1, "Internal data api error\n");
  2757. return 0;
  2758. }
  2759. /* add the complete structure. */
  2760. ast_data_add_structure(test_structure, test_structure, &local_test_structure);
  2761. if (!ast_data_search_match(search, test_structure)) {
  2762. ast_data_remove_node(root, test_structure);
  2763. }
  2764. return 0;
  2765. }
  2766. /*!
  2767. * \internal
  2768. * \brief Handler definition for the full provider.
  2769. */
  2770. static const struct ast_data_handler full_provider = {
  2771. .version = AST_DATA_HANDLER_VERSION,
  2772. .get = test_data_full_provider
  2773. };
  2774. /*!
  2775. * \internal
  2776. * \brief Structure used to define multiple providers at once.
  2777. */
  2778. static const struct ast_data_entry test_providers[] = {
  2779. AST_DATA_ENTRY("test/node1/node11/node111", &full_provider)
  2780. };
  2781. AST_TEST_DEFINE(test_data_get)
  2782. {
  2783. struct ast_data *res, *node;
  2784. struct ast_data_iterator *i;
  2785. struct ast_data_query query = {
  2786. .version = AST_DATA_QUERY_VERSION,
  2787. .path = "test/node1/node11/node111",
  2788. .search = "node111/test_structure/a_int=10",
  2789. .filter = "node111/test_structure/a*int"
  2790. };
  2791. switch (cmd) {
  2792. case TEST_INIT:
  2793. info->name = "data_test";
  2794. info->category = "/main/data/";
  2795. info->summary = "Data API unit test";
  2796. info->description =
  2797. "Tests whether data API get implementation works as expected.";
  2798. return AST_TEST_NOT_RUN;
  2799. case TEST_EXECUTE:
  2800. break;
  2801. }
  2802. ast_data_register_multiple_core(test_providers, ARRAY_LEN(test_providers));
  2803. res = ast_data_get(&query);
  2804. if (!res) {
  2805. ast_test_status_update(test, "Unable to get tree.");
  2806. ast_data_unregister("test/node1/node11/node111");
  2807. return AST_TEST_FAIL;
  2808. }
  2809. /* initiate the iterator and check for errors. */
  2810. i = ast_data_iterator_init(res, "test_structure/");
  2811. if (!i) {
  2812. ast_test_status_update(test, "Unable to initiate the iterator.");
  2813. ast_data_free(res);
  2814. ast_data_unregister("test/node1/node11/node111");
  2815. return AST_TEST_FAIL;
  2816. }
  2817. /* walk the returned nodes. */
  2818. while ((node = ast_data_iterator_next(i))) {
  2819. if (!strcmp(ast_data_retrieve_name(node), "a_int")) {
  2820. if (ast_data_retrieve_int(node, "/") != 10) {
  2821. ast_data_iterator_end(i);
  2822. ast_data_free(res);
  2823. ast_data_unregister("test/node1/node11/node111");
  2824. return AST_TEST_FAIL;
  2825. }
  2826. } else if (!strcmp(ast_data_retrieve_name(node), "a_uint")) {
  2827. if (ast_data_retrieve_uint(node, "/") != 20) {
  2828. ast_data_iterator_end(i);
  2829. ast_data_free(res);
  2830. ast_data_unregister("test/node1/node11/node111");
  2831. return AST_TEST_FAIL;
  2832. }
  2833. }
  2834. }
  2835. /* finish the iterator. */
  2836. ast_data_iterator_end(i);
  2837. ast_data_free(res);
  2838. ast_data_unregister("test/node1/node11/node111");
  2839. return AST_TEST_PASS;
  2840. }
  2841. #endif
  2842. /*!
  2843. * \internal
  2844. * \brief Clean up resources on Asterisk shutdown
  2845. */
  2846. static void data_shutdown(void)
  2847. {
  2848. ast_manager_unregister("DataGet");
  2849. ast_cli_unregister_multiple(cli_data, ARRAY_LEN(cli_data));
  2850. ao2_t_ref(root_data.container, -1, "Unref root_data.container in data_shutdown");
  2851. root_data.container = NULL;
  2852. ast_rwlock_destroy(&root_data.lock);
  2853. AST_TEST_UNREGISTER(test_data_get);
  2854. }
  2855. int ast_data_init(void)
  2856. {
  2857. int res = 0;
  2858. ast_rwlock_init(&root_data.lock);
  2859. if (!(root_data.container = ao2_container_alloc(NUM_DATA_NODE_BUCKETS,
  2860. data_provider_hash, data_provider_cmp))) {
  2861. return -1;
  2862. }
  2863. res |= ast_cli_register_multiple(cli_data, ARRAY_LEN(cli_data));
  2864. res |= ast_manager_register_xml_core("DataGet", 0, manager_data_get);
  2865. AST_TEST_REGISTER(test_data_get);
  2866. ast_register_cleanup(data_shutdown);
  2867. return res;
  2868. }