2003-08-17 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Mon, 18 Aug 2003 15:27:33 +0000 (15:27 +0000)
committerHavoc Pennington <hp@redhat.com>
Mon, 18 Aug 2003 15:27:33 +0000 (15:27 +0000)
This doesn't compile yet, but syncing up so I can hack on it from
work. What are branches for if not broken code? ;-)

* dbus/dbus-protocol.h: remove DBUS_HEADER_FIELD_NAME, add
DBUS_HEADER_FIELD_INTERFACE, DBUS_HEADER_FIELD_MEMBER,
DBUS_HEADER_FIELD_ERROR_NAME

* dbus/dbus-hash.c: Introduce DBUS_HASH_TWO_STRINGS as hack to use
for the interface+member pairs
(string_hash): change to use g_str_hash algorithm
(find_direct_function, find_string_function): refactor these to
share most code.

* dbus/dbus-message.c: port all of this over to support
interface/member fields instead of name field

* dbus/dbus-object-registry.c: port over

* dbus/dbus-string.c (_dbus_string_validate_interface): rename
from _dbus_string_validate_name

* bus/dbus-daemon-1.1: change file format for the
<deny>/<allow> stuff to match new message naming scheme

* bus/policy.c: port over

* bus/config-parser.c: parse new format

18 files changed:
ChangeLog
bus/bus.c
bus/config-parser.c
bus/connection.c
bus/dispatch.c
bus/policy.c
bus/policy.h
dbus/dbus-bus.c
dbus/dbus-connection.c
dbus/dbus-hash.c
dbus/dbus-hash.h
dbus/dbus-message.c
dbus/dbus-message.h
dbus/dbus-object-registry.c
dbus/dbus-object-registry.h
dbus/dbus-protocol.h
dbus/dbus-string.c
dbus/dbus-string.h

index b2f71f1..e22c0de 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2003-08-17  Havoc Pennington  <hp@pobox.com>
+
+       This doesn't compile yet, but syncing up so I can hack on it from
+       work. What are branches for if not broken code? ;-)
+       
+       * dbus/dbus-protocol.h: remove DBUS_HEADER_FIELD_NAME, add
+       DBUS_HEADER_FIELD_INTERFACE, DBUS_HEADER_FIELD_MEMBER,
+       DBUS_HEADER_FIELD_ERROR_NAME
+       
+       * dbus/dbus-hash.c: Introduce DBUS_HASH_TWO_STRINGS as hack to use
+       for the interface+member pairs
+       (string_hash): change to use g_str_hash algorithm
+       (find_direct_function, find_string_function): refactor these to
+       share most code.
+       
+       * dbus/dbus-message.c: port all of this over to support 
+       interface/member fields instead of name field
+
+       * dbus/dbus-object-registry.c: port over
+       
+       * dbus/dbus-string.c (_dbus_string_validate_interface): rename
+       from _dbus_string_validate_name
+
+       * bus/dbus-daemon-1.1: change file format for the 
+       <deny>/<allow> stuff to match new message naming scheme
+
+       * bus/policy.c: port over
+
+       * bus/config-parser.c: parse new format
+       
 2003-08-16  Havoc Pennington  <hp@pobox.com>
 
        * dbus/dbus-object-registry.c (add_and_remove_objects): remove
index a553097..58a1096 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -870,20 +870,21 @@ bus_context_check_security_policy (BusContext     *context,
            * the hello message to the bus driver
            */
           if (recipient == NULL &&
-              dbus_message_has_name (message, DBUS_MESSAGE_HELLO))
+              dbus_message_has_interface (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) &&
+              dbus_message_has_member (message, "Hello"))
             {
               _dbus_verbose ("security check allowing %s message\n",
-                             DBUS_MESSAGE_HELLO);
+                             "Hello");
               return TRUE;
             }
           else
             {
               _dbus_verbose ("security check disallowing non-%s message\n",
-                             DBUS_MESSAGE_HELLO);
+                             "Hello");
 
               dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
                               "Client tried to send a message other than %s without being registered",
-                              DBUS_MESSAGE_HELLO);
+                              "Hello");
               
               return FALSE;
             }
@@ -934,9 +935,14 @@ bus_context_check_security_policy (BusContext     *context,
                       "A security policy in place prevents this sender "
                       "from sending this message to this recipient, "
                       "see message bus configuration file (rejected message "
-                      "had name \"%s\" destination \"%s\")",
-                      dbus_message_get_name (message),
-                      dest ? dest : DBUS_SERVICE_DBUS);
+                      "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")",
+                      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)",
+                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
       _dbus_verbose ("security policy disallowing message due to sender policy\n");
       return FALSE;
     }
@@ -951,9 +957,14 @@ bus_context_check_security_policy (BusContext     *context,
                       "A security policy in place prevents this recipient "
                       "from receiving this message from this sender, "
                       "see message bus configuration file (rejected message "
-                      "had name \"%s\" destination \"%s\")",
-                      dbus_message_get_name (message),
-                      dest ? dest : DBUS_SERVICE_DBUS);
+                      "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")",
+                      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)",
+                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
       _dbus_verbose ("security policy disallowing message due to recipient policy\n");
       return FALSE;
     }
@@ -966,7 +977,7 @@ bus_context_check_security_policy (BusContext     *context,
       const char *dest = dbus_message_get_destination (message);
       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
                       "The destination service \"%s\" has a full message queue",
-                      dest ? dest : DBUS_SERVICE_DBUS);
+                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
       _dbus_verbose ("security policy disallowing message due to full message queue\n");
       return FALSE;
     }
index c42278e..471c67d 100644 (file)
@@ -816,11 +816,15 @@ append_rule_from_element (BusConfigParser   *parser,
                           dbus_bool_t        allow,
                           DBusError         *error)
 {
-  const char *send;
-  const char *receive;
+  const char *send_interface;
+  const char *send_member;
+  const char *send_error;
+  const char *send_service;
+  const char *receive_interface;
+  const char *receive_member;
+  const char *receive_error;
+  const char *receive_service;
   const char *own;
-  const char *send_to;
-  const char *receive_from;
   const char *user;
   const char *group;
   BusPolicyRule *rule;
@@ -829,57 +833,112 @@ append_rule_from_element (BusConfigParser   *parser,
                           attribute_names,
                           attribute_values,
                           error,
-                          "send", &send,
-                          "receive", &receive,
+                          "send_interface", &send_interface,
+                          "send_member", &send_member,
+                          "send_error", &send_error,
+                          "send_service", &send_service,
+                          "receive_interface", &receive_interface,
+                          "receive_member", &receive_member,
+                          "receive_error", &receive_error,
+                          "receive_service", &receive_service,
                           "own", &own,
-                          "send_to", &send_to,
-                          "receive_from", &receive_from,
                           "user", &user,
                           "group", &group,
                           NULL))
     return FALSE;
 
-  if (!(send || receive || own || send_to || receive_from ||
-        user || group))
+  if (!(send_interface || send_member || send_error || send_service ||
+        receive_interface || receive_member || receive_error || receive_service ||
+        own || user || group))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "Element <%s> must have one or more attributes",
                       element_name);
       return FALSE;
     }
-  
-  if (((send && own) ||
-       (send && receive) ||
-       (send && receive_from) ||
-       (send && user) ||
-       (send && group)) ||
-
-      ((receive && own) ||
-       (receive && send_to) ||
-       (receive && user) ||
-       (receive && group)) ||
-
-      ((own && send_to) ||
-       (own && receive_from) ||
-       (own && user) ||
-       (own && group)) ||
 
-      ((send_to && receive_from) ||
-       (send_to && user) ||
-       (send_to && group)) ||
+  if ((send_member && send_interface == NULL) ||
+      (receive_member && receive_interface == NULL))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "On element <%s>, if you specify a member you must specify an interface",
+                      element_name);
+      return FALSE;
+    }
+  
+  /* Allowed combinations of elements are:
+   *
+   *   base, must be all send or all receive:
+   *     interface
+   *     interface + member
+   *     error
+   * 
+   *   base send_ can combine with send_service,
+   *   base receive_ with receive_service
+   *
+   *   user, group, own must occur alone
+   */
 
-      ((receive_from && user) ||
-       (receive_from && group)) ||
+  if (((send_interface && send_error) ||
+       (send_interface && receive_interface) ||
+       (send_interface && receive_member) ||
+       (send_interface && receive_error) ||
+       (send_interface && receive_service) ||
+       (send_interface && own) ||
+       (send_interface && user) ||
+       (send_interface && group)) ||
+
+      ((send_member && send_error) ||
+       (send_member && receive_interface) ||
+       (send_member && receive_member) ||
+       (send_member && receive_error) ||
+       (send_member && receive_service) ||
+       (send_member && own) ||
+       (send_member && user) ||
+       (send_member && group)) ||
+      
+      ((send_error && receive_interface) ||
+       (send_error && receive_member) ||
+       (send_error && receive_error) ||
+       (send_error && receive_service) ||
+       (send_error && own) ||
+       (send_error && user) ||
+       (send_error && group)) ||
+
+      ((send_service && receive_interface) ||
+       (send_service && receive_member) ||
+       (send_service && receive_error) ||
+       (send_service && receive_service) ||
+       (send_service && own) ||
+       (send_service && user) ||
+       (send_service && group)) ||
+
+      ((receive_interface && receive_error) ||
+       (receive_interface && own) ||
+       (receive_interface && user) ||
+       (receive_interface && group)) ||
+
+      ((receive_member && receive_error) ||
+       (receive_member && own) ||
+       (receive_member && user) ||
+       (receive_member && group)) ||
+
+      ((receive_error && own) ||
+       (receive_error && user) ||
+       (receive_error && group)) ||
+
+      ((own && user) ||
+       (own && group)) ||
 
-      (user && group))
+      ((user && group)))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "Invalid combination of attributes on element <%s>, "
-                      "only send/send_to or receive/receive_from may be paired",
+                      "only send_foo/send_service or receive_foo/receive_service may be paired",
                       element_name);
       return FALSE;
     }
-
+       
   rule = NULL;
 
   /* In BusPolicyRule, NULL represents wildcard.
@@ -887,41 +946,60 @@ append_rule_from_element (BusConfigParser   *parser,
    */
 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
 
-  if (send || send_to)
+  if (send_interface || send_member || send_error || send_service)
     {
       rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); 
       if (rule == NULL)
         goto nomem;
-
-      if (IS_WILDCARD (send))
-        send = NULL;
-      if (IS_WILDCARD (send_to))
-        send_to = NULL;
       
-      rule->d.send.message_name = _dbus_strdup (send);
-      rule->d.send.destination = _dbus_strdup (send_to);
-      if (send && rule->d.send.message_name == NULL)
+      if (IS_WILDCARD (send_interface))
+        send_interface = NULL;
+      if (IS_WILDCARD (send_member))
+        send_member = NULL;
+      if (IS_WILDCARD (send_error))
+        send_error = NULL;
+      if (IS_WILDCARD (send_service))
+        send_service = NULL;
+      
+      rule->d.send.interface = _dbus_strdup (send_interface);
+      rule->d.send.member = _dbus_strdup (send_member);
+      rule->d.send.error = _dbus_strdup (send_error);
+      rule->d.send.destination = _dbus_strdup (send_service);
+      if (send_interface && rule->d.send.interface == NULL)
+        goto nomem;
+      if (send_member && rule->d.send.member == NULL)
         goto nomem;
-      if (send_to && rule->d.send.destination == NULL)
+      if (send_error && rule->d.send.error == NULL)
+        goto nomem;
+      if (send_service && rule->d.send.destination == NULL)
         goto nomem;
     }
-  else if (receive || receive_from)
+  else if (receive_interface || receive_member || receive_error || receive_service)
     {
       rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); 
       if (rule == NULL)
         goto nomem;
-
-      if (IS_WILDCARD (receive))
-        receive = NULL;
-
-      if (IS_WILDCARD (receive_from))
-        receive_from = NULL;
       
-      rule->d.receive.message_name = _dbus_strdup (receive);
-      rule->d.receive.origin = _dbus_strdup (receive_from);
-      if (receive && rule->d.receive.message_name == NULL)
+      if (IS_WILDCARD (receive_interface))
+        receive_interface = NULL;
+      if (IS_WILDCARD (receive_member))
+        receive_member = NULL;
+      if (IS_WILDCARD (receive_error))
+        receive_error = NULL;
+      if (IS_WILDCARD (receive_service))
+        receive_service = NULL;
+
+      rule->d.receive.interface = _dbus_strdup (receive_interface);
+      rule->d.receive.member = _dbus_strdup (receive_member);
+      rule->d.receive.error = _dbus_strdup (receive_error);
+      rule->d.receive.origin = _dbus_strdup (receive_service);
+      if (receive_interface && rule->d.receive.interface == NULL)
+        goto nomem;
+      if (receive_member && rule->d.receive.member == NULL)
+        goto nomem;
+      if (receive_error && rule->d.receive.error == NULL)
         goto nomem;
-      if (receive_from && rule->d.receive.origin == NULL)
+      if (receive_service && rule->d.receive.origin == NULL)
         goto nomem;
     }
   else if (own)
index e588039..4df00bf 100644 (file)
@@ -972,10 +972,10 @@ bus_connection_preallocate_oom_error (DBusConnection *connection)
     }
 
   /* d->name may be NULL, but that is OK */
-  if (!dbus_message_set_name (message, DBUS_ERROR_NO_MEMORY) ||
+  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_DBUS))
+                                DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
     {
       dbus_connection_free_preallocated_send (connection, preallocated);
       dbus_message_unref (message);
@@ -1312,10 +1312,15 @@ 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
@@ -1337,11 +1342,16 @@ bus_transaction_send (BusTransaction *transaction,
   BusConnectionData *d;
   DBusList *link;
 
-  _dbus_verbose ("  trying to add %s %s to transaction%s\n",
+  _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)");
 
index e8f0c9b..934619f 100644 (file)
@@ -104,7 +104,7 @@ static DBusHandlerResult
 bus_dispatch (DBusConnection *connection,
               DBusMessage    *message)
 {
-  const char *sender, *service_name, *message_name;
+  const char *sender, *service_name;
   DBusError error;
   BusTransaction *transaction;
   BusContext *context;
@@ -126,14 +126,24 @@ bus_dispatch (DBusConnection *connection,
   
   /* Ref connection in case we disconnect it at some point in here */
   dbus_connection_ref (connection);
-
+  
   service_name = dbus_message_get_destination (message);
-  message_name = dbus_message_get_name (message);
-
-  _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
 
-  _dbus_verbose ("DISPATCH: %s to %s\n",
-                 message_name, service_name ? service_name : "peer");
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    const char *interface_name, *member_name, *error_name;
+
+    interface_name = dbus_message_get_interface (message);
+    member_name = dbus_message_get_member (message);
+    error_name = dbus_message_get_error_name (message);
+    
+    _dbus_verbose ("DISPATCH: %s %s %s to %s\n",
+                   interface_name ? interface_name : "(no interface)",
+                   member_name ? member_name : "(no member)",
+                   error_name ? error_name : "(no error name)",
+                   service_name ? service_name : "peer");
+  }
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
   
   /* If service_name is NULL, this is a message to the bus daemon, not
    * intended to actually go "on the bus"; e.g. a peer-to-peer
@@ -142,7 +152,8 @@ bus_dispatch (DBusConnection *connection,
    */
   if (service_name == NULL)
     {      
-      if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
+      if (dbus_message_has_interface (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL) &&
+          dbus_message_has_member (message, "Disconnect"))
         bus_connection_disconnected (connection);
 
       /* DBusConnection also handles some of these automatically, we leave
@@ -182,7 +193,7 @@ bus_dispatch (DBusConnection *connection,
       service_name = dbus_message_get_destination (message);
     }
 
-  if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
+  if (strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) /* to bus driver */
     {
       if (!bus_context_check_security_policy (context,
                                               connection, NULL, message, &error))
@@ -191,7 +202,7 @@ bus_dispatch (DBusConnection *connection,
           goto out;
         }
 
-      _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
+      _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
       if (!bus_driver_handle_message (connection, transaction, message, &error))
         goto out;
     }
@@ -679,7 +690,7 @@ check_hello_message (BusContext     *context,
   message = NULL;
   
   message = dbus_message_new_method_call (DBUS_MESSAGE_HELLO,
-                                          DBUS_SERVICE_DBUS);
+                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
 
   if (message == NULL)
     return TRUE;
@@ -721,7 +732,7 @@ check_hello_message (BusContext     *context,
   _dbus_verbose ("Received %s on %p\n",
                  dbus_message_get_name (message), connection);
 
-  if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+  if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
     {
       _dbus_warn ("Message has wrong sender %s\n",
                   dbus_message_get_sender (message) ?
@@ -911,7 +922,7 @@ check_nonexistent_service_activation (BusContext     *context,
   dbus_error_init (&error);
   
   message = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE,
-                                          DBUS_SERVICE_DBUS);
+                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
 
   if (message == NULL)
     return TRUE;
@@ -959,7 +970,7 @@ check_nonexistent_service_activation (BusContext     *context,
 
   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
     {
-      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
         {
           _dbus_warn ("Message has wrong sender %s\n",
                       dbus_message_get_sender (message) ?
@@ -1465,7 +1476,7 @@ check_existent_service_activation (BusContext     *context,
   dbus_error_init (&error);
   
   message = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE,
-                                          DBUS_SERVICE_DBUS);
+                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
 
   if (message == NULL)
     return TRUE;
@@ -1519,7 +1530,7 @@ check_existent_service_activation (BusContext     *context,
 
   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
     {
-      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
         {
           _dbus_warn ("Message has wrong sender %s\n",
                       dbus_message_get_sender (message) ?
@@ -1673,7 +1684,7 @@ check_segfault_service_activation (BusContext     *context,
   dbus_error_init (&error);
   
   message = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE,
-                                          DBUS_SERVICE_DBUS);
+                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
 
   if (message == NULL)
     return TRUE;
@@ -1722,7 +1733,7 @@ check_segfault_service_activation (BusContext     *context,
 
   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
     {
-      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
         {
           _dbus_warn ("Message has wrong sender %s\n",
                       dbus_message_get_sender (message) ?
index 2f8e2ca..3b3ceb4 100644 (file)
@@ -80,11 +80,15 @@ bus_policy_rule_unref (BusPolicyRule *rule)
       switch (rule->type)
         {
         case BUS_POLICY_RULE_SEND:
-          dbus_free (rule->d.send.message_name);
+          dbus_free (rule->d.send.interface);
+          dbus_free (rule->d.send.member);
+          dbus_free (rule->d.send.error);
           dbus_free (rule->d.send.destination);
           break;
         case BUS_POLICY_RULE_RECEIVE:
-          dbus_free (rule->d.receive.message_name);
+          dbus_free (rule->d.receive.interface);
+          dbus_free (rule->d.receive.member);
+          dbus_free (rule->d.receive.error);
           dbus_free (rule->d.receive.origin);
           break;
         case BUS_POLICY_RULE_OWN:
@@ -680,8 +684,8 @@ bus_client_policy_optimize (BusClientPolicy *policy)
 
   /* The idea here is that if we have:
    * 
-   * <allow send="foo"/>
-   * <deny send="*"/>
+   * <allow send_interface="foo.bar"/>
+   * <deny send_interface="*"/>
    *
    * (for example) the deny will always override the allow.  So we
    * delete the allow. Ditto for deny followed by allow, etc. This is
@@ -713,12 +717,16 @@ bus_client_policy_optimize (BusClientPolicy *policy)
         {
         case BUS_POLICY_RULE_SEND:
           remove_preceding =
-            rule->d.send.message_name == NULL &&
+            rule->d.send.interface == NULL &&
+            rule->d.send.member == NULL &&
+            rule->d.send.error == NULL &&
             rule->d.send.destination == NULL;
           break;
         case BUS_POLICY_RULE_RECEIVE:
           remove_preceding =
-            rule->d.receive.message_name == NULL &&
+            rule->d.receive.interface == NULL &&
+            rule->d.receive.member == NULL &&
+            rule->d.receive.error == NULL &&
             rule->d.receive.origin == NULL;
           break;
         case BUS_POLICY_RULE_OWN:
@@ -791,16 +799,34 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
           continue;
         }
 
-      if (rule->d.send.message_name != NULL)
+      if (rule->d.send.interface != NULL)
         {
-          if (!dbus_message_has_name (message,
-                                      rule->d.send.message_name))
+          if (!dbus_message_has_interface (message,
+                                           rule->d.send.interface))
             {
-              _dbus_verbose ("  (policy) skipping rule for different message name\n");
+              _dbus_verbose ("  (policy) skipping rule for different interface\n");
               continue;
             }
         }
-
+      else if (rule->d.send.member != NULL)
+        {
+          if (!dbus_message_has_member (message,
+                                        rule->d.send.member))
+            {
+              _dbus_verbose ("  (policy) skipping rule for different member\n");
+              continue;
+            }
+        }
+      else if (rule->d.send.error != NULL)
+        {
+          if (!dbus_message_has_error_name (message,
+                                            rule->d.send.error))
+            {
+              _dbus_verbose ("  (policy) skipping rule for different error name\n");
+              continue;
+            }
+        }
+      
       if (rule->d.send.destination != NULL)
         {
           /* receiver can be NULL for messages that are sent to the
@@ -886,16 +912,34 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
           continue;
         }
 
-      if (rule->d.receive.message_name != NULL)
+      if (rule->d.receive.interface != NULL)
         {
-          if (!dbus_message_has_name (message,
-                                      rule->d.receive.message_name))
+          if (!dbus_message_has_interface (message,
+                                           rule->d.receive.interface))
             {
-              _dbus_verbose ("  (policy) skipping rule for different message name\n");
+              _dbus_verbose ("  (policy) skipping rule for different interface\n");
               continue;
             }
         }
-
+      else if (rule->d.receive.member != NULL)
+        {
+          if (!dbus_message_has_member (message,
+                                        rule->d.receive.member))
+            {
+              _dbus_verbose ("  (policy) skipping rule for different member\n");
+              continue;
+            }
+        }
+      else if (rule->d.receive.error != NULL)
+        {
+          if (!dbus_message_has_error_name (message,
+                                            rule->d.receive.error))
+            {
+              _dbus_verbose ("  (policy) skipping rule for different error name\n");
+              continue;
+            }
+        }
+      
       if (rule->d.receive.origin != NULL)
         {          
           /* sender can be NULL for messages that originate from the
index 940085e..2aa69aa 100644 (file)
@@ -54,15 +54,19 @@ struct BusPolicyRule
   {
     struct
     {
-      /* either can be NULL meaning "any" */
-      char *message_name;
+      /* any of these can be NULL meaning "any" */
+      char *interface;
+      char *member;
+      char *error;
       char *destination;
     } send;
 
     struct
     {
-      /* either can be NULL meaning "any" */
-      char *message_name;
+      /* any of these can be NULL meaning "any" */
+      char *interface;
+      char *member;
+      char *error;
       char *origin;
     } receive;
 
index 214978d..445606e 100644 (file)
  * @ingroup DBus
  * @brief Functions for communicating with the message bus
  *
+ *
+ * @todo get rid of most of these; they should be done
+ * with DBusGProxy and the Qt equivalent, i.e. the same
+ * way any other interface would be used.
  */
 
 
@@ -398,8 +402,9 @@ dbus_bus_register (DBusConnection *connection,
       return TRUE;
     }
   
-  message = dbus_message_new_method_call (DBUS_MESSAGE_HELLO,
-                                          DBUS_SERVICE_DBUS);
+  message = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "Hello",
+                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
                              
 
   if (!message)
@@ -516,9 +521,9 @@ dbus_bus_acquire_service (DBusConnection *connection,
   _dbus_return_val_if_fail (service_name != NULL, 0);
   _dbus_return_val_if_error_is_set (error, 0);
   
-  message = dbus_message_new_method_call (DBUS_MESSAGE_ACQUIRE_SERVICE,
-                                          DBUS_SERVICE_DBUS);
-
+  message = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "AcquireService",
+                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
 
   if (message == NULL)
     {
@@ -590,8 +595,9 @@ dbus_bus_service_exists (DBusConnection *connection,
   _dbus_return_val_if_fail (service_name != NULL, FALSE);
   _dbus_return_val_if_error_is_set (error, FALSE);
   
-  message = dbus_message_new_method_call (DBUS_MESSAGE_SERVICE_EXISTS,
-                                          DBUS_SERVICE_DBUS);
+  message = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "ServiceExists",
+                                          DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
   if (message == NULL)
     {
       _DBUS_SET_OOM (error);
@@ -652,8 +658,9 @@ dbus_bus_activate_service (DBusConnection *connection,
   DBusMessage *msg;
   DBusMessage *reply;
 
-  msg = dbus_message_new_method_call (DBUS_MESSAGE_ACTIVATE_SERVICE,
-                                      DBUS_SERVICE_DBUS);
+  msg = dbus_message_new_method_call (DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                      "ActivateService",
+                                      DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
 
   if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, service_name,
                                 DBUS_TYPE_UINT32, flags, DBUS_TYPE_INVALID))
index bc26a3e..7be35b4 100644 (file)
@@ -296,9 +296,11 @@ _dbus_connection_queue_received_message_link (DBusConnection  *connection,
 
   _dbus_connection_wakeup_mainloop (connection);
   
-  _dbus_assert (dbus_message_get_name (message) != NULL);
   _dbus_verbose ("Message %p (%s) added to incoming queue %p, %d incoming\n",
-                 message, dbus_message_get_name (message),
+                 message,
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
                  connection,
                  connection->n_incoming);
 }
@@ -381,7 +383,10 @@ _dbus_connection_message_sent (DBusConnection *connection,
   connection->n_outgoing -= 1;
 
   _dbus_verbose ("Message %p (%s) removed from outgoing queue %p, %d left to send\n",
-                 message, dbus_message_get_name (message),
+                 message,
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
                  connection, connection->n_outgoing);
 
   /* Save this link in the link cache also */
@@ -820,7 +825,9 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
   if (io_path_cond == NULL)
     goto error;
 
-  disconnect_message = dbus_message_new_signal (DBUS_MESSAGE_LOCAL_DISCONNECT);
+  disconnect_message = dbus_message_new_signal (DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
+                                                "Disconnect");
+  
   if (disconnect_message == NULL)
     goto error;
 
@@ -1482,7 +1489,9 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection       *connection,
 
   _dbus_verbose ("Message %p (%s) added to outgoing queue %p, %d pending to send\n",
                  message,
-                 dbus_message_get_name (message),
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
                  connection,
                  connection->n_outgoing);
 
@@ -1530,7 +1539,12 @@ dbus_connection_send_preallocated (DBusConnection       *connection,
   _dbus_return_if_fail (preallocated != NULL);
   _dbus_return_if_fail (message != NULL);
   _dbus_return_if_fail (preallocated->connection == connection);
-  _dbus_return_if_fail (dbus_message_get_name (message) != NULL);
+  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
+                        (dbus_message_get_interface (message) != NULL &&
+                         dbus_message_get_member (message) != NULL));
+  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
+                        (dbus_message_get_interface (message) != NULL &&
+                         dbus_message_get_member (message) != NULL));
   
   CONNECTION_LOCK (connection);
   _dbus_connection_send_preallocated_unlocked (connection,
@@ -1854,8 +1868,7 @@ _dbus_connection_block_for_reply (DBusConnection     *connection,
         {          
           status = _dbus_connection_get_dispatch_status_unlocked (connection);
 
-          _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply %s\n",
-                         dbus_message_get_name (reply));
+          _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
 
           /* Unlocks, and calls out to user code */
           _dbus_connection_update_dispatch_status_and_unlock (connection, status);
@@ -2148,7 +2161,10 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
       connection->n_incoming -= 1;
 
       _dbus_verbose ("Message %p (%s) removed from incoming queue %p, %d incoming\n",
-                     link->data, dbus_message_get_name (link->data),
+                     link->data,
+                     dbus_message_get_interface (link->data) ?
+                     dbus_message_get_interface (link->data) :
+                     "no interface",
                      connection, connection->n_incoming);
 
       return link;
@@ -2194,7 +2210,10 @@ _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
   connection->n_incoming += 1;
 
   _dbus_verbose ("Message %p (%s) put back into queue %p, %d incoming\n",
-                 message_link->data, dbus_message_get_name (message_link->data),
+                 message_link->data,
+                 dbus_message_get_interface (message_link->data) ?
+                 dbus_message_get_interface (message_link->data) :
+                 "no interface",
                  connection, connection->n_incoming);
 }
 
@@ -2523,7 +2542,10 @@ dbus_connection_dispatch (DBusConnection *connection)
    * since we acquired the dispatcher
    */
   _dbus_verbose ("  running object handler on message %p (%s)\n",
-                 message, dbus_message_get_name (message));
+                 message,
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface");
   
   result = _dbus_object_registry_handle_and_unlock (connection->objects,
                                                     message);
@@ -2549,8 +2571,9 @@ dbus_connection_dispatch (DBusConnection *connection)
         }
               
       if (!_dbus_string_append_printf (&str,
-                                       "Method \"%s\" doesn't exist\n",
-                                       dbus_message_get_name (message)))
+                                       "Method \"%s\" on interface \"%s\" doesn't exist\n",
+                                       dbus_message_get_member (message),
+                                       dbus_message_get_interface (message)))
         {
           _dbus_string_free (&str);
           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
@@ -2586,7 +2609,10 @@ dbus_connection_dispatch (DBusConnection *connection)
     }
   
   _dbus_verbose ("  done dispatching %p (%s) on connection %p\n", message,
-                 dbus_message_get_name (message), connection);
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
+                 connection);
   
  out:
   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
index 2c41001..f454781 100644 (file)
@@ -221,26 +221,32 @@ typedef struct
   int n_entries_on_init;     /**< used to detect table resize since initialization */
 } DBusRealHashIter;
 
-static DBusHashEntry* find_direct_function (DBusHashTable          *table,
-                                            void                   *key,
-                                            dbus_bool_t             create_if_not_found,
-                                            DBusHashEntry        ***bucket,
-                                            DBusPreallocatedHash   *preallocated);
-static DBusHashEntry* find_string_function (DBusHashTable          *table,
-                                            void                   *key,
-                                            dbus_bool_t             create_if_not_found,
-                                            DBusHashEntry        ***bucket,
-                                            DBusPreallocatedHash   *preallocated);
-static unsigned int   string_hash          (const char             *str);
-static void           rebuild_table        (DBusHashTable          *table);
-static DBusHashEntry* alloc_entry          (DBusHashTable          *table);
-static void           remove_entry         (DBusHashTable          *table,
-                                            DBusHashEntry         **bucket,
-                                            DBusHashEntry          *entry);
-static void           free_entry           (DBusHashTable          *table,
-                                            DBusHashEntry          *entry);
-static void           free_entry_data      (DBusHashTable          *table,
-                                            DBusHashEntry          *entry);
+static DBusHashEntry* find_direct_function      (DBusHashTable          *table,
+                                                 void                   *key,
+                                                 dbus_bool_t             create_if_not_found,
+                                                 DBusHashEntry        ***bucket,
+                                                 DBusPreallocatedHash   *preallocated);
+static DBusHashEntry* find_string_function      (DBusHashTable          *table,
+                                                 void                   *key,
+                                                 dbus_bool_t             create_if_not_found,
+                                                 DBusHashEntry        ***bucket,
+                                                 DBusPreallocatedHash   *preallocated);
+static DBusHashEntry* find_two_strings_function (DBusHashTable          *table,
+                                                 void                   *key,
+                                                 dbus_bool_t             create_if_not_found,
+                                                 DBusHashEntry        ***bucket,
+                                                 DBusPreallocatedHash   *preallocated);
+static unsigned int   string_hash               (const char             *str);
+static unsigned int   two_strings_hash          (const char             *str);
+static void           rebuild_table             (DBusHashTable          *table);
+static DBusHashEntry* alloc_entry               (DBusHashTable          *table);
+static void           remove_entry              (DBusHashTable          *table,
+                                                 DBusHashEntry         **bucket,
+                                                 DBusHashEntry          *entry);
+static void           free_entry                (DBusHashTable          *table,
+                                                 DBusHashEntry          *entry);
+static void           free_entry_data           (DBusHashTable          *table,
+                                                 DBusHashEntry          *entry);
 
 
 /** @} */
@@ -323,6 +329,9 @@ _dbus_hash_table_new (DBusHashType     type,
     case DBUS_HASH_STRING:
       table->find_function = find_string_function;
       break;
+    case DBUS_HASH_TWO_STRINGS:
+      table->find_function = find_two_strings_function;
+      break;
     default:
       _dbus_assert_not_reached ("Unknown hash table type");
       break;
@@ -685,6 +694,24 @@ _dbus_hash_iter_get_string_key (DBusHashIter *iter)
 }
 
 /**
+ * Gets the key for the current entry.
+ * Only works for hash tables of type #DBUS_HASH_TWO_STRINGS
+ * @param iter the hash table iterator.
+ */
+const char*
+_dbus_hash_iter_get_two_strings_key (DBusHashIter *iter)
+{
+  DBusRealHashIter *real;
+
+  real = (DBusRealHashIter*) iter;
+
+  _dbus_assert (real->table != NULL);
+  _dbus_assert (real->entry != NULL);
+
+  return real->entry->key;
+}
+
+/**
  * A low-level but efficient interface for manipulating the hash
  * table.  It's efficient because you can get, set, and optionally
  * create the hash entry while only running the hash function one
@@ -803,64 +830,63 @@ add_entry (DBusHashTable        *table,
   return entry;
 }
 
+/* This is g_str_hash from GLib which was
+ * extensively discussed/tested/profiled
+ */
 static unsigned int
 string_hash (const char *str)
 {
-  register unsigned int result;
-  register int c;
+  const char *p = str;
+  unsigned int h = *p;
 
-  /*
-   * I tried a zillion different hash functions and asked many other
-   * people for advice.  Many people had their own favorite functions,
-   * all different, but no-one had much idea why they were good ones.
-   * I chose the one below (multiply by 9 and add new character)
-   * because of the following reasons:
-   *
-   * 1. Multiplying by 10 is perfect for keys that are decimal strings,
-   *    and multiplying by 9 is just about as good.
-   * 2. Times-9 is (shift-left-3) plus (old).  This means that each
-   *    character's bits hang around in the low-order bits of the
-   *    hash value for ever, plus they spread fairly rapidly up to
-   *    the high-order bits to fill out the hash value.  This seems
-   *    works well both for decimal and non-decimal strings.
-   */
+  if (h)
+    for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + *p;
 
-  /* FIXME the hash function in GLib is better than this one */
-  
-  result = 0;
-  while (TRUE)
-    {
-      c = *str;
-      str++;
-      if (c == 0)
-        break;
-      
-      result += (result << 3) + c;
-    }
+  return h;
+}
+
+/* This hashes a memory block with two nul-terminated strings
+ * in it, used in dbus-object-registry.c at the moment.
+ */
+static unsigned int
+two_strings_hash (const char *str)
+{
+  const char *p = str;
+  unsigned int h = *p;
+
+  if (h)
+    for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + *p;
+
+  for (p += 1; *p != '\0'; p++)
+    h = (h << 5) - h + *p;
   
-  return result;
+  return h;
 }
 
+typedef int (* KeyCompareFunc) (const void *key_a, const void *key_b);
+
 static DBusHashEntry*
-find_string_function (DBusHashTable        *table,
-                      void                 *key,
-                      dbus_bool_t           create_if_not_found,
-                      DBusHashEntry      ***bucket,
-                      DBusPreallocatedHash *preallocated)
+find_generic_function (DBusHashTable        *table,
+                       void                 *key,
+                       unsigned int          idx,
+                       KeyCompareFunc        compare_func,
+                       dbus_bool_t           create_if_not_found,
+                       DBusHashEntry      ***bucket,
+                       DBusPreallocatedHash *preallocated)
 {
   DBusHashEntry *entry;
-  unsigned int idx;
 
   if (bucket)
     *bucket = NULL;
-  
-  idx = string_hash (key) & table->mask;
 
   /* Search all of the entries in this bucket. */
   entry = table->buckets[idx];
   while (entry != NULL)
     {
-      if (strcmp (key, entry->key) == 0)
+      if ((compare_func == NULL && key == entry->key) ||
+          (compare_func != NULL && (* compare_func) (key, entry->key) == 0))
         {
           if (bucket)
             *bucket = &(table->buckets[idx]);
@@ -878,50 +904,75 @@ find_string_function (DBusHashTable        *table,
     entry = add_entry (table, idx, key, bucket, preallocated);
   else if (preallocated)
     _dbus_hash_table_free_preallocated_entry (table, preallocated);
-
+  
   return entry;
 }
 
 static DBusHashEntry*
-find_direct_function (DBusHashTable        *table,
+find_string_function (DBusHashTable        *table,
                       void                 *key,
                       dbus_bool_t           create_if_not_found,
                       DBusHashEntry      ***bucket,
                       DBusPreallocatedHash *preallocated)
 {
-  DBusHashEntry *entry;
   unsigned int idx;
+  
+  idx = string_hash (key) & table->mask;
 
-  if (bucket)
-    *bucket = NULL;
+  return find_generic_function (table, key, idx,
+                                (KeyCompareFunc) strcmp, create_if_not_found, bucket,
+                                preallocated);
+}
+
+static int
+two_strings_cmp (const char *a,
+                 const char *b)
+{
+  size_t len_a;
+  size_t len_b;
+  int res;
   
-  idx = RANDOM_INDEX (table, key) & table->mask;
+  res = strcmp (a, b);
+  if (res != 0)
+    return res;
 
-  /* Search all of the entries in this bucket. */
-  entry = table->buckets[idx];
-  while (entry != NULL)
-    {
-      if (key == entry->key)
-        {
-          if (bucket)
-            *bucket = &(table->buckets[idx]);
+  len_a = strlen (a);
+  len_b = strlen (b);
 
-          if (preallocated)
-            _dbus_hash_table_free_preallocated_entry (table, preallocated);
-          
-          return entry;
-        }
-      
-      entry = entry->next;
-    }
+  return strcmp (a + len_a + 1, b + len_b + 1);
+}
 
-  /* Entry not found.  Add a new one to the bucket. */
-  if (create_if_not_found)
-    entry = add_entry (table, idx, key, bucket, preallocated);
-  else if (preallocated)
-    _dbus_hash_table_free_preallocated_entry (table, preallocated);
+static DBusHashEntry*
+find_two_strings_function (DBusHashTable        *table,
+                           void                 *key,
+                           dbus_bool_t           create_if_not_found,
+                           DBusHashEntry      ***bucket,
+                           DBusPreallocatedHash *preallocated)
+{
+  unsigned int idx;
+  
+  idx = two_strings_hash (key) & table->mask;
 
-  return entry;
+  return find_generic_function (table, key, idx,
+                                (KeyCompareFunc) two_strings_cmp, create_if_not_found, bucket,
+                                preallocated);
+}
+
+static DBusHashEntry*
+find_direct_function (DBusHashTable        *table,
+                      void                 *key,
+                      dbus_bool_t           create_if_not_found,
+                      DBusHashEntry      ***bucket,
+                      DBusPreallocatedHash *preallocated)
+{
+  unsigned int idx;
+  
+  idx = RANDOM_INDEX (table, key) & table->mask;
+
+
+  return find_generic_function (table, key, idx,
+                                NULL, create_if_not_found, bucket,
+                                preallocated);
 }
 
 static void
@@ -1021,6 +1072,9 @@ rebuild_table (DBusHashTable *table)
             case DBUS_HASH_STRING:
               idx = string_hash (entry->key) & table->mask;
               break;
+            case DBUS_HASH_TWO_STRINGS:
+              idx = two_strings_hash (entry->key) & table->mask;
+              break;
             case DBUS_HASH_INT:
             case DBUS_HASH_ULONG:
             case DBUS_HASH_POINTER:
@@ -1070,6 +1124,31 @@ _dbus_hash_table_lookup_string (DBusHashTable *table,
 }
 
 /**
+ * Looks up the value for a given string in a hash table
+ * of type #DBUS_HASH_TWO_STRINGS. Returns %NULL if the value
+ * is not present. (A not-present entry is indistinguishable
+ * from an entry with a value of %NULL.)
+ * @param table the hash table.
+ * @param key the string to look up.
+ * @returns the value of the hash entry.
+ */
+void*
+_dbus_hash_table_lookup_two_strings (DBusHashTable *table,
+                                     const char    *key)
+{
+  DBusHashEntry *entry;
+
+  _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS);
+  
+  entry = (* table->find_function) (table, (char*) key, FALSE, NULL, NULL);
+
+  if (entry)
+    return entry->value;
+  else
+    return NULL;
+}
+
+/**
  * Looks up the value for a given integer in a hash table
  * of type #DBUS_HASH_INT. Returns %NULL if the value
  * is not present. (A not-present entry is indistinguishable
@@ -1184,6 +1263,34 @@ _dbus_hash_table_remove_string (DBusHashTable *table,
  * @returns #TRUE if the entry existed
  */
 dbus_bool_t
+_dbus_hash_table_remove_two_strings (DBusHashTable *table,
+                                     const char    *key)
+{
+  DBusHashEntry *entry;
+  DBusHashEntry **bucket;
+  
+  _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS);
+  
+  entry = (* table->find_function) (table, (char*) key, FALSE, &bucket, NULL);
+
+  if (entry)
+    {
+      remove_entry (table, bucket, entry);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Removes the hash entry for the given key. If no hash entry
+ * for the key exists, does nothing.
+ *
+ * @param table the hash table.
+ * @param key the hash key.
+ * @returns #TRUE if the entry existed
+ */
+dbus_bool_t
 _dbus_hash_table_remove_int (DBusHashTable *table,
                              int            key)
 {
@@ -1312,6 +1419,40 @@ _dbus_hash_table_insert_string (DBusHashTable *table,
  * @param value the hash entry value.
  */
 dbus_bool_t
+_dbus_hash_table_insert_two_strings (DBusHashTable *table,
+                                     char          *key,
+                                     void          *value)
+{
+  DBusPreallocatedHash *preallocated;
+
+  _dbus_assert (table->key_type == DBUS_HASH_TWO_STRINGS);
+
+  preallocated = _dbus_hash_table_preallocate_entry (table);
+  if (preallocated == NULL)
+    return FALSE;
+
+  _dbus_hash_table_insert_string_preallocated (table, preallocated,
+                                               key, value);
+  
+  return TRUE;
+}
+
+/**
+ * Creates a hash entry with the given key and value.
+ * The key and value are not copied; they are stored
+ * in the hash table by reference. If an entry with the
+ * given key already exists, the previous key and value
+ * are overwritten (and freed if the hash table has
+ * a key_free_function and/or value_free_function).
+ *
+ * Returns #FALSE if memory for the new hash entry
+ * can't be allocated.
+ * 
+ * @param table the hash table.
+ * @param key the hash entry key.
+ * @param value the hash entry value.
+ */
+dbus_bool_t
 _dbus_hash_table_insert_int (DBusHashTable *table,
                              int            key,
                              void          *value)
@@ -1536,6 +1677,28 @@ count_entries (DBusHashTable *table)
   return count;
 }
 
+/* Copy the foo\0bar\0 double string thing */
+static char*
+_dbus_strdup2 (const char *str)
+{
+  size_t len;
+  char *copy;
+  
+  if (str == NULL)
+    return NULL;
+  
+  len = strlen (str);
+  len += strlen ((str + len + 1));
+
+  copy = dbus_malloc (len + 2);
+  if (copy == NULL)
+    return NULL;
+
+  memcpy (copy, str, len + 2);
+  
+  return copy;
+}
+
 /**
  * @ingroup DBusHashTableInternals
  * Unit test for DBusHashTable
@@ -1548,6 +1711,7 @@ _dbus_hash_test (void)
   DBusHashTable *table1;
   DBusHashTable *table2;
   DBusHashTable *table3;
+  DBusHashTable *table4;
   DBusHashIter iter;
 #define N_HASH_KEYS 5000
   char **keys;
@@ -1569,7 +1733,16 @@ _dbus_hash_test (void)
   i = 0;
   while (i < N_HASH_KEYS)
     {
-      sprintf (keys[i], "Hash key %d", i); 
+      int len;
+
+      /* all the hash keys are TWO_STRINGS, but
+       * then we can also use those as regular strings.
+       */
+      
+      len = sprintf (keys[i], "Hash key %d", i);
+      sprintf (keys[i] + len + 1, "Two string %d", i);
+      _dbus_assert (*(keys[i] + len) == '\0');
+      _dbus_assert (*(keys[i] + len + 1) != '\0');
       ++i;
     }
   printf ("... done.\n");
@@ -1588,6 +1761,12 @@ _dbus_hash_test (void)
                                  NULL, dbus_free);
   if (table3 == NULL)
     goto out;
+
+  table4 = _dbus_hash_table_new (DBUS_HASH_TWO_STRINGS,
+                                 dbus_free, dbus_free);
+  if (table4 == NULL)
+    goto out;
+
   
   /* Insert and remove a bunch of stuff, counting the table in between
    * to be sure it's not broken and that iteration works
@@ -1624,10 +1803,22 @@ _dbus_hash_test (void)
       if (!_dbus_hash_table_insert_ulong (table3,
                                           i, value))
         goto out;
+
+      key = _dbus_strdup2 (keys[i]);
+      if (key == NULL)
+        goto out;
+      value = _dbus_strdup ("Value!");
+      if (value == NULL)
+        goto out;
+      
+      if (!_dbus_hash_table_insert_string (table4,
+                                           key, value))
+        goto out;
       
       _dbus_assert (count_entries (table1) == i + 1);
       _dbus_assert (count_entries (table2) == i + 1);
       _dbus_assert (count_entries (table3) == i + 1);
+      _dbus_assert (count_entries (table4) == i + 1);
 
       value = _dbus_hash_table_lookup_string (table1, keys[i]);
       _dbus_assert (value != NULL);
@@ -1640,6 +1831,10 @@ _dbus_hash_test (void)
       value = _dbus_hash_table_lookup_ulong (table3, i);
       _dbus_assert (value != NULL);
       _dbus_assert (strcmp (value, keys[i]) == 0);
+
+      value = _dbus_hash_table_lookup_ulong (table4, i);
+      _dbus_assert (value != NULL);
+      _dbus_assert (strcmp (value, keys[i]) == 0);
       
       ++i;
     }
@@ -1654,9 +1849,13 @@ _dbus_hash_test (void)
 
       _dbus_hash_table_remove_ulong (table3, i); 
 
+      _dbus_hash_table_remove_two_strings (table4,
+                                           keys[i]);
+      
       _dbus_assert (count_entries (table1) == i);
       _dbus_assert (count_entries (table2) == i);
       _dbus_assert (count_entries (table3) == i);
+      _dbus_assert (count_entries (table4) == i);
 
       --i;
     }
@@ -1664,12 +1863,15 @@ _dbus_hash_test (void)
   _dbus_hash_table_ref (table1);
   _dbus_hash_table_ref (table2);
   _dbus_hash_table_ref (table3);
+  _dbus_hash_table_ref (table4);
   _dbus_hash_table_unref (table1);
   _dbus_hash_table_unref (table2);
   _dbus_hash_table_unref (table3);
+  _dbus_hash_table_unref (table4);
   _dbus_hash_table_unref (table1);
   _dbus_hash_table_unref (table2);
   _dbus_hash_table_unref (table3);
+  _dbus_hash_table_unref (table4);
   table3 = NULL;
 
   /* Insert a bunch of stuff then check
index 566d402..25b81dd 100644 (file)
@@ -52,61 +52,68 @@ typedef struct DBusHashIter  DBusHashIter;
  */
 typedef enum
 {
-  DBUS_HASH_STRING,  /**< Hash keys are strings. */
-  DBUS_HASH_INT,     /**< Hash keys are integers. */
-  DBUS_HASH_POINTER, /**< Hash keys are pointers. */
-  DBUS_HASH_ULONG    /**< Hash keys are unsigned long. */
+  DBUS_HASH_STRING,        /**< Hash keys are strings. */
+  DBUS_HASH_TWO_STRINGS,   /**< Hash key is two strings in one memory block, i.e. foo\0bar\0 */
+  DBUS_HASH_INT,           /**< Hash keys are integers. */
+  DBUS_HASH_POINTER,       /**< Hash keys are pointers. */
+  DBUS_HASH_ULONG          /**< Hash keys are unsigned long. */
 } DBusHashType;
-
-DBusHashTable* _dbus_hash_table_new            (DBusHashType      type,
-                                                DBusFreeFunction  key_free_function,
-                                                DBusFreeFunction  value_free_function);
-void           _dbus_hash_table_ref            (DBusHashTable    *table);
-void           _dbus_hash_table_unref          (DBusHashTable    *table);
-void           _dbus_hash_iter_init            (DBusHashTable    *table,
-                                                DBusHashIter     *iter);
-dbus_bool_t    _dbus_hash_iter_next            (DBusHashIter     *iter);
-void           _dbus_hash_iter_remove_entry    (DBusHashIter     *iter);
-void*          _dbus_hash_iter_get_value       (DBusHashIter     *iter);
-void           _dbus_hash_iter_set_value       (DBusHashIter     *iter,
-                                                void             *value);
-int            _dbus_hash_iter_get_int_key     (DBusHashIter     *iter);
-const char*    _dbus_hash_iter_get_string_key  (DBusHashIter     *iter);
-unsigned long  _dbus_hash_iter_get_ulong_key   (DBusHashIter     *iter);
-dbus_bool_t    _dbus_hash_iter_lookup          (DBusHashTable    *table,
-                                                void             *key,
-                                                dbus_bool_t       create_if_not_found,
-                                                DBusHashIter     *iter);
-void*          _dbus_hash_table_lookup_string  (DBusHashTable    *table,
-                                                const char       *key);
-void*          _dbus_hash_table_lookup_int     (DBusHashTable    *table,
-                                                int               key);
-void*          _dbus_hash_table_lookup_pointer (DBusHashTable    *table,
-                                                void             *key);
-void*          _dbus_hash_table_lookup_ulong   (DBusHashTable    *table,
-                                                unsigned long     key);
-dbus_bool_t    _dbus_hash_table_remove_string  (DBusHashTable    *table,
-                                                const char       *key);
-dbus_bool_t    _dbus_hash_table_remove_int     (DBusHashTable    *table,
-                                                int               key);
-dbus_bool_t    _dbus_hash_table_remove_pointer (DBusHashTable    *table,
-                                                void             *key);
-dbus_bool_t    _dbus_hash_table_remove_ulong   (DBusHashTable    *table,
-                                                unsigned long     key);
-dbus_bool_t    _dbus_hash_table_insert_string  (DBusHashTable    *table,
-                                                char             *key,
-                                                void             *value);
-dbus_bool_t    _dbus_hash_table_insert_int     (DBusHashTable    *table,
-                                                int               key,
-                                                void             *value);
-dbus_bool_t    _dbus_hash_table_insert_pointer (DBusHashTable    *table,
-                                                void             *key,
-                                                void             *value);
-dbus_bool_t    _dbus_hash_table_insert_ulong   (DBusHashTable    *table,
-                                                unsigned long     key,
-                                                void             *value);
-int            _dbus_hash_table_get_n_entries  (DBusHashTable    *table);
-
+DBusHashTable* _dbus_hash_table_new                (DBusHashType      type,
+                                                    DBusFreeFunction  key_free_function,
+                                                    DBusFreeFunction  value_free_function);
+void           _dbus_hash_table_ref                (DBusHashTable    *table);
+void           _dbus_hash_table_unref              (DBusHashTable    *table);
+void           _dbus_hash_iter_init                (DBusHashTable    *table,
+                                                    DBusHashIter     *iter);
+dbus_bool_t    _dbus_hash_iter_next                (DBusHashIter     *iter);
+void           _dbus_hash_iter_remove_entry        (DBusHashIter     *iter);
+void*          _dbus_hash_iter_get_value           (DBusHashIter     *iter);
+void           _dbus_hash_iter_set_value           (DBusHashIter     *iter,
+                                                    void             *value);
+int            _dbus_hash_iter_get_int_key         (DBusHashIter     *iter);
+const char*    _dbus_hash_iter_get_string_key      (DBusHashIter     *iter);
+const char*    _dbus_hash_iter_get_two_strings_key (DBusHashIter     *iter);
+unsigned long  _dbus_hash_iter_get_ulong_key       (DBusHashIter     *iter);
+dbus_bool_t    _dbus_hash_iter_lookup              (DBusHashTable    *table,
+                                                    void             *key,
+                                                    dbus_bool_t       create_if_not_found,
+                                                    DBusHashIter     *iter);
+void*          _dbus_hash_table_lookup_string      (DBusHashTable    *table,
+                                                    const char       *key);
+void*          _dbus_hash_table_lookup_two_strings (DBusHashTable    *table,
+                                                    const char       *key);
+void*          _dbus_hash_table_lookup_int         (DBusHashTable    *table,
+                                                    int               key);
+void*          _dbus_hash_table_lookup_pointer     (DBusHashTable    *table,
+                                                    void             *key);
+void*          _dbus_hash_table_lookup_ulong       (DBusHashTable    *table,
+                                                    unsigned long     key);
+dbus_bool_t    _dbus_hash_table_remove_string      (DBusHashTable    *table,
+                                                    const char       *key);
+dbus_bool_t    _dbus_hash_table_remove_two_strings (DBusHashTable    *table,
+                                                    const char       *key);
+dbus_bool_t    _dbus_hash_table_remove_int         (DBusHashTable    *table,
+                                                    int               key);
+dbus_bool_t    _dbus_hash_table_remove_pointer     (DBusHashTable    *table,
+                                                    void             *key);
+dbus_bool_t    _dbus_hash_table_remove_ulong       (DBusHashTable    *table,
+                                                    unsigned long     key);
+dbus_bool_t    _dbus_hash_table_insert_string      (DBusHashTable    *table,
+                                                    char             *key,
+                                                    void             *value);
+dbus_bool_t    _dbus_hash_table_insert_two_strings (DBusHashTable    *table,
+                                                    char             *key,
+                                                    void             *value);
+dbus_bool_t    _dbus_hash_table_insert_int         (DBusHashTable    *table,
+                                                    int               key,
+                                                    void             *value);
+dbus_bool_t    _dbus_hash_table_insert_pointer     (DBusHashTable    *table,
+                                                    void             *key,
+                                                    void             *value);
+dbus_bool_t    _dbus_hash_table_insert_ulong       (DBusHashTable    *table,
+                                                    unsigned long     key,
+                                                    void             *value);
+int            _dbus_hash_table_get_n_entries      (DBusHashTable    *table);
 
 /* Preallocation */
 typedef struct DBusPreallocatedHash DBusPreallocatedHash;
index 5f3d01e..e5bbcab 100644 (file)
@@ -47,7 +47,9 @@ enum
   FIELD_HEADER_LENGTH,
   FIELD_BODY_LENGTH,
   FIELD_CLIENT_SERIAL,
-  FIELD_NAME,
+  FIELD_INTERFACE,
+  FIELD_MEMBER,
+  FIELD_ERROR_NAME,
   FIELD_SERVICE,
   FIELD_SENDER,
   FIELD_REPLY_SERIAL,
@@ -60,7 +62,9 @@ static dbus_bool_t field_is_named[FIELD_LAST] =
   FALSE, /* FIELD_HEADER_LENGTH */
   FALSE, /* FIELD_BODY_LENGTH */
   FALSE, /* FIELD_CLIENT_SERIAL */
-  TRUE,  /* FIELD_NAME */
+  TRUE,  /* FIELD_INTERFACE */
+  TRUE,  /* FIELD_MEMBER */
+  TRUE,  /* FIELD_ERROR_NAME */
   TRUE,  /* FIELD_SERVICE */
   TRUE,  /* FIELD_SENDER */
   TRUE   /* FIELD_REPLY_SERIAL */
@@ -593,9 +597,17 @@ set_string_field (DBusMessage *message,
           return append_string_field (message, field,
                                       DBUS_HEADER_FIELD_SENDER,
                                       value);
-        case FIELD_NAME:
+        case FIELD_INTERFACE:
           return append_string_field (message, field,
-                                      DBUS_HEADER_FIELD_NAME,
+                                      DBUS_HEADER_FIELD_INTERFACE,
+                                      value);
+        case FIELD_MEMBER:
+          return append_string_field (message, field,
+                                      DBUS_HEADER_FIELD_MEMBER,
+                                      value);
+        case FIELD_ERROR_NAME:
+          return append_string_field (message, field,
+                                      DBUS_HEADER_FIELD_ERROR_NAME,
                                       value);
         case FIELD_SERVICE:
           return append_string_field (message, field,
@@ -817,10 +829,16 @@ _dbus_message_remove_size_counter (DBusMessage  *message,
 static dbus_bool_t
 dbus_message_create_header (DBusMessage *message,
                             int          type,
-                            const char  *name,
+                            const char  *interface,
+                            const char  *member,
+                            const char  *error_name,
                             const char  *service)
 {
   unsigned int flags;
+
+  _dbus_assert ((interface && member) ||
+                (error_name) ||
+                !(interface || member || error_name));
   
   if (!_dbus_string_append_byte (&message->header, message->byte_order))
     return FALSE;
@@ -857,12 +875,30 @@ dbus_message_create_header (DBusMessage *message,
         return FALSE;
     }
 
-  if (name != NULL)
+  if (interface != NULL)
+    {
+      if (!append_string_field (message,
+                                FIELD_INTERFACE,
+                                DBUS_HEADER_FIELD_INTERFACE,
+                                interface))
+        return FALSE;
+    }
+
+  if (member != NULL)
     {
       if (!append_string_field (message,
-                                FIELD_NAME,
-                                DBUS_HEADER_FIELD_NAME,
-                                name))
+                                FIELD_MEMBER,
+                                DBUS_HEADER_FIELD_MEMBER,
+                                member))
+        return FALSE;
+    }
+
+  if (error_name != NULL)
+    {
+      if (!append_string_field (message,
+                                FIELD_ERROR_NAME,
+                                DBUS_HEADER_FIELD_ERROR_NAME,
+                                error_name))
         return FALSE;
     }
   
@@ -979,7 +1015,7 @@ dbus_message_new (int message_type)
   
   if (!dbus_message_create_header (message,
                                    message_type,
-                                   NULL, NULL))
+                                   NULL, NULL, NULL, NULL))
     {
       dbus_message_unref (message);
       return NULL;
@@ -995,18 +1031,21 @@ dbus_message_new (int message_type)
  * this is appropriate when using D-BUS in a peer-to-peer context (no
  * message bus).
  *
- * @param name name of the message
+ * @param interface interface to invoke method on
+ * @param method method to invoke
  * @param destination_service service that the message should be sent to or #NULL
  * @returns a new DBusMessage, free with dbus_message_unref()
  * @see dbus_message_unref()
  */
 DBusMessage*
-dbus_message_new_method_call (const char *name,
+dbus_message_new_method_call (const char *interface,
+                              const char *method,
                               const char *destination_service)           
 {
   DBusMessage *message;
 
-  _dbus_return_val_if_fail (name != NULL, NULL);
+  _dbus_return_val_if_fail (interface != NULL, NULL);
+  _dbus_return_val_if_fail (method != NULL, NULL);
   
   message = dbus_message_new_empty_header ();
   if (message == NULL)
@@ -1014,7 +1053,7 @@ dbus_message_new_method_call (const char *name,
   
   if (!dbus_message_create_header (message,
                                    DBUS_MESSAGE_TYPE_METHOD_CALL,
-                                   name, destination_service))
+                                   interface, method, NULL, destination_service))
     {
       dbus_message_unref (message);
       return NULL;
@@ -1036,14 +1075,12 @@ DBusMessage*
 dbus_message_new_method_return (DBusMessage *method_call)
 {
   DBusMessage *message;
-  const char *sender, *name;
+  const char *sender;
 
   _dbus_return_val_if_fail (method_call != NULL, NULL);
   
   sender = get_string_field (method_call,
                              FIELD_SENDER, NULL);
-  name = get_string_field (method_call,
-                          FIELD_NAME, NULL);
 
   /* sender is allowed to be null here in peer-to-peer case */
 
@@ -1053,7 +1090,7 @@ dbus_message_new_method_return (DBusMessage *method_call)
   
   if (!dbus_message_create_header (message,
                                    DBUS_MESSAGE_TYPE_METHOD_RETURN,
-                                   name, sender))
+                                   NULL, NULL, NULL, sender))
     {
       dbus_message_unref (message);
       return NULL;
@@ -1071,15 +1108,18 @@ dbus_message_new_method_return (DBusMessage *method_call)
 
 /**
  * Constructs a new message representing a signal emission. Returns
- * #NULL if memory can't be allocated for the message. The name
- * passed in is the name of the signal.
+ * #NULL if memory can't be allocated for the message.
+ * A signal is identified by its originating interface, and
+ * the name of the signal.
  *
+ * @param interface the interface the signal is emitted from
  * @param name name of the signal
  * @returns a new DBusMessage, free with dbus_message_unref()
  * @see dbus_message_unref()
  */
 DBusMessage*
-dbus_message_new_signal (const char *name)
+dbus_message_new_signal (const char *interface,
+                         const char *name)
 {
   DBusMessage *message;
 
@@ -1091,7 +1131,7 @@ dbus_message_new_signal (const char *name)
   
   if (!dbus_message_create_header (message,
                                    DBUS_MESSAGE_TYPE_SIGNAL,
-                                   name, NULL))
+                                   interface, name, NULL, NULL))
     {
       dbus_message_unref (message);
       return NULL;
@@ -1134,7 +1174,7 @@ dbus_message_new_error (DBusMessage *reply_to,
   
   if (!dbus_message_create_header (message,
                                    DBUS_MESSAGE_TYPE_ERROR,
-                                   error_name, sender))
+                                   NULL, NULL, error_name, sender))
     {
       dbus_message_unref (message);
       return NULL;
@@ -1312,46 +1352,139 @@ dbus_message_get_type (DBusMessage *message)
   return type;
 }
 
+/**
+ * Sets the interface this message is being sent to
+ * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or
+ * the interface a signal is being emitted from
+ * (for DBUS_MESSAGE_TYPE_SIGNAL).
+ *
+ * @param message the message
+ * @param interface the interface
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_interface (DBusMessage  *message,
+                            const char   *interface)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  
+  if (interface == NULL)
+    {
+      delete_string_field (message, FIELD_INTERFACE);
+      return TRUE;
+    }
+  else
+    {
+      return set_string_field (message,
+                               FIELD_INTERFACE,
+                               interface);
+    }
+}
 
 /**
- * Sets the message name.
+ * Gets the interface this message is being sent to
+ * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
+ * from (for DBUS_MESSAGE_TYPE_SIGNAL).
+ * The interface name is fully-qualified (namespaced).
  *
  * @param message the message
- * @param name the name
+ * @returns the message interface (should not be freed)
+ */
+const char*
+dbus_message_get_interface (DBusMessage *message)
+{
+  _dbus_return_val_if_fail (message != NULL, NULL);
+  
+  return get_string_field (message, FIELD_INTERFACE, NULL);
+}
+
+/**
+ * Sets the interface member being invoked
+ * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
+ * (DBUS_MESSAGE_TYPE_SIGNAL).
+ * The interface name is fully-qualified (namespaced).
+ *
+ * @param message the message
+ * @param member the member
  * @returns #FALSE if not enough memory
  */
 dbus_bool_t
-dbus_message_set_name (DBusMessage  *message,
-                       const char   *name)
+dbus_message_set_member (DBusMessage  *message,
+                       const char   *member)
 {
   _dbus_return_val_if_fail (message != NULL, FALSE);
   _dbus_return_val_if_fail (!message->locked, FALSE);
   
-  if (name == NULL)
+  if (member == NULL)
     {
-      delete_string_field (message, FIELD_NAME);
+      delete_string_field (message, FIELD_MEMBER);
       return TRUE;
     }
   else
     {
       return set_string_field (message,
-                               FIELD_NAME,
-                               name);
+                               FIELD_MEMBER,
+                               member);
     }
 }
 
 /**
- * Gets the name of a message.
+ * Gets the interface member being invoked
+ * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
+ * (DBUS_MESSAGE_TYPE_SIGNAL).
+ * 
+ * @param message the message
+ * @returns the member name (should not be freed)
+ */
+const char*
+dbus_message_get_member (DBusMessage *message)
+{
+  _dbus_return_val_if_fail (message != NULL, NULL);
+  
+  return get_string_field (message, FIELD_MEMBER, NULL);
+}
+
+/**
+ * Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
+ * The name is fully-qualified (namespaced).
  *
  * @param message the message
- * @returns the message name (should not be freed)
+ * @param name the name
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_error_name (DBusMessage  *message,
+                             const char   *error_name)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  
+  if (error_name == NULL)
+    {
+      delete_string_field (message, FIELD_ERROR_NAME);
+      return TRUE;
+    }
+  else
+    {
+      return set_string_field (message,
+                               FIELD_ERROR_NAME,
+                               error_name);
+    }
+}
+
+/**
+ * Gets the error name (DBUS_MESSAGE_TYPE_ERROR only).
+ * 
+ * @param message the message
+ * @returns the error name (should not be freed)
  */
 const char*
-dbus_message_get_name (DBusMessage *message)
+dbus_message_get_error_name (DBusMessage *message)
 {
   _dbus_return_val_if_fail (message != NULL, NULL);
   
-  return get_string_field (message, FIELD_NAME, NULL);
+  return get_string_field (message, FIELD_ERROR_NAME, NULL);
 }
 
 /**
@@ -3917,27 +4050,54 @@ dbus_message_get_sender (DBusMessage *message)
 }
 
 /**
- * Checks whether the message has the given name.
- * If the message has no name or has a different
- * name, returns #FALSE.
+ * Checks whether the message has the given interface field.  If the
+ * message has no interface field or has a different one, returns
+ * #FALSE.
+ *
+ * @param message the message
+ * @param interface the name to check (must not be #NULL)
+ * 
+ * @returns #TRUE if the message has the given name
+ */
+dbus_bool_t
+dbus_message_has_interface (DBusMessage *message,
+                            const char  *interface)
+{
+  const char *n;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (interface != NULL, FALSE);
+  
+  n = dbus_message_get_interface (message);
+
+  if (n && strcmp (n, interface) == 0)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+
+/**
+ * Checks whether the message has the given member field.  If the
+ * message has no member field or has a different one, returns #FALSE.
  *
  * @param message the message
- * @param name the name to check (must not be #NULL)
+ * @param member the name to check (must not be #NULL)
  * 
  * @returns #TRUE if the message has the given name
  */
 dbus_bool_t
-dbus_message_has_name (DBusMessage *message,
-                       const char  *name)
+dbus_message_has_member (DBusMessage *message,
+                         const char  *member)
 {
   const char *n;
 
   _dbus_return_val_if_fail (message != NULL, FALSE);
-  _dbus_return_val_if_fail (name != NULL, FALSE);
+  _dbus_return_val_if_fail (member != NULL, FALSE);
   
-  n = dbus_message_get_name (message);
+  n = dbus_message_get_member (message);
 
-  if (n && strcmp (n, name) == 0)
+  if (n && strcmp (n, member) == 0)
     return TRUE;
   else
     return FALSE;
@@ -4034,7 +4194,7 @@ dbus_set_error_from_message (DBusError   *error,
                          DBUS_TYPE_STRING, &str,
                          DBUS_TYPE_INVALID);
 
-  dbus_set_error (error, dbus_message_get_name (message),
+  dbus_set_error (error, dbus_message_get_error_name (message),
                   str ? "%s" : NULL, str);
 
   dbus_free (str);
@@ -4216,9 +4376,17 @@ _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
                        (((dbus_uint32_t)c) << 8)  |     \
                        ((dbus_uint32_t)d))
 
-/** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
-#define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
-  FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
+/** DBUS_HEADER_FIELD_INTERFACE packed into a dbus_uint32_t */
+#define DBUS_HEADER_FIELD_INTERFACE_AS_UINT32    \
+  FOUR_CHARS_TO_UINT32 ('i', 'f', 'c', 'e')
+
+/** DBUS_HEADER_FIELD_MEMBER packed into a dbus_uint32_t */
+#define DBUS_HEADER_FIELD_MEMBER_AS_UINT32    \
+  FOUR_CHARS_TO_UINT32 ('m', 'e', 'b', 'r')
+
+/** DBUS_HEADER_FIELD_ERROR_NAME packed into a dbus_uint32_t */
+#define DBUS_HEADER_FIELD_ERROR_NAME_AS_UINT32    \
+  FOUR_CHARS_TO_UINT32 ('e', 'r', 'n', 'm')
 
 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
@@ -4267,23 +4435,41 @@ decode_string_field (const DBusString   *data,
   _dbus_string_init_const (&tmp,
                            _dbus_string_get_const_data (data) + string_data_pos);
 
-  if (field == FIELD_NAME)
+  if (field == FIELD_INTERFACE)
     {
-      if (!_dbus_string_validate_name (&tmp, 0, _dbus_string_get_length (&tmp)))
+      if (!_dbus_string_validate_interface (&tmp, 0, _dbus_string_get_length (&tmp)))
         {
           _dbus_verbose ("%s field has invalid content \"%s\"\n",
                          field_name, _dbus_string_get_const_data (&tmp));
           return FALSE;
         }
       
-      if (_dbus_string_starts_with_c_str (&tmp,
-                                          DBUS_NAMESPACE_LOCAL_MESSAGE))
+      if (_dbus_string_equal_c_str (&tmp,
+                                    DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
         {
-          _dbus_verbose ("Message is in the local namespace\n");
+          _dbus_verbose ("Message is on the local interface\n");
           return FALSE;
         }
     }
-  else
+  else if (field == FIELD_MEMBER)
+    {
+      if (!_dbus_string_validate_member (&tmp, 0, _dbus_string_get_length (&tmp)))
+        {
+          _dbus_verbose ("%s field has invalid content \"%s\"\n",
+                         field_name, _dbus_string_get_const_data (&tmp));
+          return FALSE;
+        }
+    }
+  else if (field == FIELD_ERROR_NAME)
+    {
+      if (!_dbus_string_validate_error_name (&tmp, 0, _dbus_string_get_length (&tmp)))
+        {
+          _dbus_verbose ("%s field has invalid content \"%s\"\n",
+                         field_name, _dbus_string_get_const_data (&tmp));
+          return FALSE;
+        }
+    }
+  else if (field == FIELD_SERVICE)
     {
       if (!_dbus_string_validate_service (&tmp, 0, _dbus_string_get_length (&tmp)))
         {
@@ -4292,6 +4478,10 @@ decode_string_field (const DBusString   *data,
           return FALSE;
         }
     }
+  else
+    {
+      _dbus_assert_not_reached ("Unknown field\n");
+    }
   
   fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4);
   
@@ -4307,6 +4497,7 @@ static dbus_bool_t
 decode_header_data (const DBusString   *data,
                    int                 header_len,
                    int                 byte_order,
+                    int                 message_type,
                     HeaderField         fields[FIELD_LAST],
                    int                *message_padding)
 {
@@ -4375,13 +4566,27 @@ decode_header_data (const DBusString   *data,
             return FALSE;
           break;
 
-        case DBUS_HEADER_FIELD_NAME_AS_UINT32:
+        case DBUS_HEADER_FIELD_INTERFACE_AS_UINT32:
+          if (!decode_string_field (data, fields, pos, type,
+                                    FIELD_INTERFACE,
+                                    DBUS_HEADER_FIELD_INTERFACE))
+            return FALSE;
+          break;
+
+        case DBUS_HEADER_FIELD_MEMBER_AS_UINT32:
           if (!decode_string_field (data, fields, pos, type,
-                                    FIELD_NAME,
-                                    DBUS_HEADER_FIELD_NAME))
+                                    FIELD_MEMBER,
+                                    DBUS_HEADER_FIELD_MEMBER))
             return FALSE;
           break;
 
+        case DBUS_HEADER_FIELD_ERROR_NAME_AS_UINT32:
+          if (!decode_string_field (data, fields, pos, type,
+                                    FIELD_ERROR_NAME,
+                                    DBUS_HEADER_FIELD_ERROR_NAME))
+            return FALSE;
+          break;
+          
        case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
           if (!decode_string_field (data, fields, pos, type,
                                     FIELD_SENDER,
@@ -4430,12 +4635,37 @@ decode_header_data (const DBusString   *data,
         }
     }
 
-  /* Name field is mandatory */
-  if (fields[FIELD_NAME].offset < 0)
+  /* Depending on message type, enforce presence of certain fields. */
+  switch (message_type)
     {
-      _dbus_verbose ("No %s field provided\n",
-                     DBUS_HEADER_FIELD_NAME);
-      return FALSE;
+    case DBUS_MESSAGE_TYPE_SIGNAL:
+    case DBUS_MESSAGE_TYPE_METHOD_CALL:
+      if (fields[FIELD_INTERFACE].offset < 0)
+        {
+          _dbus_verbose ("No %s field provided\n",
+                         DBUS_HEADER_FIELD_INTERFACE);
+          return FALSE;
+        }
+      if (fields[FIELD_MEMBER].offset < 0)
+        {
+          _dbus_verbose ("No %s field provided\n",
+                         DBUS_HEADER_FIELD_MEMBER);
+          return FALSE;
+        }
+      break;
+    case DBUS_MESSAGE_TYPE_ERROR:
+      if (fields[FIELD_ERROR_NAME].offset < 0)
+        {
+          _dbus_verbose ("No %s field provided\n",
+                         DBUS_HEADER_FIELD_ERROR_NAME);
+          return FALSE;
+        }
+      break;
+    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+      break;
+    default:
+      /* An unknown type, spec requires us to ignore it */
+      break;
     }
   
   if (message_padding)
@@ -4579,7 +4809,8 @@ _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
 #if 0
          _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
 #endif   
-         if (!decode_header_data (&loader->data, header_len, byte_order,
+         if (!decode_header_data (&loader->data, message_type,
+                                   header_len, byte_order,
                                    fields, &header_padding))
            {
               _dbus_verbose ("Header was invalid\n");
@@ -6010,15 +6241,19 @@ _dbus_message_test (const char *test_data_dir)
   
   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
 
-  message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test");
-  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.Test"));
+  message = dbus_message_new_method_call ("Foo.TestInterface",
+                                          "TestMethod",
+                                          "org.freedesktop.DBus.TestService");
+  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
+  _dbus_assert (dbus_message_has_interface (message, "Foo.TestInterface"));
+  _dbus_assert (dbus_message_has_member (message, "TestMethod"));
   _dbus_message_set_serial (message, 1234);
   dbus_message_set_sender (message, "org.foo.bar");
   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar"));
   dbus_message_set_sender (message, NULL);
   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar"));
   _dbus_assert (dbus_message_get_serial (message) == 1234);
-  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.Test"));
+  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
 
   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
   dbus_message_set_no_reply (message, TRUE);
@@ -6029,7 +6264,9 @@ _dbus_message_test (const char *test_data_dir)
   dbus_message_unref (message);
   
   /* Test the vararg functions */
-  message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test");
+  message = dbus_message_new_method_call ("Foo.TestInterface",
+                                          "TestMethod",
+                                          "org.freedesktop.DBus.TestService");
   _dbus_message_set_serial (message, 1);
   dbus_message_append_args (message,
                            DBUS_TYPE_INT32, -0x12345678,
@@ -6087,15 +6324,22 @@ _dbus_message_test (const char *test_data_dir)
 
   verify_test_message (copy);
 
-  name1 = dbus_message_get_name (message);
-  name2 = dbus_message_get_name (copy);
+  name1 = dbus_message_get_interface (message);
+  name2 = dbus_message_get_interface (copy);
+
+  _dbus_assert (strcmp (name1, name2) == 0);
+
+  name1 = dbus_message_get_member (message);
+  name2 = dbus_message_get_member (copy);
 
   _dbus_assert (strcmp (name1, name2) == 0);
   
   dbus_message_unref (message);
   dbus_message_unref (copy);
-  
-  message = dbus_message_new_method_call ("test.Message", "org.freedesktop.DBus.Test");
+
+  message = dbus_message_new_method_call ("Foo.TestInterface",
+                                          "TestMethod",
+                                          "org.freedesktop.DBus.TestService");
   _dbus_message_set_serial (message, 1);
   dbus_message_set_reply_serial (message, 0x12345678);
 
index 1b61c8d..dc20458 100644 (file)
@@ -58,10 +58,12 @@ struct DBusMessageIter
 };
 
 DBusMessage* dbus_message_new               (int          message_type);
-DBusMessage* dbus_message_new_method_call   (const char  *name,
+DBusMessage* dbus_message_new_method_call   (const char  *interface,
+                                             const char  *method,
                                              const char  *destination_service);
 DBusMessage* dbus_message_new_method_return (DBusMessage *method_call);
-DBusMessage* dbus_message_new_signal        (const char  *name);
+DBusMessage* dbus_message_new_signal        (const char  *interface,
+                                             const char  *name);
 DBusMessage* dbus_message_new_error         (DBusMessage *reply_to,
                                              const char  *error_name,
                                              const char  *error_message);
@@ -71,9 +73,15 @@ DBusMessage *dbus_message_copy              (const DBusMessage *message);
 void          dbus_message_ref              (DBusMessage   *message);
 void          dbus_message_unref            (DBusMessage   *message);
 int           dbus_message_get_type         (DBusMessage   *message);
-dbus_bool_t   dbus_message_set_name         (DBusMessage   *message,
+dbus_bool_t   dbus_message_set_interface    (DBusMessage   *message,
+                                             const char    *interface);
+const char*   dbus_message_get_interface    (DBusMessage   *message);
+dbus_bool_t   dbus_message_set_member       (DBusMessage   *message,
+                                             const char    *member);
+const char*   dbus_message_get_member       (DBusMessage   *message);
+dbus_bool_t   dbus_message_set_error_name   (DBusMessage   *message,
                                              const char    *name);
-const char*   dbus_message_get_name         (DBusMessage   *message);
+const char*   dbus_message_get_error_name   (DBusMessage   *message);
 dbus_bool_t   dbus_message_set_destination  (DBusMessage   *message,
                                              const char    *destination);
 const char*   dbus_message_get_destination  (DBusMessage   *message);
@@ -83,7 +91,11 @@ const char*   dbus_message_get_sender       (DBusMessage   *message);
 void          dbus_message_set_no_reply     (DBusMessage   *message,
                                              dbus_bool_t    no_reply);
 dbus_bool_t   dbus_message_get_no_reply     (DBusMessage   *message);
-dbus_bool_t   dbus_message_has_name         (DBusMessage   *message,
+dbus_bool_t   dbus_message_has_interface    (DBusMessage   *message,
+                                             const char    *interface);
+dbus_bool_t   dbus_message_has_member       (DBusMessage   *message,
+                                             const char    *member);
+dbus_bool_t   dbus_message_has_error_name   (DBusMessage   *message,
                                              const char    *name);
 dbus_bool_t   dbus_message_has_destination  (DBusMessage   *message,
                                              const char    *service);
index d3d175d..e5a8131 100644 (file)
@@ -63,7 +63,7 @@ struct DBusSignalEntry
   dbus_uint16_t *connections;      /**< Index of each object connected (can have dups for multiple
                                     * connections)
                                     */
-  char name[4];                    /**< Name of signal (actually allocated larger) */
+  char name[4];                    /**< Interface of signal, nul, then name of signal (actually allocated larger) */
 };
 
  /* 14 bits for object index, 32K objects */
@@ -144,8 +144,8 @@ _dbus_object_registry_new (DBusConnection *connection)
   if (interface_table == NULL)
     goto oom;
 
-  signal_table = _dbus_hash_table_new (DBUS_HASH_STRING,
-                                          NULL, free_signal_entry);
+  signal_table = _dbus_hash_table_new (DBUS_HASH_TWO_STRINGS,
+                                       NULL, free_signal_entry);
   if (signal_table == NULL)
     goto oom;
   
@@ -431,32 +431,45 @@ object_remove_from_interfaces (DBusObjectRegistry *registry,
 
 static DBusSignalEntry*
 lookup_signal (DBusObjectRegistry *registry,
-               const char         *name,
+               const char         *signal_interface,
+               const char         *signal_name,
                dbus_bool_t         create_if_not_found)
 {
   DBusSignalEntry *entry;
   int sz;
-  int len;
+  size_t len_interface, len_name;
+  char buf[2 * DBUS_MAXIMUM_NAME_LENGTH + 2];
+
+  /* This is all a little scary and maybe we shouldn't jump
+   * through these hoops just to save some bytes.
+   */
   
-  entry = _dbus_hash_table_lookup_string (registry->signal_table,
-                                          name);
+  len_interface = strlen (signal_interface);
+  len_name = strlen (signal_name);
+  
+  _dbus_assert (len_interface + len_name + 2 <= sizeof (buf));
+
+  memcpy (buf, signal_interface, len_interface + 1);
+  memcpy (buf + len_interface + 1, signal_name, len_name + 1);
+  
+  entry = _dbus_hash_table_lookup_two_strings (registry->signal_table,
+                                               buf);
   if (entry != NULL || !create_if_not_found)
     return entry;
   
   _dbus_assert (create_if_not_found);
 
-  len = strlen (name);
-  sz = _DBUS_STRUCT_OFFSET (DBusSignalEntry, name) + len + 1;
+  sz = _DBUS_STRUCT_OFFSET (DBusSignalEntry, name) + len_interface + len_name + 2;
   entry = dbus_malloc (sz);
   if (entry == NULL)
     return NULL;
   entry->n_connections = 0;
   entry->n_allocated = 0;
   entry->connections = NULL;
-  memcpy (entry->name, name, len + 1);
+  memcpy (entry->name, buf, len_interface + len_name + 2);
 
-  if (!_dbus_hash_table_insert_string (registry->signal_table,
-                                       entry->name, entry))
+  if (!_dbus_hash_table_insert_two_strings (registry->signal_table,
+                                            entry->name, entry))
     {
       dbus_free (entry);
       return NULL;
@@ -469,8 +482,8 @@ static void
 delete_signal (DBusObjectRegistry *registry,
                DBusSignalEntry *entry)
 {
-  _dbus_hash_table_remove_string (registry->signal_table,
-                                  entry->name);
+  _dbus_hash_table_remove_two_strings (registry->signal_table,
+                                       entry->name);
 }
 
 static dbus_bool_t
@@ -553,11 +566,11 @@ object_remove_from_signals (DBusObjectRegistry *registry,
       i = 0;
       while (entry->signals[i] != NULL)
         {
-          DBusSignalEntry *iface = entry->signals[i];
+          DBusSignalEntry *signal = entry->signals[i];
           
-          signal_entry_remove_object (iface, entry->id_index);
-          if (iface->n_connections == 0)
-            delete_signal (registry, iface);
+          signal_entry_remove_object (signal, entry->id_index);
+          if (signal->n_connections == 0)
+            delete_signal (registry, signal);
           ++i;
         }
     }
@@ -573,19 +586,24 @@ object_remove_from_signals (DBusObjectRegistry *registry,
  * 
  * @param registry the object registry
  * @param object_id object that would like to see the signal
- * @param signal signal name
+ * @param signal_interface signal interface name
+ * @param signal_name signal member name
  *
  * @returns #FALSE if no memory
  */
 dbus_bool_t
 _dbus_object_registry_connect_locked (DBusObjectRegistry *registry,
                                       const DBusObjectID *object_id,
+                                      const char         *signal_interface,
                                       const char         *signal_name)
 {
   DBusSignalEntry **new_signals;
   DBusSignalEntry *signal;
   DBusObjectEntry *entry;
   int i;
+
+  _dbus_assert (signal_interface != NULL);
+  _dbus_assert (signal_name != NULL);
   
   entry = validate_id (registry, object_id);
   if (entry == NULL)
@@ -617,7 +635,7 @@ _dbus_object_registry_connect_locked (DBusObjectRegistry *registry,
 
   entry->signals = new_signals;
   
-  signal = lookup_signal (registry, signal_name, TRUE); 
+  signal = lookup_signal (registry, signal_interface, signal_name, TRUE); 
   if (signal == NULL)
     goto oom;
 
@@ -642,30 +660,35 @@ _dbus_object_registry_connect_locked (DBusObjectRegistry *registry,
  *
  * @param registry the object registry
  * @param object_id object that would like to see the signal
- * @param signal signal name
+ * @param signal_interface signal interface
+ * @param signal_name signal name
  */
 void
 _dbus_object_registry_disconnect_locked (DBusObjectRegistry      *registry,
                                          const DBusObjectID      *object_id,
+                                         const char              *signal_interface,
                                          const char              *signal_name)
 {
   DBusObjectEntry *entry;
   DBusSignalEntry *signal;
+
+  _dbus_assert (signal_interface != NULL);
+  _dbus_assert (signal_name != NULL);
   
   entry = validate_id (registry, object_id);
   if (entry == NULL)
     {
-      _dbus_warn ("Tried to disconnect signal \"%s\" from a nonexistent D-BUS object ID\n",
-                  signal_name);
+      _dbus_warn ("Tried to disconnect signal \"%s\"::\"%s\" from a nonexistent D-BUS object ID\n",
+                  signal_interface, signal_name);
       
       return;
     }
 
-  signal = lookup_signal (registry, signal_name, FALSE);
+  signal = lookup_signal (registry, signal_interface, signal_name, FALSE);
   if (signal == NULL)
     {
-      _dbus_warn ("Tried to disconnect signal \"%s\" but no such signal is connected\n",
-                  signal_name);
+      _dbus_warn ("Tried to disconnect signal \"%s\"::\"%s\" but no such signal is connected\n",
+                  signal_interface, signal_name);
       return;
     }
   
@@ -695,7 +718,7 @@ handle_method_call_and_unlock (DBusObjectRegistry *registry,
    * it to the first object that supports the given interface.
    */
   iface_entry = lookup_interface (registry,
-                                  dbus_message_get_name (message),
+                                  dbus_message_get_interface (message),
                                   FALSE);
   
   if (iface_entry == NULL)
@@ -750,7 +773,8 @@ handle_signal_and_unlock (DBusObjectRegistry *registry,
   _dbus_assert (message != NULL);
 
   signal_entry = lookup_signal (registry,
-                                dbus_message_get_name (message),
+                                dbus_message_get_interface (message),
+                                dbus_message_get_member (message),
                                 FALSE);
   
   if (signal_entry == NULL)
@@ -1291,7 +1315,8 @@ add_and_remove_objects (DBusObjectRegistry *registry)
       ++i;
     }
 
-  message = dbus_message_new_method_call ("org.freedesktop.Test.Foo", NULL);
+  message = dbus_message_new_method_call ("org.freedesktop.Test.Foo",
+                                          "Bar", NULL);
   if (message != NULL)
     {
       if (_dbus_object_registry_handle_and_unlock (registry, message) !=
@@ -1300,7 +1325,8 @@ add_and_remove_objects (DBusObjectRegistry *registry)
       dbus_message_unref (message);
     }
 
-  message = dbus_message_new_method_call ("org.freedesktop.Test.Blah", NULL);
+  message = dbus_message_new_method_call ("org.freedesktop.Test.Blah",
+                                          "Baz", NULL);
   if (message != NULL)
     {
       if (_dbus_object_registry_handle_and_unlock (registry, message) !=
@@ -1309,7 +1335,8 @@ add_and_remove_objects (DBusObjectRegistry *registry)
       dbus_message_unref (message);
     }
 
-  message = dbus_message_new_method_call ("org.freedesktop.Test.NotRegisteredIface", NULL);
+  message = dbus_message_new_method_call ("org.freedesktop.Test.NotRegisteredIface",
+                                          "Boo", NULL);
   if (message != NULL)
     {
       if (_dbus_object_registry_handle_and_unlock (registry, message) !=
index bcbd0f8..29c92b9 100644 (file)
@@ -45,10 +45,12 @@ DBusHandlerResult _dbus_object_registry_handle_and_unlock (DBusObjectRegistry
 void              _dbus_object_registry_free_all_unlocked (DBusObjectRegistry      *registry);
 dbus_bool_t       _dbus_object_registry_connect_locked    (DBusObjectRegistry      *registry,
                                                            const DBusObjectID      *object_id,
-                                                           const char              *signal);
+                                                           const char              *signal_interface,
+                                                           const char              *signal_name);
 void              _dbus_object_registry_disconnect_locked (DBusObjectRegistry      *registry,
                                                            const DBusObjectID      *object_id,
-                                                           const char              *signal);
+                                                           const char              *signal_interface,
+                                                           const char              *signal_name);
 
 DBUS_END_DECLS;
 
index e027cf5..a1f4a72 100644 (file)
@@ -57,7 +57,7 @@ extern "C" {
   
 #define DBUS_TYPE_LAST DBUS_TYPE_OBJECT_ID
 
-/* Max length in bytes of a service or message name */
+/* Max length in bytes of a service or interface or member name */
 #define DBUS_MAXIMUM_NAME_LENGTH 256
 
 /* Types of message */
@@ -71,14 +71,16 @@ extern "C" {
 #define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED 0x1
   
 /* Header fields */
-#define DBUS_HEADER_FIELD_NAME    "name"
-#define DBUS_HEADER_FIELD_SERVICE "srvc"
-#define DBUS_HEADER_FIELD_REPLY          "rply"
-#define DBUS_HEADER_FIELD_SENDER  "sndr"
+#define DBUS_HEADER_FIELD_INTERFACE  "ifce"
+#define DBUS_HEADER_FIELD_MEMBER     "mebr"
+#define DBUS_HEADER_FIELD_ERROR_NAME "ernm"
+#define DBUS_HEADER_FIELD_SERVICE    "srvc"
+#define DBUS_HEADER_FIELD_REPLY             "rply"
+#define DBUS_HEADER_FIELD_SENDER     "sndr"
 
 /* Services */
-#define DBUS_SERVICE_DBUS      "org.freedesktop.DBus"
-#define DBUS_SERVICE_BROADCAST "org.freedesktop.DBus.Broadcast"
+#define DBUS_SERVICE_ORG_FREEDESKTOP_DBUS      "org.freedesktop.DBus"
+#define DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST "org.freedesktop.Broadcast"
 
 /* Service owner flags */
 #define DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT 0x1
@@ -94,23 +96,30 @@ extern "C" {
 #define DBUS_ACTIVATION_REPLY_ACTIVATED      0x0
 #define DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE 0x1
   
-/* Messages */
-#define DBUS_MESSAGE_ACTIVATE_SERVICE      "org.freedesktop.DBus.ActivateService"  
-#define DBUS_MESSAGE_SERVICE_EXISTS        "org.freedesktop.DBus.ServiceExists"
-#define DBUS_MESSAGE_HELLO                 "org.freedesktop.DBus.Hello"
-#define DBUS_MESSAGE_LIST_SERVICES         "org.freedesktop.DBus.ListServices"
-#define DBUS_MESSAGE_ACQUIRE_SERVICE       "org.freedesktop.DBus.AcquireService"
-#define DBUS_MESSAGE_SERVICE_ACQUIRED      "org.freedesktop.DBus.ServiceAcquired"
-#define DBUS_MESSAGE_SERVICE_CREATED       "org.freedesktop.DBus.ServiceCreated"
-#define DBUS_MESSAGE_SERVICE_DELETED       "org.freedesktop.DBus.ServiceDeleted"
-#define DBUS_MESSAGE_SERVICE_LOST          "org.freedesktop.DBus.ServiceLost"
-
-
-/* This namespace is reserved for locally-synthesized messages, you can't
- * send messages that have this namespace.
+/* Interfaces, these #define don't do much other than
+ * catch typos at compile time
  */
-#define DBUS_NAMESPACE_LOCAL_MESSAGE       "org.freedesktop.Local."
-#define DBUS_MESSAGE_LOCAL_DISCONNECT      DBUS_NAMESPACE_LOCAL_MESSAGE"Disconnect"
+#define DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS  "org.freedesktop.DBus"
+
+/* This is a special interface whose methods can only be invoked
+ * by the local implementation (messages from remote apps aren't
+ * allowed to specify this interface).
+ */
+#define DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL "org.freedesktop.Local"
+
+#if 0
+  /* these are a bad idea, FIXME */
+#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_ACTIVATE_SERVICE      "ActivateService"  
+#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_SERVICE_EXISTS        "ServiceExists"
+#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_HELLO                 "Hello"
+#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_LIST_SERVICES         "ListServices"
+#define DBUS_METHOD_ORG_FREEDESKTOP_DBUS_ACQUIRE_SERVICE       "AcquireService"
+
+#define DBUS_SIGNAL_ORG_FREEDESKTOP_DBUS_SERVICE_ACQUIRED      "ServiceAcquired"
+#define DBUS_SIGNAL_ORG_FREEDESKTOP_DBUS_SERVICE_CREATED       "ServiceCreated"
+#define DBUS_SIGNAL_ORG_FREEDESKTOP_DBUS_SERVICE_DELETED       "ServiceDeleted"
+#define DBUS_SIGNAL_ORG_FREEDESKTOP_DBUS_SERVICE_LOST          "ServiceLost"
+#endif /* #if 0 */
   
 #ifdef __cplusplus
 }
index f4f7a2a..848135f 100644 (file)
@@ -2846,7 +2846,7 @@ _dbus_string_validate_nul (const DBusString *str,
 }
 
 /**
- * Checks that the given range of the string is a valid message name
+ * Checks that the given range of the string is a valid interface name
  * in the D-BUS protocol. This includes a length restriction, etc.,
  * see the specification. It does not validate UTF-8, that has to be
  * done separately for now.
@@ -2860,9 +2860,9 @@ _dbus_string_validate_nul (const DBusString *str,
  * @returns #TRUE if the byte range exists and is a valid name
  */
 dbus_bool_t
-_dbus_string_validate_name (const DBusString  *str,
-                            int                start,
-                            int                len)
+_dbus_string_validate_interface (const DBusString  *str,
+                                 int                start,
+                                 int                len)
 {
   const unsigned char *s;
   const unsigned char *end;
@@ -2902,6 +2902,86 @@ _dbus_string_validate_name (const DBusString  *str,
   return TRUE;
 }
 
+/**
+ * Checks that the given range of the string is a valid member name
+ * in the D-BUS protocol. This includes a length restriction, etc.,
+ * see the specification. It does not validate UTF-8, that has to be
+ * done separately for now.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that isn't in the string.
+ * 
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_string_validate_member (const DBusString  *str,
+                              int                start,
+                              int                len)
+{
+  const unsigned char *s;
+  const unsigned char *end;
+  dbus_bool_t saw_dot;
+  
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= real->len);
+  
+  if (len > real->len - start)
+    return FALSE;
+
+  if (len > DBUS_MAXIMUM_NAME_LENGTH)
+    return FALSE;
+
+  if (len == 0)
+    return FALSE;
+
+  saw_dot = FALSE;
+  s = real->str + start;
+  end = s + len;
+  while (s != end)
+    {
+      if (*s == '.')
+        {
+          saw_dot = TRUE;
+          break;
+        }
+      
+      ++s;
+    }
+
+  /* No dot allowed in member names */
+  if (saw_dot)
+    return FALSE;
+  
+  return TRUE;
+}
+
+/**
+ * Checks that the given range of the string is a valid error name
+ * in the D-BUS protocol. This includes a length restriction, etc.,
+ * see the specification. It does not validate UTF-8, that has to be
+ * done separately for now.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that isn't in the string.
+ * 
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_string_validate_error_name (const DBusString  *str,
+                                  int                start,
+                                  int                len)
+{
+  /* Same restrictions as interface name at the moment */
+  return _dbus_string_validate_interface (str, start, len);
+}
 
 /**
  * Checks that the given range of the string is a valid service name
index 732359a..6f164be 100644 (file)
@@ -223,7 +223,13 @@ dbus_bool_t   _dbus_string_validate_utf8         (const DBusString  *str,
 dbus_bool_t   _dbus_string_validate_nul          (const DBusString  *str,
                                                   int                start,
                                                   int                len);
-dbus_bool_t   _dbus_string_validate_name         (const DBusString  *str,
+dbus_bool_t   _dbus_string_validate_interface    (const DBusString  *str,
+                                                  int                start,
+                                                  int                len);
+dbus_bool_t   _dbus_string_validate_member       (const DBusString  *str,
+                                                  int                start,
+                                                  int                len);
+dbus_bool_t   _dbus_string_validate_error_name   (const DBusString  *str,
                                                   int                start,
                                                   int                len);
 dbus_bool_t   _dbus_string_validate_service      (const DBusString  *str,