Logo Search packages:      
Sourcecode: galago-daemon version File versions  Download package

core.c

Go to the documentation of this file.
/**
 * @file core.c Galago Core message processor
 *
 * Copyright (C) 2004-2006 Christian Hammond.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA  02111-1307  USA
 */
#include "galagod.h"
#include "filter.h"
#include "service-list.h"
#include "person-list.h"
#include "utils.h"

/* Provided by libgalago */
void _galago_person_set_session_id(GalagoPerson *person, const char *id);

static DBusHandlerResult
coco_add_service(DBusConnection *dbus_conn, DBusMessage *message,
                 GalagodCoCo *coco)
{
      GalagoService *service;
      DBusMessageIter iter;
      DBusMessage *reply;
      char *obj_path;

      dbus_message_iter_init(message, &iter);
      service = galago_dbus_message_iter_get_object(&iter, GALAGO_TYPE_SERVICE);
      g_object_set_data(G_OBJECT(service), "coco", coco);

      /* Send the reply containing the object path. */
      reply = dbus_message_new_method_return(message);
      dbus_message_iter_init_append(reply, &iter);

      obj_path = galagod_service_generate_path(service);
      galago_object_set_dbus_path(GALAGO_OBJECT(service), obj_path);
      dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &obj_path);

      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      g_free(obj_path);

      galagod_services_add(service);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
coco_remove_service(DBusConnection *conn, DBusMessage *message,
                              GalagodCoCo *coco)
{
      GalagoService *service;
      DBusMessageIter iter;

      dbus_message_iter_init(message, &iter);
      service = galago_dbus_message_iter_get_object(&iter, GALAGO_TYPE_SERVICE);
      galagod_services_remove(service);
      g_object_unref(service);

      galagod_dbus_send_empty_reply(conn, message);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
coco_clear_services(DBusConnection *conn, DBusMessage *message,
                              GalagodCoCo *coco)
{
      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

static DBusHandlerResult
coco_add_person(DBusConnection *dbus_conn, DBusMessage *message,
                        GalagodCoCo *coco)
{
      DBusMessage *reply;
      DBusMessageIter iter;
      GalagodMetaPerson *meta_person;
      GalagoPerson *person;
      const char *uid;
      char *obj_path;

      dbus_message_iter_init(message, &iter);
      person = galago_dbus_message_iter_get_object(&iter, GALAGO_TYPE_PERSON);
      g_object_set_data(G_OBJECT(person), "coco", coco);
      obj_path = galagod_person_generate_path(person);
      galago_object_set_dbus_path(GALAGO_OBJECT(person), obj_path);

      galagod_people_add(person);

      meta_person = GALAGOD_META_PERSON(person);
      uid = galago_person_get_id(galagod_meta_person_get_person(meta_person));

      /* Send the reply containing the object path. */
      reply = dbus_message_new_method_return(message);
      dbus_message_iter_init_append(reply, &iter);
      dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &obj_path);
      galago_dbus_message_iter_append_string_or_nil(&iter, uid);
      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      g_free(obj_path);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
coco_remove_person(DBusConnection *conn, DBusMessage *message,
                           GalagodCoCo *coco)
{
      GalagoPerson *person;
      DBusMessageIter iter;

      dbus_message_iter_init(message, &iter);
      person = galago_dbus_message_iter_get_object(&iter, GALAGO_TYPE_PERSON);

      galagod_people_remove(person);

      g_object_unref(person);

      galagod_dbus_send_empty_reply(conn, message);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
coco_clear_people(DBusConnection *conn, DBusMessage *message,
                          GalagodCoCo *coco)
{
      return DBUS_HANDLER_RESULT_HANDLED;
}

static const GalagodCommand coco_commands[] =
{
      GALAGOD_COMMAND("AddService",    coco_add_service),
      GALAGOD_COMMAND("RemoveService", coco_remove_service),
      GALAGOD_COMMAND("ClearServices", coco_clear_services),
      GALAGOD_COMMAND("AddPerson",     coco_add_person),
      GALAGOD_COMMAND("RemovePerson",  coco_remove_person),
      GALAGOD_COMMAND("ClearPeople",   coco_clear_people),
      GALAGOD_COMMAND_LAST
};

static DBusHandlerResult
coco_path_message_func(DBusConnection *dbus_conn, DBusMessage *message,
                                 void *user_data)
{
      DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
      GalagodCoCo *coco = (GalagodCoCo *)user_data;

      if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
            return result;

      if (dbus_message_get_path(message) == NULL)
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      galago_context_push(galagod_coco_get_context(coco));
      result = galagod_cmd_table_execute(coco_commands, dbus_conn,
                                                         message, coco, NULL,
                                                         GALAGO_DBUS_CORE_INTERFACE);
      galago_context_pop();

      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

static DBusObjectPathVTable coco_vtable =
{
      NULL,
      coco_path_message_func,
      NULL,
};

static DBusHandlerResult
core_register(DBusConnection *conn, DBusMessage *message)
{
      DBusConnection *dbus_conn;
      DBusMessage *reply;
      DBusMessageIter iter;
      GalagodCoCo *coco;
      gboolean feed;
      const char *name;

      dbus_conn = galago_get_dbus_conn();

      dbus_message_iter_init(message, &iter);
      dbus_message_iter_get_basic(&iter, &name);
      dbus_message_iter_next(&iter);

      dbus_message_iter_get_basic(&iter, &feed);
      dbus_message_iter_next(&iter);

      coco = galagod_coco_new(name, feed, dbus_message_get_sender(message));

      if (coco == NULL)
      {
            reply = dbus_message_new_error(message, "RegistrationFailed",
                                                         "Registration failed.");
      }
      else
      {
            const char *obj_path, *id;

            obj_path = galago_object_get_dbus_path(GALAGO_OBJECT(coco));
            id       = galagod_coco_get_id(coco);

            if (!dbus_connection_register_object_path(dbus_conn, obj_path,
                                                                          &coco_vtable, coco))
            {
                  abort();
            }

            reply = dbus_message_new_method_return(message);
            dbus_message_iter_init_append(reply, &iter);
            dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &id);
            dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &obj_path);
      }

      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      if (feed)
            g_message("Feed '%s' registered.", name);
      else
            g_message("Client '%s' registered.", name);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_unregister(DBusConnection *conn, DBusMessage *message)
{
      DBusMessageIter iter;
      GalagodCoCo *coco;
      const char *obj_path;

      dbus_message_iter_init(message, &iter);
      dbus_message_iter_get_basic(&iter, &obj_path);

      coco = galagod_cocos_get_with_obj_path(obj_path);

      if (coco == NULL)
      {
            g_warning("Attempted to unregister a non-existant CoCo with path %s",
                          obj_path);

            return DBUS_HANDLER_RESULT_HANDLED;
      }

      g_object_unref(coco);

      galagod_dbus_send_empty_reply(conn, message);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_get_service(DBusConnection *dbus_conn, DBusMessage *message)
{
      DBusMessage *reply;
      DBusMessageIter iter;
      GalagodMetaService *meta_service;
      GalagoService *service = NULL;
      const char *id;

      dbus_message_iter_init(message, &iter);
      dbus_message_iter_get_basic(&iter, &id);
      dbus_message_iter_next(&iter);

      meta_service = galagod_services_get_meta_service(id);

      if (meta_service != NULL)
            service = galagod_meta_service_get_service(meta_service);

      if (service == NULL)
      {
            reply = galagod_object_not_found_error_new(message,
                  "The service '%s' could not be found.",
                  id);
      }
      else
      {
            reply = dbus_message_new_method_return(message);
            dbus_message_iter_init_append(reply, &iter);
            galago_dbus_message_iter_append_object(&iter, GALAGO_OBJECT(service));
      }

      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_get_services(DBusConnection *dbus_conn, DBusMessage *message)
{
      DBusMessage *reply;
      DBusMessageIter iter, array_iter;
      const GList *l;
      GalagodMetaService *meta_service;
      GalagoService *service;

      reply = dbus_message_new_method_return(message);

      dbus_message_iter_init_append(reply, &iter);
      dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
            galago_object_type_get_dbus_signature(GALAGO_TYPE_SERVICE),
            &array_iter);

      for (l = galagod_services_get_meta_services(); l != NULL; l = l->next)
      {
            meta_service = (GalagodMetaService *)l->data;
            service      = galagod_meta_service_get_service(meta_service);

            galago_dbus_message_iter_append_object(&array_iter,
                                                                     GALAGO_OBJECT(service));
      }

      dbus_message_iter_close_container(&iter, &array_iter);

      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_get_services_count(DBusConnection *dbus_conn, DBusMessage *message)
{
      DBusMessage *reply;
      DBusMessageIter iter;
      size_t count;

      count = galagod_services_get_meta_service_count();

      reply = dbus_message_new_method_return(message);
      dbus_message_iter_init_append(reply, &iter);
      dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &count);
      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_get_person(DBusConnection *dbus_conn, DBusMessage *message)
{
      DBusMessage *reply;
      DBusMessageIter iter;
      GalagodMetaPerson *meta_person;
      GalagoPerson *person = NULL;
      const char *id;

      dbus_message_iter_init(message, &iter);
      dbus_message_iter_get_basic(&iter, &id);

      meta_person = galagod_people_get_meta_person(id);

      if (meta_person != NULL)
            person = galagod_meta_person_get_person(meta_person);

      if (person == NULL)
      {
            reply = galagod_object_not_found_error_new(message,
                  "The person '%s' could not be found.",
                  id);
      }
      else
      {
            reply = dbus_message_new_method_return(message);
            dbus_message_iter_init_append(reply, &iter);
            galago_dbus_message_iter_append_object(&iter, GALAGO_OBJECT(person));
      }

      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_get_me(DBusConnection *dbus_conn, DBusMessage *message)
{
      DBusMessage *reply;
      DBusMessageIter iter;
      GalagodMetaPerson *meta_me;
      GalagoPerson *me = NULL;

      meta_me = galagod_people_get_me();

      if (meta_me != NULL)
            me = galagod_meta_person_get_person(meta_me);

      if (me == NULL)
      {
            /*
             * XXX We really should always have this. Make it always exist
             *     later?
             */
            reply = galagod_object_not_found_error_new(message,
                  "The 'me' person could not be found.");
      }
      else
      {
            reply = dbus_message_new_method_return(message);
            dbus_message_iter_init_append(reply, &iter);
            galago_dbus_message_iter_append_object(&iter, GALAGO_OBJECT(me));
      }

      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_get_people(DBusConnection *dbus_conn, DBusMessage *message)
{
      DBusMessage *reply;
      DBusMessageIter iter, array_iter;
      const GList *l;
      size_t person_count;
      GalagodMetaPerson *meta_person;
      GalagoPerson *person;

      person_count = galagod_people_get_meta_person_count();

      reply = dbus_message_new_method_return(message);

      dbus_message_iter_init_append(reply, &iter);
      dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
            galago_object_type_get_dbus_signature(GALAGO_TYPE_PERSON),
            &array_iter);

      for (l = galagod_people_get_meta_people(); l != NULL; l = l->next)
      {
            meta_person = (GalagodMetaPerson *)l->data;
            person      = galagod_meta_person_get_person(meta_person);

            galago_dbus_message_iter_append_object(&array_iter,
                                                                     GALAGO_OBJECT(person));
      }

      dbus_message_iter_close_container(&iter, &array_iter);

      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_get_people_count(DBusConnection *dbus_conn, DBusMessage *message)
{
      DBusMessage *reply;
      DBusMessageIter iter;
      size_t count;

      count = galagod_people_get_meta_person_count();

      reply = dbus_message_new_method_return(message);
      dbus_message_iter_init_append(reply, &iter);
      dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &count);
      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult
core_shutdown(DBusConnection *dbus_conn, DBusMessage *message)
{
      galagod_dbus_send_empty_reply(dbus_conn, message);

      galagod_shutdown();

      return DBUS_HANDLER_RESULT_HANDLED;
}

static const GalagodCommand core_commands[] =
{
      GALAGOD_COMMAND("Register",         core_register),
      GALAGOD_COMMAND("Unregister",       core_unregister),
      GALAGOD_COMMAND("GetService",       core_get_service),
      GALAGOD_COMMAND("GetServices",      core_get_services),
      GALAGOD_COMMAND("GetServicesCount", core_get_services_count),
      GALAGOD_COMMAND("GetMe",            core_get_me),
      GALAGOD_COMMAND("GetPerson",        core_get_person),
      GALAGOD_COMMAND("GetPeople",        core_get_people),
      GALAGOD_COMMAND("GetPeopleCount",   core_get_people_count),
      GALAGOD_COMMAND("ShutDown",         core_shutdown),
      GALAGOD_COMMAND_LAST
};

static DBusHandlerResult
core_path_message_func(DBusConnection *dbus_conn, DBusMessage *message,
                                 void *user_data)
{
      if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      return galagod_cmd_table_execute(core_commands, dbus_conn, message, NULL,
                                                       NULL, GALAGO_DBUS_CORE_INTERFACE);
}

static DBusObjectPathVTable core_vtable =
{
      NULL,
      core_path_message_func,
      NULL,
};

static DBusHandlerResult
filter_func(DBusConnection *dbus_conn, DBusMessage *message, void *user_data)
{
      DBusMessageIter iter;

      if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
                                             "ServiceDeleted"))
      {
            const char *dbus_service;

            dbus_message_iter_init(message, &iter);
            dbus_message_iter_get_basic(&iter, &dbus_service);

            if (strcmp(dbus_service, GALAGO_DBUS_SERVICE))
            {
                  GalagodCoCo *coco;

                  coco = galagod_cocos_get_with_service_id(dbus_service);

                  if (coco != NULL)
                        g_object_unref(coco);
            }
      }

      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

void
galagod_core_add_filter(void)
{
      DBusConnection *dbus_conn = galago_get_dbus_conn();

      if (!dbus_connection_register_object_path(dbus_conn,
                                                                    GALAGO_DBUS_CORE_OBJECT,
                                                                    &core_vtable, NULL))
      {
            abort();
      }

      dbus_bus_add_match(dbus_conn,
                                 "type='signal',"
                                 "interface='" DBUS_INTERFACE_DBUS "',"
                                 "sender='" DBUS_SERVICE_DBUS "'",
                                 NULL);

      dbus_connection_add_filter(dbus_conn, filter_func, NULL, NULL);
}

Generated by  Doxygen 1.6.0   Back to index