register_obj_internal.c

Go to the documentation of this file.
00001 /*
00002  EasyDbus: 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:  register_obj_internal.c
00020 
00021  Description:
00022 
00023  Version:  1.0
00024  Created:  09/17/07 19:16:42 CEST
00025  Revision:  none
00026 
00027  Author:   Daniele Rondina aka Ge@@ru (geaaru@gmail.com) 
00028  License:  GPL 2.0
00029 */
00030 
00031 #include <string.h>
00032 #include <stdlib.h>
00033 //easydbus includes
00034 #include "easydbus-core.h"
00035 #include "debug.h"
00036 #include "utils.h"
00037 #include "reply_internal.h"
00038 #include "introspect_internal.h"
00039 #include "register_obj_internal.h"
00040 #include "message_internal.h"
00041 
00042 /* prototypes */
00043 static DBusHandlerResult
00044 easydbus_signal_handler (struct EasyDbus_core *,
00045                          DBusMessage *);
00046 
00047 static DBusHandlerResult
00048 easydbus_error_handler (struct EasyDbus_core *,
00049                         DBusMessage *);
00050 
00051 static DBusHandlerResult
00052 easydbus_reply_handler (struct EasyDbus_core *,
00053                         DBusMessage *);
00054 
00077 DBusHandlerResult 
00078 easydbus_obj_path_msg_function (DBusConnection * conn, 
00079                                 DBusMessage * msg, 
00080                                 void *user_data) 
00081 {
00082    struct EasyDbus_core *core = (struct EasyDbus_core *) user_data;
00083    struct EasyDbus_object_box *obj = NULL;
00084    struct EasyDbus_obj_interface *interface = NULL;
00085    EasyDbus_reply *reply = NULL;
00086    const char *msg_member = NULL;
00087    const char *msg_interface = NULL;
00088    const char *msg_path = NULL;
00089    int ret_val = -1;
00090 
00091    // Check input param
00092    if (!msg || !conn || !user_data ||
00093        (dbus_message_get_type (msg) != 
00094         DBUS_MESSAGE_TYPE_METHOD_CALL)) {
00095       EasyDbusDebug ("Error");
00096       // see how manage this error. Maybe with an error msg.
00097       return DBUS_HANDLER_RESULT_HANDLED;
00098    }
00099 
00100    msg_path = dbus_message_get_path (msg);
00101    msg_member = dbus_message_get_member (msg);
00102    msg_interface = dbus_message_get_interface (msg);
00103 
00104    EasyDbusDebug ("Message %s for \n"
00105                   "path = %s\n"
00106                   "interface = %s\n"
00107                   "member = %s\n",
00108                   dbus_message_type_to_string (
00109                      dbus_message_get_type (msg)),
00110                   msg_path, msg_interface, msg_member);
00111 
00112    // check object path string of message with object
00113    // path string of registered objects.
00114    obj = easydbus_get_obj (core->objects, msg_path);
00115    if (!obj)
00116       goto obj_not_found;
00117 
00118    /* control any interface connect to object:
00119     * - first match meet is used */
00120    for (interface = obj->core.handled_interfaces;
00121         interface; interface = interface->next) {
00122       reply = easydbus_verify_match_and_prepare_reply (interface, 
00123                                                        msg, msg_interface, 
00124                                                        msg_member, &ret_val);
00125       if (ret_val == EASYDBUS_METHOD_HANDLED ||
00126           ret_val == EASYDBUS_FAILURE_HANDLED) {
00127          easydbus_reply_send (core, msg, reply);
00128          easydbus_reply_free_skeleton (reply);
00129          return DBUS_HANDLER_RESULT_HANDLED;
00130          // this must be managed correctly still
00131       }
00132       else if (ret_val == EASYDBUS_SIGNAL_HANDLED ||
00133                ret_val == EASYDBUS_METHOD_RETURN_HANDLED) {
00134          easydbus_reply_send_error (core, msg,
00135                                     "Error",
00136                                     "Error: unpredictable error");
00137          return DBUS_HANDLER_RESULT_HANDLED;
00138       }
00139    }
00140 
00141 obj_not_found:
00142    // send obj path doesn't exist error msg.
00143    // send_not_found_error ();
00144    easydbus_reply_send_error (core, msg, "NotFound",
00145                               "Error: method not found");
00146    return DBUS_HANDLER_RESULT_HANDLED;
00147 }
00148 
00157 void 
00158 easydbus_obj_path_unregister_function (DBusConnection * conn, 
00159                                        void *user_data) 
00160 {
00161 }
00162 
00177 EasyDbus_reply *
00178 easydbus_verify_match_and_prepare_reply 
00179   (struct EasyDbus_obj_interface *interface,
00180    DBusMessage * msg, const char *msg_interface,
00181    const char *member_name, int *return_value) 
00182 {
00183    int callback_retvalue;
00184    struct EasyDbus_obj_method *method = NULL;
00185    EasyDbus_method *method_skeleton = NULL;
00186    EasyDbus_reply *reply = NULL;
00187 
00188    // manage method request
00189    method = easydbus_obj_interface_get_method (member_name, 
00190                                                msg_interface, 
00191                                                interface);
00192    if (!method) {
00193       *return_value = EASYDBUS_METHOD_NOT_FOUND;
00194       goto not_found;
00195    }
00196 
00197    method_skeleton = easydbus_method_build_skeleton (msg);
00198    if (!method_skeleton) {
00199       *return_value = EASYDBUS_ERROR;
00200       goto not_found;
00201    }
00202    callback_retvalue = (int) 
00203       method->method_callback (method_skeleton);
00204    // see if manage failure in this mannaer
00205    if (callback_retvalue == EASYDBUS_METHOD_HANDLED) {
00206       reply = method_skeleton->reply;
00207       *return_value = callback_retvalue;
00208    }
00209    else if (callback_retvalue == EASYDBUS_FAILURE_HANDLED)
00210       if (method_skeleton->reply) {
00211          reply = method_skeleton->reply;
00212          *return_value = callback_retvalue;
00213       }
00214    method_skeleton->reply = NULL;
00215    easydbus_method_free_skeleton (method_skeleton);
00216 
00217    return reply;
00218 
00219 not_found:
00220 
00221    return NULL;
00222 }
00223 
00224 
00234 static DBusHandlerResult
00235 easydbus_signal_handler (struct EasyDbus_core *core,
00236                          DBusMessage *msg) 
00237 {
00238    struct EasyDbus_ext_signal *el = NULL;
00239    struct EasyDbus_signal *handled_signal = NULL;
00240    const char *msg_member = NULL;
00241    const char *msg_interface = NULL;
00242    const char *msg_path = NULL;
00243    const char *msg_sender = NULL;
00244    const char *msg_destination = NULL;
00245 
00246    // get member
00247    msg_member = dbus_message_get_member (msg);
00248    // get interface
00249    msg_interface = dbus_message_get_interface (msg);
00250    // get path
00251    msg_path = dbus_message_get_path (msg);
00252    // get sender
00253    msg_sender = dbus_message_get_sender (msg);
00254    // get destination
00255    msg_destination = dbus_message_get_destination (msg);
00256 
00257    if (core->handled_signal)
00258       for (el = core->handled_ext_signals; el; el = el->next)
00259          if (!easydbus_verify_signal_match
00260              (msg_member, msg_interface, msg_path, msg_sender, 
00261               msg_destination, el)) {
00262             EasyDbusDebug ("Extern Signal Handled");
00263             handled_signal = easydbus_signal_build_skeleton (msg);
00264             if (handled_signal) {
00266                if (msg_sender)
00267                   easydbus_signal_set_sender (handled_signal, msg_sender);
00268                el->signal_callback ((struct EasyDbus_conn *) core,
00269                                     handled_signal);
00270                easydbus_signal_free_skeleton (handled_signal);
00271             }
00272             goto out;
00273          }
00274 
00275    EasyDbusDebug ("\n"
00276                   "- Drop signal -------------------\n"
00277                   "path = %s\n"
00278                   "interface = %s\n"
00279                   "member = %s\n"
00280                   "sender = %s\n"
00281                   "destination = %s\n"
00282                   "---------------------------------\n",
00283                   msg_path, msg_interface, msg_member, 
00284                   msg_sender, msg_destination);
00285 
00286 out:
00287    return DBUS_HANDLER_RESULT_HANDLED;
00288 }
00289 
00300 static DBusHandlerResult
00301 easydbus_error_handler (struct EasyDbus_core *core,
00302                          DBusMessage *msg) 
00303 {
00304    EasyDbus_reply *error_message = NULL;
00305    struct EasyDbus_Pending *p = NULL, **pp = NULL;
00306    const char *msg_interface = NULL;
00307    const char *msg_path = NULL;
00308    const char *msg_sender = NULL;
00309    dbus_uint32_t serial = 0;
00310 
00311    // get interface
00312    msg_interface = dbus_message_get_interface (msg);
00313    // get path
00314    msg_path = dbus_message_get_path (msg);
00315    // get sender
00316    msg_sender = dbus_message_get_sender (msg);
00317 
00318    EasyDbusDebug ("\n"
00319                   "- Handle error message ----------\n"
00320                   "path = %s\n"
00321                   "interface = %s\n"
00322                   "member = %s\n"
00323                   "sender = %s\n"
00324                   "---------------------------------\n",
00325                   msg_path, msg_interface, 
00326                   dbus_message_get_member (msg), msg_sender);
00327 
00328    error_message = easydbus_reply_create_skeleton ();
00329    if (!error_message)
00330       goto need_memory;
00331 
00332    easydbus_reply_set_type (error_message, EASYDBUS_ET_FAILURE);
00333 
00334    if (msg_interface)
00335       if (easydbus_reply_set_interface (error_message, msg_interface))
00336          goto need_memory;
00337    if (msg_path)
00338       if (easydbus_reply_set_path (error_message, msg_path))
00339          goto need_memory;
00340    if (msg_sender)
00341       if (easydbus_reply_set_sender (error_message, msg_sender))
00342          goto need_memory;
00343 
00344    easydbus_build_skeleton_data (msg, EASYDBUS_ET_FAILURE, 
00345                                  error_message);
00346 
00347    serial = dbus_message_get_reply_serial (msg);
00348    EasyDbusDebug ("Message serial = %d", serial);
00349 
00350    for (p = core->pending_msgs; p; p = p->next) 
00351       // if p->pcall is equal to null then is a pending struct
00352       // not connected to async message with notify
00353       if (!p->pcall && p->message_serial == serial) {
00354          p->message->reply = error_message;
00355          // remove EasyDbus_pending object from list
00356          for (pp = &(p->core->pending_msgs); *pp; pp = &(*pp)->next)
00357             if (*pp == p) {
00358                *pp = (*pp)->next;
00359                break;
00360             }
00361          if (core->user_data.reply_message_cb) 
00362             core->user_data.reply_message_cb ((EasyDbus_conn *) core,
00363                                               (const EasyDbus_method *) p->message,
00364                                               p->closure);
00365          break;
00366       }
00367 
00368    if (p)
00369       // error_message is free on easydbus_pending_destroy if 
00370       // it is connected to a EasyDbus_pending object
00371       easydbus_pending_destroy (p);
00372    else {
00373       if (core->user_data.error_message_cb)
00374          core->user_data.error_message_cb ((EasyDbus_conn *) core,
00375                                            (const EasyDbus_reply *) error_message,
00376                                            core->user_data.error_message_closure);
00377       easydbus_reply_free_skeleton (error_message);
00378    }
00379 
00380    return DBUS_HANDLER_RESULT_HANDLED;
00381 
00382 need_memory:
00383    if (error_message)
00384       easydbus_reply_free_skeleton (error_message);
00385 
00386    return DBUS_HANDLER_RESULT_NEED_MEMORY;
00387 }
00388 
00401 static DBusHandlerResult
00402 easydbus_reply_handler (struct EasyDbus_core *core,
00403                          DBusMessage *msg) 
00404 {
00405    EasyDbus_reply *reply = NULL;
00406    struct EasyDbus_Pending *p = NULL, **pp = NULL;
00407    const char *msg_member = NULL;
00408    const char *msg_interface = NULL;
00409    const char *msg_path = NULL;
00410    const char *msg_sender = NULL;
00411    dbus_uint32_t serial = 0;
00412 
00413    // get member
00414    msg_member = dbus_message_get_member (msg);
00415    // get interface
00416    msg_interface = dbus_message_get_interface (msg);
00417    // get path
00418    msg_path = dbus_message_get_path (msg);
00419    // get sender
00420    msg_sender = dbus_message_get_sender (msg);
00421 
00422    EasyDbusDebug ("\n"
00423                   "- Message reply -----------------\n"
00424                   "path = %s\n"
00425                   "interface = %s\n"
00426                   "member = %s\n"
00427                   "sender = %s\n"
00428                   "---------------------------------\n",
00429                   msg_path, msg_interface, msg_member, msg_sender);
00430 
00431    reply = easydbus_reply_create_skeleton ();
00432    if (!reply)
00433       goto need_memory;
00434 
00435    easydbus_reply_set_type (reply, EASYDBUS_ET_REPLY);
00436 
00437    if (msg_interface)
00438       if (easydbus_reply_set_interface (reply, msg_interface))
00439          goto need_memory;
00440    if (msg_path)
00441       if (easydbus_reply_set_path (reply, msg_path))
00442          goto need_memory;
00443    if (msg_sender)
00444       if (easydbus_reply_set_sender (reply, msg_sender))
00445          goto need_memory;
00446 
00447    easydbus_build_skeleton_data (msg, EASYDBUS_ET_REPLY, 
00448                                  reply);
00449 
00450    serial = dbus_message_get_reply_serial (msg);
00451    EasyDbusDebug ("Message serial = %d", serial);
00452 
00453    for (p = core->pending_msgs; p; p = p->next)
00454       // if p->pcall is equal to null then is a pending struct
00455       // not connected to async message with notify
00456       if (!p->pcall && p->message_serial == serial) {
00457          p->message->reply = reply;
00458          // remove EasyDbus_pending object from list
00459          for (pp = &(p->core->pending_msgs); *pp; pp = &(*pp)->next)
00460             if (*pp == p) {
00461                *pp = (*pp)->next;
00462                break;
00463             }
00464          if (core->user_data.reply_message_cb)
00465             core->user_data.reply_message_cb ((EasyDbus_conn *) core,
00466                                               (const EasyDbus_method *) p->message,
00467                                               p->closure);
00468          break;
00469       }
00470 
00471    if (p)
00472       easydbus_pending_destroy (p);
00473    else
00474       easydbus_reply_free_skeleton (reply);
00475 
00476    return DBUS_HANDLER_RESULT_HANDLED;
00477 
00478 need_memory:
00479 
00480    if (reply)
00481       easydbus_reply_free_skeleton (reply);
00482 
00483    return DBUS_HANDLER_RESULT_NEED_MEMORY;
00484 }
00485 
00508 DBusHandlerResult
00509 easydbus_core_filter_func (DBusConnection * conn,
00510                            DBusMessage * msg, void *user_data)
00511 {
00512    struct EasyDbus_core *core =
00513     (struct EasyDbus_core *) user_data;
00514 
00515    if (dbus_message_is_signal (msg,
00516                                DBUS_INTERFACE_LOCAL,
00517                                "Disconnected")) {
00518       EasyDbusDebug ("Error DBUS disconnected!!!");
00519 
00520       if (core->user_data.error_cb)
00521          core->user_data.error_cb ((EasyDbus_conn *) user_data, 
00522                                    core->user_data.error_closure);
00523       return DBUS_HANDLER_RESULT_HANDLED;
00524    }
00525 
00526    EasyDbusDebug ("Core filter analysis");
00527    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00528 }
00529 
00539 DBusHandlerResult
00540 easydbus_filter_func (DBusConnection * conn,
00541                       DBusMessage * msg, void *user_data)
00542 {
00543    struct EasyDbus_core *core = (struct EasyDbus_core *) user_data;
00544    int msg_type;
00545 
00546    if (!conn || !msg || !user_data) {
00547       EasyDbusDebug ("Error");
00548       return DBUS_HANDLER_RESULT_HANDLED;
00549    }
00550 
00551    EasyDbusDebug ("Message under filter analysis");
00552 
00553    // get message type
00554    msg_type = dbus_message_get_type (msg);
00555 
00556    if (msg_type == DBUS_MESSAGE_TYPE_SIGNAL) 
00557       return easydbus_signal_handler (core, msg);
00558    else if (msg_type == DBUS_MESSAGE_TYPE_ERROR) 
00559       return easydbus_error_handler (core, msg);
00560    else if (msg_type == DBUS_MESSAGE_TYPE_METHOD_RETURN) 
00561       return easydbus_reply_handler (core, msg);
00562 
00563    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00564 }
00565 
00577 int
00578 easydbus_verify_signal_match (const char *member,
00579                               const char *interface,
00580                               const char *path,
00581                               const char *sender,
00582                               const char *destination,
00583                               struct EasyDbus_ext_signal *el)
00584 {
00585    if (!el || !member )
00586       return -1;
00587 
00588    if (strcmp (el->signal, member))
00589       return -1;
00590 
00591    if (interface && el->interface)
00592       if (strcmp (el->interface, interface))
00593          return -1;
00594 
00595    if (path && el->path)
00596       if (strcmp (el->path, path))
00597          return -1;
00598 
00599    if (sender && el->sender)
00600       if (strcmp (el->sender, sender))
00601          return -1;
00602 
00603    if (destination && el->destination)
00604       if (strcmp (el->destination, destination))
00605          return -1;
00606 
00607    return 0;
00608 }
00609 
00610 // vim: ts=3 shiftwidth=3 expandtab

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