diff options
Diffstat (limited to 'bus/connection.c')
| -rw-r--r-- | bus/connection.c | 169 | 
1 files changed, 149 insertions, 20 deletions
| diff --git a/bus/connection.c b/bus/connection.c index 5121658d..a824576c 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -25,6 +25,7 @@  #include "policy.h"  #include "services.h"  #include "utils.h" +#include "signals.h"  #include <dbus/dbus-list.h>  #include <dbus/dbus-hash.h>  #include <dbus/dbus-timeout.h> @@ -41,6 +42,7 @@ struct BusConnections    BusContext *context;    DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */    DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */ +  int stamp;            /**< Incrementing number */  };  static dbus_int32_t connection_data_slot = -1; @@ -52,6 +54,8 @@ typedef struct    DBusConnection *connection;    DBusList *services_owned;    int n_services_owned; +  DBusList *match_rules; +  int n_match_rules;    char *name;    DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */    DBusMessage *oom_message; @@ -60,6 +64,7 @@ typedef struct    long connection_tv_sec;  /**< Time when we connected (seconds component) */    long connection_tv_usec; /**< Time when we connected (microsec component) */ +  int stamp;               /**< connections->stamp last time we were traversed */  } BusConnectionData;  static dbus_bool_t expire_incomplete_timeout (void *data); @@ -140,12 +145,20 @@ bus_connection_disconnected (DBusConnection *connection)  {    BusConnectionData *d;    BusService *service; - +  BusMatchmaker *matchmaker; +      d = BUS_CONNECTION_DATA (connection);    _dbus_assert (d != NULL);    _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",                   d->name ? d->name : "(inactive)"); + +  /* Delete our match rules */ +  if (d->n_match_rules > 0) +    { +      matchmaker = bus_context_get_matchmaker (d->connections->context); +      bus_matchmaker_disconnected (matchmaker, connection); +    }    /* Drop any service ownership. FIXME Unfortunately, this requires     * memory allocation and there doesn't seem to be a good way to @@ -881,6 +894,40 @@ bus_connections_get_context (BusConnections *connections)    return connections->context;  } +/* + * This is used to avoid covering the same connection twice when + * traversing connections. Note that it assumes we will + * bus_connection_mark_stamp() each connection at least once per + * INT_MAX increments of the global stamp, or wraparound would break + * things. + */ +void +bus_connections_increment_stamp (BusConnections *connections) +{ +  connections->stamp += 1; +} + +/* Mark connection with current stamp, return TRUE if it + * didn't already have that stamp + */ +dbus_bool_t +bus_connection_mark_stamp (DBusConnection *connection) +{ +  BusConnectionData *d; +   +  d = BUS_CONNECTION_DATA (connection); +   +  _dbus_assert (d != NULL); + +  if (d->stamp == d->connections->stamp) +    return FALSE; +  else +    { +      d->stamp = d->connections->stamp; +      return TRUE; +    } +} +  BusContext*  bus_connection_get_context (DBusConnection *connection)  { @@ -929,6 +976,18 @@ bus_connection_get_activation (DBusConnection *connection)    return bus_context_get_activation (d->connections->context);  } +BusMatchmaker* +bus_connection_get_matchmaker (DBusConnection *connection) +{ +  BusConnectionData *d; + +  d = BUS_CONNECTION_DATA (connection); + +  _dbus_assert (d != NULL); + +  return bus_context_get_matchmaker (d->connections->context); +} +  /**   * Checks whether the connection is registered with the message bus.   * @@ -963,19 +1022,19 @@ bus_connection_preallocate_oom_error (DBusConnection *connection)    if (preallocated == NULL)      return FALSE; -  /* d->name may be NULL, but that is OK */ -  message = dbus_message_new (DBUS_ERROR_NO_MEMORY, -                              d->name); +  message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); +    if (message == NULL)      {        dbus_connection_free_preallocated_send (connection, preallocated);        return FALSE;      } -  dbus_message_set_is_error (message, TRUE); - -  if (!dbus_message_set_sender (message, -                                DBUS_SERVICE_DBUS)) +  /* d->name may be NULL, but that is OK */ +  if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) || +      !dbus_message_set_destination (message, d->name) || +      !dbus_message_set_sender (message, +                                DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))      {        dbus_connection_free_preallocated_send (connection, preallocated);        dbus_message_unref (message); @@ -1025,6 +1084,62 @@ bus_connection_send_oom_error (DBusConnection *connection,  }  void +bus_connection_add_match_rule_link (DBusConnection *connection, +                                    DBusList       *link) +{ +  BusConnectionData *d; + +  d = BUS_CONNECTION_DATA (connection); +  _dbus_assert (d != NULL); + +  _dbus_list_append_link (&d->match_rules, link); + +  d->n_match_rules += 1; +} + +dbus_bool_t +bus_connection_add_match_rule (DBusConnection *connection, +                               BusMatchRule   *rule) +{ +    DBusList *link; + +  link = _dbus_list_alloc_link (rule); + +  if (link == NULL) +    return FALSE; + +  bus_connection_add_match_rule_link (connection, link); + +  return TRUE; +} + +void +bus_connection_remove_match_rule (DBusConnection *connection, +                                  BusMatchRule   *rule) +{ +  BusConnectionData *d; + +  d = BUS_CONNECTION_DATA (connection); +  _dbus_assert (d != NULL); + +  _dbus_list_remove_last (&d->match_rules, rule); + +  d->n_match_rules -= 1; +  _dbus_assert (d->n_match_rules >= 0); +} + +int +bus_connection_get_n_match_rules (DBusConnection *connection) +{ +  BusConnectionData *d; + +  d = BUS_CONNECTION_DATA (connection); +  _dbus_assert (d != NULL); +   +  return d->n_match_rules; +} + +void  bus_connection_add_owned_service_link (DBusConnection *connection,                                         DBusList       *link)  { @@ -1092,6 +1207,8 @@ bus_connection_complete (DBusConnection   *connection,    _dbus_assert (d != NULL);    _dbus_assert (d->name == NULL);    _dbus_assert (d->policy == NULL); + +  _dbus_assert (!bus_connection_is_active (connection));    if (!_dbus_string_copy_data (name, &d->name))      { @@ -1147,6 +1264,8 @@ bus_connection_complete (DBusConnection   *connection,    /* See if we can remove the timeout */    bus_connections_expire_incomplete (d->connections); + +  _dbus_assert (bus_connection_is_active (connection));    return TRUE;  } @@ -1312,17 +1431,22 @@ bus_transaction_send_from_driver (BusTransaction *transaction,     * to check security policy since it was not done in     * dispatch.c     */ -  _dbus_verbose ("Sending %s from driver\n", -                 dbus_message_get_name (message)); -   -  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) +  _dbus_verbose ("Sending %s %s %s from driver\n", +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : "(no interface)", +                 dbus_message_get_member (message) ? +                 dbus_message_get_member (message) : "(no member)", +                 dbus_message_get_error_name (message) ? +                 dbus_message_get_error_name (message) : "(no error name)"); +                  +  if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))      return FALSE;    /* If security policy doesn't allow the message, we silently     * eat it; the driver doesn't care about getting a reply.     */    if (!bus_context_check_security_policy (bus_transaction_get_context (transaction), -                                          NULL, connection, message, NULL)) +                                          NULL, connection, connection, message, NULL))      return TRUE;    return bus_transaction_send (transaction, connection, message); @@ -1337,11 +1461,16 @@ bus_transaction_send (BusTransaction *transaction,    BusConnectionData *d;    DBusList *link; -  _dbus_verbose ("  trying to add %s %s to transaction%s\n", -                 dbus_message_get_is_error (message) ? "error" : +  _dbus_verbose ("  trying to add %s interface=%s member=%s error=%s to transaction%s\n", +                 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" :                   dbus_message_get_reply_serial (message) != 0 ? "reply" :                   "message", -                 dbus_message_get_name (message), +                 dbus_message_get_interface (message) ? +                 dbus_message_get_interface (message) : "(unset)", +                 dbus_message_get_member (message) ? +                 dbus_message_get_member (message) : "(unset)", +                 dbus_message_get_error_name (message) ? +                 dbus_message_get_error_name (message) : "(unset)",                   dbus_connection_get_is_connected (connection) ?                   "" : " (disconnected)"); @@ -1550,13 +1679,13 @@ bus_transaction_send_error_reply (BusTransaction  *transaction,    _dbus_assert (error != NULL);    _DBUS_ASSERT_ERROR_IS_SET (error); - +      _dbus_verbose ("Sending error reply %s \"%s\"\n",                   error->name, error->message); -  reply = dbus_message_new_error_reply (in_reply_to, -                                        error->name, -                                        error->message); +  reply = dbus_message_new_error (in_reply_to, +                                  error->name, +                                  error->message);    if (reply == NULL)      return FALSE; | 
