introspect_internal.c

Go to the documentation of this file.
00001 /*
00002  EasyDbus Library: DBUS Binding Library
00003  Copyright (C) 2007  Daniele Rondina aka Ge@@ru, geaaru@gmail.com 
00004 
00005  This program is free software; you can redistribute it and/or
00006  modify it under the terms of the GNU General Public License
00007  as published by the Free Software Foundation; either version 2
00008  of the License, or (at your option) any later version.
00009 
00010  This program is distributed in the hope that it will be useful,
00011  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  GNU General Public License for more details.
00014 
00015  You should have received a copy of the GNU General Public License
00016  along with this program; if not, write to the Free Software
00017  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 
00019  Filename:  introspect.c
00020  
00021  Description: Functions for insert informations about 
00022         methods/signals managed on a register object. 
00023  
00024  Version:  1.0
00025  Created:  09/12/07 12:36:15 CEST
00026  Revision:  
00027         0 - created
00028         1 - created functions for creation of instropect XML
00029                  string.
00030    2 - created doxygen documentation and added support for
00031        opaque struct (Ge@@ru) - 11/03/07 
00032  
00033  Author:   Daniele Rondina aka ge@@ru (geaaru@gmail.com) 
00034  License:  GPL 2.0
00035 */
00036 
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <stdarg.h>
00047 // easydbus includes
00048 #include "easydbus-core.h"
00049 #include "debug.h"
00050 #include "introspect_internal.h"
00051 #include "reply_internal.h"
00052 #include "utils.h"
00053 
00054 // ---  Introspect Object Tree functions ---
00055 
00066 introspect_objs_tree *
00067 easydbus_introspect_obj_tree_create (char *leaf_name, 
00068                                      struct EasyDbus_object_box *obj)
00069 {
00070    introspect_objs_tree *o = NULL;
00071    int n;
00072 
00073    if (!leaf_name) return NULL;
00074 
00075    o = (introspect_objs_tree *) 
00076        malloc (sizeof (introspect_objs_tree));
00077    if (!o) goto error;
00078 
00079    memset (o, 0, sizeof (introspect_objs_tree));
00080    n = strlen (leaf_name) + 1;
00081    o->leaf_name = (char *) malloc (n);
00082    EASYDBUS_MEMCOPY (o->leaf_name, leaf_name, n);
00083    o->n_leafs = 0;
00084    o->obj = obj;
00085    o->leafs = NULL;
00086 
00087    return o;
00088 
00089 error:
00090    if (o) {
00091       if (o->leaf_name)
00092          free (o->leaf_name);
00093       free (o);
00094    }
00095    return NULL;
00096 }
00097 
00103 void 
00104 easydbus_introspect_obj_tree_free (introspect_objs_tree *o)
00105 {
00106    if (!o) return;
00107 
00108    if (o->leaf_name)
00109       free (o->leaf_name);
00110 
00111    if (o->leafs)
00112       free (o->leafs);
00113 
00114    o->leaf_name = NULL;
00115    o->obj = NULL;
00116    o->leafs = NULL;
00117 
00118    free (o);
00119 }
00120 
00127 introspect_objs_tree *
00128 easydbus_introspect_objs_tree_build (struct EasyDbus_object_box *object)
00129 {
00130    introspect_objs_tree *tree = NULL;
00131    struct EasyDbus_object_box *obj = NULL;
00132    int i, length, n_token = 0;
00133    char *tmp , *token, *saveptr;
00134    char **l_tokens;
00135 
00136    if (!object) 
00137       return NULL;
00138    
00139    tmp = token = saveptr = NULL;
00140    l_tokens = NULL;
00141 
00142    for (obj = object; obj; obj = obj->next) {
00143       length = strlen (obj->core.path);
00144       n_token = 
00145          easydbus_introspect_get_ntoken (obj->core.path, 
00146                                          length);
00147       EasyDbusDebug ("Service %s has %d token", obj->core.path,
00148                      n_token);
00149       if (n_token <= 0) goto error;
00150 
00151       l_tokens = (char **) malloc (sizeof (char *[n_token]));
00152       if (!l_tokens) goto error;
00153 
00154       tmp = (char *) malloc (++length);
00155       if (!tmp) goto error;
00156 
00157       EASYDBUS_MEMCOPY (tmp, obj->core.path, length);
00158       // post: i with number of token;
00159       for (i = 0, token = strtok_r (tmp, "/", &saveptr); token;
00160           token = strtok_r (saveptr, "/", &saveptr), i++)
00161          l_tokens[i] = token;
00162       if (easydbus_introspect_objs_tree_add_leafs (&tree, l_tokens, 
00163                                                    n_token, obj))
00164          goto error;
00165       free (l_tokens);
00166       free (tmp);
00167       l_tokens = NULL;
00168       tmp = NULL;
00169    }
00170 
00171    return tree;
00172 error:
00173    if (tmp) free (tmp);
00174    if (l_tokens) free (l_tokens);
00175    if (tree) 
00176       easydbus_introspect_objs_tree_destroy (tree);
00177    EasyDbusDebug ("Error on create introspect tree");
00178    return NULL;
00179 }
00180 
00194 int
00195 easydbus_introspect_objs_tree_add_leafs (introspect_objs_tree **tt,
00196                                          char **l_tokens, unsigned int n,
00197                                          struct EasyDbus_object_box *obj)
00198 {
00199    unsigned int i, j, hastoken = 0;
00200    introspect_objs_tree *t, *leaf, *next;
00201    introspect_objs_tree **temp_tt, **temp2_tt;
00202 
00203    if (!l_tokens) return -1;
00204 
00205    leaf = next = t = NULL;
00206    temp_tt = temp2_tt = NULL;
00207 
00208    // if tt is null create main node.
00209    if (!*tt) {
00210       *tt = easydbus_introspect_obj_tree_create ("/", NULL);
00211       if (!*tt) return -1;
00212    }
00213    t = *tt;
00214    for (i = 0; i < n; i++, t = next) {
00215       // if there are child leafs check if token is already on tree
00216       if (t->n_leafs) {
00217          leaf = easydbus_introspect_obj_tree_hastoken (t, l_tokens[i]);
00218          if (leaf) hastoken = 1;
00219       }
00220       if (!leaf) {
00221          // if token isn't already on tree
00222          if (i < (n-1))
00223             leaf = easydbus_introspect_obj_tree_create (l_tokens[i], NULL);
00224          else
00225             leaf = easydbus_introspect_obj_tree_create (l_tokens[i], obj);
00226          if (!leaf) return -1;
00227       }
00228       if (t->n_leafs && !hastoken) {
00229          temp_tt = (introspect_objs_tree **) 
00230                    malloc (sizeof (introspect_objs_tree [t->n_leafs+1]));
00231          if (!temp_tt) goto error;
00232          for (j = 0; j < t->n_leafs; j++)
00233             temp_tt[j] = t->leafs[j];
00234          temp_tt[t->n_leafs++] = leaf;
00235          temp2_tt = t->leafs;
00236          t->leafs = temp_tt;
00237          free (temp2_tt);
00238       } else if (!hastoken) {
00239          t->n_leafs = 1;
00240          t->leafs = (introspect_objs_tree **) 
00241                     malloc (sizeof (introspect_objs_tree [t->n_leafs]));
00242          if (!t->leafs) goto error;
00243          t->leafs[0] = leaf;
00244       }
00245       next = leaf;
00246       leaf = NULL;
00247       hastoken = 0;
00248    }
00249    return 0;
00250 error:
00251    if (leaf) 
00252       easydbus_introspect_obj_tree_free (leaf);
00253    return -1;
00254 }
00255 
00263 int 
00264 easydbus_introspect_objs_tree_destroy (introspect_objs_tree *tree) 
00265 {
00266    unsigned int i;
00267 
00268    if (!tree) return -1;
00269 
00270    for (i = 0; i < tree->n_leafs; i++) 
00271       easydbus_introspect_objs_tree_destroy (tree->leafs[i]);
00272 
00273    easydbus_introspect_obj_tree_free (tree);
00274    return 0;
00275 }
00276 
00285 inline introspect_objs_tree *         
00286 easydbus_introspect_obj_tree_hastoken (introspect_objs_tree *tree,
00287                                        char *token)
00288 {
00289    unsigned int i;
00290 
00291    if (tree && token)
00292       for (i = 0; i < tree->n_leafs; i++)
00293          if (!strcmp (tree->leafs[i]->leaf_name, token))
00294             return tree->leafs[i];
00295 
00296    return NULL;
00297 }
00298 
00299 // --- Functions for manage struct easydbus_introspect_arg_info ---
00300 
00306 void inline
00307 easydbus_free_introspect_info_arg (struct easydbus_introspect_arg_info *arg)
00308 {
00309    if (!arg)
00310       return;
00311 
00312    if (arg->name)
00313       free (arg->name);
00314 
00315    if (arg->signature)
00316       free (arg->signature);
00317 
00318    free (arg);
00319 }
00320 
00330 int
00331 easydbus_add_new_field_to_list (struct easydbus_introspect_arg_info *el, 
00332                                 struct easydbus_introspect_arg_info **list)
00333 {
00334    struct easydbus_introspect_arg_info *prev, *current;
00335 
00336    if (el == NULL || list == NULL)
00337       return -1;
00338 
00339    if (*list == NULL) {
00340       // no element on list
00341       *list = el;
00342       return 0;
00343    }
00344 
00345    prev = NULL;
00346    current = *list;
00347    while (current != NULL) {
00348       if (el->offset < current->offset) {
00349          el->next = current;
00350          if (prev != NULL)
00351             prev->next = el;
00352          else
00353             *list = el;
00354          return 0;
00355       }
00356       prev = current;
00357       current = current->next;
00358    }
00359 
00360    prev->next = el;
00361    return 0;
00362 }
00363 
00374 inline int
00375 easydbus_introspect_get_ntoken (char *name, int l) 
00376 {
00377    int i, n;
00378  
00379    for (i = 0, n = 0; name[i] != '\0'; i++) 
00380       if ((i != (l-1)) && name[i] == '/') 
00381          n++;
00382    return n;
00383 }
00384 
00396 int
00397 easydbus_introspect_set_object_buffer (struct EasyDbus_object_box * obj,
00398                                        char *istring, int *offset) 
00399 {
00400    EasyDbus_obj_interface *interface = NULL;
00401    int i_string_l = 0;
00402 
00403    // add interfaces info
00404    for (interface = obj->core.handled_interfaces;
00405         interface; interface = interface->next) 
00406       if (easydbus_introspect_set_interface_buffer (interface, 
00407                                                     istring, offset))
00408          return -1;
00409    i_string_l = *offset;
00410    
00411    // add introspectable interface info
00412    EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00413                                 EASYDBUS_INTROSPECT_XML_INTERFACE_DATA,
00414                                 strlen (EASYDBUS_INTROSPECT_XML_INTERFACE_DATA));
00415 
00416    *offset = i_string_l;
00417 
00418    return 0;
00419 }
00420 
00434 int 
00435 easydbus_introspect_set_reply_buffer (char *istring,
00436                                       char *req_path,
00437                                       introspect_objs_tree *t,
00438                                       struct EasyDbus_object_box * obj,
00439                                       unsigned int obj_path)
00440 {
00441    int offset = 0, ntoken = 0;
00442    unsigned int i;
00443    char *token = NULL, *saveptr, *tmp_path;
00444    introspect_objs_tree *i_t;
00445 
00446    EasyDbusDebug ("Insert data on buffer (%p) for request %s (%d)",
00447                    istring, req_path, obj_path);
00448    /* create informations about object */
00449    // insert dtd info
00450    EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,
00451                                 EASYDBUS_INTROSPECT_MSG, 
00452                                 strlen (EASYDBUS_INTROSPECT_MSG));
00453    
00454    // add easydbus comment 
00455    EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,
00456                                 EASYDBUS_INTROSPECT_MSG_COMMENT, 
00457                                 strlen (EASYDBUS_INTROSPECT_MSG_COMMENT));
00458 
00459    // Manage request with path equal to "/"
00460    if (!strcmp ("/", req_path)) {
00461       // insert node tag
00462       EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,
00463                                    EASYDBUS_INTROSPECT_NODE_TAG_O, 
00464                                    EASYDBUS_INTROSPECT_NODE_TAG_O_L);
00465 
00466       // add leaf node info
00467       for (i = 0; i < t->n_leafs; i++) {
00468          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset, 
00469                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT, 
00470                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_L);
00471          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,
00472                                       t->leafs[i]->leaf_name, 
00473                                       strlen(t->leafs[i]->leaf_name));
00474          // close node tag
00475          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,
00476                                       EASYDBUS_INTROSPECT_TAG_END, 
00477                                       EASYDBUS_INTROSPECT_TAG_END_L);
00478       }
00479 
00480    } else {
00481       if (obj_path) {
00482          // insert node tag
00483          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,  
00484                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT2, 
00485                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT2_L);
00486          // insert object path string
00487          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,  
00488                                       req_path, strlen (req_path));
00489          // close node tag
00490          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,  
00491                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_C,
00492                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_C_L);
00493       } else {
00494          // insert node tag
00495          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,  
00496                                       EASYDBUS_INTROSPECT_NODE_TAG_O, 
00497                                       EASYDBUS_INTROSPECT_NODE_TAG_O_L);
00498       }
00499 
00500       ntoken = easydbus_introspect_get_ntoken (req_path, 
00501                                                strlen (req_path));
00502       tmp_path = (char *) malloc (strlen (req_path) + 1);
00503       if (!tmp_path) return -1;
00504       EASYDBUS_MEMCOPY (tmp_path, req_path, strlen (req_path) + 1);
00505 
00506       // move to last leaf of tree
00507       for (i = 0, token = strtok_r (tmp_path, "/", &saveptr),
00508            i_t = t; (int) i < ntoken; i++, 
00509            token = strtok_r (saveptr, "/", &saveptr)) {
00510          EasyDbusDebug ("token[%d] = %s, leafs = %d", 
00511                         i, token, i_t->n_leafs);
00512          i_t = easydbus_introspect_obj_tree_hastoken (i_t, token);
00513       }
00514       free (tmp_path);
00515 
00516       // add object introspect info
00517       if (obj_path) 
00518          if (easydbus_introspect_set_object_buffer (i_t->obj, istring,
00519                                                     &offset))
00520             return -1; 
00521 
00522       // add subnodes
00523       for (i = 0; i < i_t->n_leafs; i++) {
00524          EasyDbusDebug ("insert leaf[%d] %s",i, 
00525                         i_t->leafs[i]->leaf_name);
00526          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,
00527                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT,
00528                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_L);
00529          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,
00530                                       i_t->leafs[i]->leaf_name,
00531                                       strlen (i_t->leafs[i]->leaf_name));
00532          EASYDBUS_INTROSPECT_MEMCOPY (istring, offset,
00533                                       EASYDBUS_INTROSPECT_TAG_END,
00534                                       EASYDBUS_INTROSPECT_TAG_END_L);
00535       }
00536 
00537    }
00538    // close node tag
00539    EASYDBUS_INTROSPECT_MEMCOPY (istring, offset, 
00540                                 EASYDBUS_INTROSPECT_NODE_TAG_C, 
00541                                 EASYDBUS_INTROSPECT_NODE_TAG_C_L);
00542    
00543    // insert close buffer
00544    memset (&istring[offset++], 0, 1);
00545    EasyDbusDebug ("Created introspect string (offset %d) %s\n", 
00546                   offset, istring);
00547    return 0;
00548 }
00549 
00563 int
00564 easydbus_introspect_set_interface_buffer (EasyDbus_obj_interface *interface,
00565                                           char *istring, int *offset)
00566 {
00567    EasyDbus_obj_method *method = NULL;
00568    EasyDbus_obj_signal *signal = NULL;
00569    struct easydbus_introspect_arg_info *el = NULL;
00570    int i_string_l = *offset;
00571    
00572    if (!istring || !offset || !interface)
00573       return -1;
00574 
00575    // add <interface name="...">
00576    EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00577                                 EASYDBUS_INTROSPECT_INTERFACE_TAG_O,
00578                                 EASYDBUS_INTROSPECT_INTERFACE_TAG_O_L);
00579    EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00580                                 interface->name, strlen (interface->name));
00581    EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00582                                 EASYDBUS_INTROSPECT_NODE_TAG_INIT_C,
00583                                 EASYDBUS_INTROSPECT_NODE_TAG_INIT_C_L);
00584 
00585    for (method = interface->handled_methods; method;
00586         method = method->next) 
00587       // only method with info about arguments are inserted
00588       if (method->input_info || method->output_info) {
00589          // add method tag <method name="...">
00590          EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00591                                       EASYDBUS_INTROSPECT_METHOD_TAG_O,
00592                                       EASYDBUS_INTROSPECT_METHOD_TAG_O_L);
00593          EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00594                                       method->name, strlen (method->name));
00595          EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00596                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_C,
00597                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_C_L);
00598 
00599          // add input arg <arg name="..." type="signature" destination="in"/>
00600          for (el = method->input_info; el; el = el->next) {
00601             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00602                                          EASYDBUS_INTROSPECT_ARG_NAME_TAG_O,
00603                                          EASYDBUS_INTROSPECT_ARG_NAME_TAG_O_L);
00604             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00605                                          el->name, strlen (el->name));
00606             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00607                                          EASYDBUS_INTROSPECT_ARG_SPACE,
00608                                          EASYDBUS_INTROSPECT_ARG_SPACE_L);
00609             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00610                                          EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O,
00611                                          EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O_L);
00612             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00613                                          el->signature, strlen (el->signature));
00614             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00615                                          EASYDBUS_INTROSPECT_ARG_SPACE,
00616                                          EASYDBUS_INTROSPECT_ARG_SPACE_L);
00617             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00618                                          EASYDBUS_INTROSPECT_ARG_DIRECTION_O,
00619                                          EASYDBUS_INTROSPECT_ARG_DIRECTION_O_L);
00620             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00621                                          EASYDBUS_INTROSPECT_DIRECTION_IN,
00622                                          EASYDBUS_INTROSPECT_DIRECTION_IN_L);
00623             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00624                                          EASYDBUS_INTROSPECT_TAG_END,
00625                                          EASYDBUS_INTROSPECT_TAG_END_L);
00626          }
00627 
00628          // add output arg <arg name="..." type="signature" destination="out"/>
00629          for (el = method->output_info; el; el = el->next) {
00630             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00631                                          EASYDBUS_INTROSPECT_ARG_NAME_TAG_O,
00632                                          EASYDBUS_INTROSPECT_ARG_NAME_TAG_O_L);
00633             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00634                                          el->name, strlen (el->name));
00635             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00636                                          EASYDBUS_INTROSPECT_ARG_SPACE,
00637                                          EASYDBUS_INTROSPECT_ARG_SPACE_L);
00638             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00639                                          EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O,
00640                                          EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O_L);
00641             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00642                                          el->signature, strlen (el->signature));
00643             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00644                                          EASYDBUS_INTROSPECT_ARG_SPACE,
00645                                          EASYDBUS_INTROSPECT_ARG_SPACE_L);
00646             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00647                                          EASYDBUS_INTROSPECT_ARG_DIRECTION_O,
00648                                          EASYDBUS_INTROSPECT_ARG_DIRECTION_O_L);
00649             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00650                                          EASYDBUS_INTROSPECT_DIRECTION_OUT,
00651                                          EASYDBUS_INTROSPECT_DIRECTION_OUT_L);
00652             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00653                                          EASYDBUS_INTROSPECT_TAG_END,
00654                                          EASYDBUS_INTROSPECT_TAG_END_L);
00655          }
00656          // close method </method>
00657          EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00658                                       EASYDBUS_INTROSPECT_METHOD_TAG_C,
00659                                       EASYDBUS_INTROSPECT_METHOD_TAG_C_L);
00660       }
00661 
00662    for (signal = interface->handled_signals; signal;
00663         signal = signal->next) 
00664       // only signal with info about arguments are inserted
00665       if (signal->output_info) {
00666          // add signal tag <signal name="...">
00667          EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00668                                       EASYDBUS_INTROSPECT_SIGNAL_TAG_O,
00669                                       EASYDBUS_INTROSPECT_SIGNAL_TAG_O_L);
00670          EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00671                                       signal->name, strlen (signal->name));
00672          EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00673                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_C,
00674                                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_C_L);
00675 
00676          // add output arg <arg name="..." type="signature" />
00677          for (el = signal->output_info; el; el = el->next) {
00678             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00679                                          EASYDBUS_INTROSPECT_ARG_NAME_TAG_O,
00680                                          EASYDBUS_INTROSPECT_ARG_NAME_TAG_O_L);
00681             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00682                                          el->name, strlen (el->name));
00683             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00684                                          EASYDBUS_INTROSPECT_ARG_SPACE,
00685                                          EASYDBUS_INTROSPECT_ARG_SPACE_L);
00686             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00687                                          EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O,
00688                                          EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O_L);
00689             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00690                                          el->signature, strlen (el->signature));
00691             EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00692                                          EASYDBUS_INTROSPECT_TAG_END,
00693                                          EASYDBUS_INTROSPECT_TAG_END_L);
00694          }
00695 
00696          // close signal </signal>
00697          EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00698                                       EASYDBUS_INTROSPECT_SIGNAL_TAG_C,
00699                                       EASYDBUS_INTROSPECT_SIGNAL_TAG_C_L);
00700       }
00701 
00702    // </interface>
00703    EASYDBUS_INTROSPECT_MEMCOPY (istring, i_string_l,
00704                                 EASYDBUS_INTROSPECT_INTERFACE_TAG_C,
00705                                 EASYDBUS_INTROSPECT_INTERFACE_TAG_C_L);
00706 
00707    *offset = i_string_l;
00708    return 0;
00709 }
00710 
00722 char *
00723 easydbus_introspect_create_reply_string (char *req_path,
00724                                          introspect_objs_tree *t,
00725                                          struct EasyDbus_object_box *obj)
00726 {
00727    int istring_length = 0;
00728    unsigned int obj_dest_path = 0;
00729    char *buffer = NULL;
00730 
00731    if (!req_path || !t || !obj)
00732       return NULL;
00733 
00734    istring_length = easydbus_introspect_get_reply_length (req_path,
00735                                                           t, obj, 
00736                                                           &obj_dest_path);
00737    if (istring_length <= 0) 
00738       return NULL;
00739    EasyDbusDebug ("Introspect reply string length = %d\n", istring_length);
00740 
00741    buffer = (char *) malloc (istring_length);
00742    if (!buffer) return NULL;
00743    memset (buffer, 0, istring_length);
00744 
00745    if (easydbus_introspect_set_reply_buffer (buffer, req_path, t, 
00746                                              obj, obj_dest_path))
00747       goto error;
00748 
00749    return buffer;
00750 error:
00751    if (buffer)
00752       free (buffer);
00753    return NULL;
00754 }
00755 
00764 inline char *
00765 easydbus_create_arg_signature 
00766   (struct easydbus_signature_elem_stack *list)
00767 {
00768    char *signature = NULL;
00769    struct easydbus_signature_elem_stack *tmp_elem = NULL;
00770 
00771    while (list != NULL) {
00772       if (easydbus_manage_list_signature (list,
00773                                           &signature,
00774                                           EASYDBUS_SIGNATURE_NORMAL))
00775          goto error;
00776       tmp_elem = list->next;
00777       easydbus_free_elem_from_stack (list);
00778       list = tmp_elem;
00779    }
00780 
00781    EasyDbusDebug ("signature created for arg = %s", signature);
00782    return signature;
00783  error:
00784    if (signature != NULL)
00785       free (signature);
00786    return NULL;
00787 }
00788 
00798 DBusHandlerResult
00799 easydbus_introspect_filter_func (DBusConnection * conn, 
00800                                  DBusMessage * msg, 
00801                                  void *user_data) 
00802 {
00803    struct EasyDbus_core *core = (struct EasyDbus_core *) user_data;
00804    struct EasyDbus_object_box *objects = NULL;
00805    const char *msg_member = NULL;
00806    const char *msg_interface = NULL;
00807    const char *msg_path = NULL;
00808    const char *msg_sender = NULL;
00809    introspect_objs_tree *tree = NULL;
00810    char *introspect_string = NULL;
00811    struct EasyDbus_reply *reply = NULL;
00812 
00813    if (conn == NULL || msg == NULL || user_data == NULL) {
00814       EasyDbusDebug ("Error");
00815       return DBUS_HANDLER_RESULT_HANDLED;
00816    }
00817 
00818    objects = core->objects;
00819    EasyDbusDebug ("Message under filter analysis");
00820 
00821    // check if message is for Introspect method and Introspectable
00822    // interface.
00823    if (!dbus_message_is_method_call (msg,
00824                                      EASYDBUS_INTROSPECT_INTERFACE,
00825                                      EASYDBUS_INTROSPECT_METHOD)) 
00826       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00827 
00828    // introspect message handled.
00829    // get member
00830    msg_member = dbus_message_get_member (msg);
00831    // get interface
00832    msg_interface = dbus_message_get_interface (msg);
00833    // get path
00834    msg_path = dbus_message_get_path (msg);
00835    // get sender
00836    msg_sender = dbus_message_get_sender (msg);
00837 
00838    EasyDbusDebug ("Introspect Request:\n"
00839                   "Message %s with \n"
00840                   "path = %s\n"
00841                   "interface = %s\n"
00842                   "member = %s\n",
00843                   dbus_message_type_to_string (dbus_message_get_type (msg)),
00844                   msg_path, msg_interface, msg_member);
00845 
00846    // create introspect_objs_tree and check on tree
00847    tree = easydbus_introspect_objs_tree_build (objects);
00848    if (!tree) 
00849       goto error;
00850 
00851    reply = easydbus_reply_create_skeleton ();
00852    if (reply == NULL)
00853       goto error;
00854    
00855    introspect_string = 
00856       easydbus_introspect_create_reply_string ((char *) msg_path,
00857                                                tree, objects);
00858    // \todo manage error reply
00859    if (!introspect_string) {
00860       EasyDbusDebug ("instrospect string null");
00861       goto error;
00862    }
00863 
00864    reply->type = EASYDBUS_ET_REPLY;
00865    easydbus_add_string_param_to_skeleton (EASYDBUS_ET_REPLY,
00866                                           reply, introspect_string);
00867 
00868    easydbus_reply_send (core, msg, reply);
00869    easydbus_reply_free_skeleton (reply);
00870    free (introspect_string);
00871    easydbus_introspect_objs_tree_destroy (tree);
00872    return DBUS_HANDLER_RESULT_HANDLED;
00873 
00874  error:
00875    if (tree) easydbus_introspect_objs_tree_destroy (tree);
00876    if (introspect_string) free (introspect_string);
00877 
00878    if (reply) easydbus_reply_free_skeleton (reply);
00879    // if reply is null then there are problem on allocate memory
00880    else
00881       return DBUS_HANDLER_RESULT_NEED_MEMORY;
00882 
00883    if (easydbus_reply_send_error (core, msg, 
00884                                   "Object Not Found", 
00885                                   "Object request not founded"))
00886       return DBUS_HANDLER_RESULT_NEED_MEMORY;
00887 
00888    return DBUS_HANDLER_RESULT_HANDLED;
00889 }
00890 
00903 int
00904 easydbus_introspect_get_reply_length (char *path,
00905                                       introspect_objs_tree *t,
00906                                       struct EasyDbus_object_box *obj,
00907                                       unsigned int *obj_dest_path)
00908 {
00909    int istring_l = 0, ntoken = 0;
00910    char *tmp_path = NULL;
00911    char *token = NULL, *saveptr;
00912    unsigned int i, j;
00913    introspect_objs_tree *i_t;
00914 
00915    if (!path || !t || !obj)
00916       return -1;
00917 
00918    // +1 for \0 field
00919    istring_l = strlen (EASYDBUS_INTROSPECT_MSG) +
00920                strlen (EASYDBUS_INTROSPECT_MSG_COMMENT) + 1;
00921 
00922    if (!strcmp ("/", path)) {
00923       istring_l += EASYDBUS_INTROSPECT_NODE_TAG_O_L;
00924       for (i = 0; i < t->n_leafs; i++)
00925          // add sub nodes
00926          istring_l += EASYDBUS_INTROSPECT_NODE_TAG_INIT_L +
00927                       strlen(t->leafs[i]->leaf_name) + 
00928                       EASYDBUS_INTROSPECT_TAG_END_L;
00929    } else {
00930       // get number of token on path
00931       ntoken = easydbus_introspect_get_ntoken (path, 
00932                                                strlen (path));
00933       // create temporary string for strtok_r function
00934       tmp_path = (char *) malloc (strlen (path)+1);
00935       if (!tmp_path) 
00936          return -1;
00937       EASYDBUS_MEMCOPY (tmp_path, path, strlen (path) + 1);
00938       // POST: i_t point to last leaf.
00939       for (i = 0, token = strtok_r(tmp_path, "/", &saveptr),
00940            i_t = t; (int) i < ntoken; 
00941            token = strtok_r (saveptr, "/", &saveptr), i++) {
00942          i_t = easydbus_introspect_obj_tree_hastoken (i_t, token);
00943          if (!i_t)
00944             goto error;
00945       }
00946       if (i_t->obj) {
00947          *obj_dest_path = 1;
00948          // manage obj dest path and so interface, etc.
00949          istring_l += easydbus_introspect_get_obj_string_length (i_t->obj) +
00950                       EASYDBUS_INTROSPECT_NODE_TAG_INIT2_L +
00951                       strlen (path) + 
00952                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_C_L;
00953       } else 
00954          istring_l += EASYDBUS_INTROSPECT_NODE_TAG_O_L;
00955       // add sub objects
00956       for (j = 0; j < i_t->n_leafs; j++)
00957          istring_l += strlen (i_t->leafs[j]->leaf_name) +
00958                       EASYDBUS_INTROSPECT_NODE_TAG_INIT_L +
00959                       EASYDBUS_INTROSPECT_TAG_END_L;
00960       free (tmp_path);
00961    }
00962 
00963    istring_l += EASYDBUS_INTROSPECT_NODE_TAG_C_L;
00964    return istring_l;
00965 
00966 error:
00967    if (tmp_path)
00968       free (tmp_path);
00969    return -1;
00970 }
00971 
00980 int
00981 easydbus_introspect_get_obj_string_length (struct EasyDbus_object_box *obj) 
00982 {
00983    int i_string_l = 0, i;
00984    EasyDbus_obj_interface *interface = NULL;
00985 
00986    // get introspect string length for any interface
00987    for (i = 0, interface = obj->core.handled_interfaces; 
00988         i < obj->core.n_interfaces && interface;
00989         i++, interface = interface->next) 
00990       i_string_l += 
00991          easydbus_introspect_get_interface_string_length (interface);
00992 
00993    // add introspectable interface.
00994    i_string_l += strlen(EASYDBUS_INTROSPECT_XML_INTERFACE_DATA); 
00995 
00996    return i_string_l;
00997 }
00998 
01007 int
01008 easydbus_introspect_get_interface_string_length (EasyDbus_obj_interface *interface)
01009 {
01010    EasyDbus_obj_method *method = NULL;
01011    EasyDbus_obj_signal *signal = NULL;
01012    struct easydbus_introspect_arg_info *el = NULL;
01013    int i_string_l = 0;
01014 
01015    if (!interface) 
01016       return -1;
01017 
01018    // add <introspect name="..."> + </introspect>
01019    i_string_l = EASYDBUS_INTROSPECT_INTERFACE_TAG_O_L +
01020                 strlen (interface->name) +
01021                 EASYDBUS_INTROSPECT_NODE_TAG_INIT_C_L +
01022                 EASYDBUS_INTROSPECT_INTERFACE_TAG_C_L;
01023 
01024    for (method = interface->handled_methods; method;
01025         method = method->next) 
01026       if (method->input_info || method->output_info) {
01027          // add <method name="..."> + </method>
01028          i_string_l += EASYDBUS_INTROSPECT_METHOD_TAG_O_L +
01029                        strlen (method->name) +
01030                        EASYDBUS_INTROSPECT_NODE_TAG_INIT_C_L +
01031                        EASYDBUS_INTROSPECT_METHOD_TAG_C_L;
01032          for (el = method->input_info; el; el = el->next)
01033             // add <arg name="..." type="..." direction="in"/>
01034             i_string_l += EASYDBUS_INTROSPECT_ARG_NAME_TAG_O_L +
01035                           strlen (el->name) +
01036                           EASYDBUS_INTROSPECT_ARG_SPACE_L +
01037                           EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O_L +
01038                           strlen (el->signature) +
01039                           EASYDBUS_INTROSPECT_ARG_SPACE_L +
01040                           EASYDBUS_INTROSPECT_ARG_DIRECTION_O_L +
01041                           EASYDBUS_INTROSPECT_DIRECTION_IN_L +
01042                           EASYDBUS_INTROSPECT_TAG_END_L;
01043          for (el = method->output_info; el; el = el->next)
01044             // add <arg name="..." type="..." direction="out"/>
01045             i_string_l += EASYDBUS_INTROSPECT_ARG_NAME_TAG_O_L +
01046                           strlen (el->name) +
01047                           EASYDBUS_INTROSPECT_ARG_SPACE_L +
01048                           EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O_L +
01049                           strlen (el->signature) +
01050                           EASYDBUS_INTROSPECT_ARG_SPACE_L +
01051                           EASYDBUS_INTROSPECT_ARG_DIRECTION_O_L +
01052                           EASYDBUS_INTROSPECT_DIRECTION_OUT_L +
01053                           EASYDBUS_INTROSPECT_TAG_END_L;
01054       }
01055 
01056    for (signal = interface->handled_signals; signal;
01057         signal = signal->next)
01058       if (signal->output_info) {
01059          // add <signal name="..."> + </signal>
01060          i_string_l += EASYDBUS_INTROSPECT_SIGNAL_TAG_O_L +
01061                        strlen (signal->name) + 
01062                        EASYDBUS_INTROSPECT_NODE_TAG_INIT_C_L +
01063                        EASYDBUS_INTROSPECT_SIGNAL_TAG_C_L;
01064          for (el = signal->output_info; el; el = el->next)
01065             // add <arg name="..." type="..."/>
01066             i_string_l += EASYDBUS_INTROSPECT_ARG_NAME_TAG_O_L +
01067                           strlen (el->name) + 
01068                           EASYDBUS_INTROSPECT_ARG_SPACE_L +
01069                           EASYDBUS_INTROSPECT_ARG_TYPE_TAG_O_L +
01070                           strlen (el->signature) +
01071                           EASYDBUS_INTROSPECT_TAG_END_L;
01072       }
01073 
01074    return i_string_l;
01075 }
01076 
01077 // vim: ts=3 shiftwidth=3 expandtab

Generated on Thu Apr 10 10:00:18 2008 for EasyDbus-0.2 by  doxygen 1.5.4