2003-03-31 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-transport.c
index b6ab8c0..96bc6b6 100644 (file)
@@ -82,16 +82,19 @@ live_messages_size_notify (DBusCounter *counter,
  * @param transport the transport being created.
  * @param vtable the subclass vtable.
  * @param server #TRUE if this transport is on the server side of a connection
+ * @param address the address of the transport
  * @returns #TRUE on success.
  */
 dbus_bool_t
 _dbus_transport_init_base (DBusTransport             *transport,
                            const DBusTransportVTable *vtable,
-                           dbus_bool_t                server)
+                           dbus_bool_t                server,
+                           const DBusString          *address)
 {
   DBusMessageLoader *loader;
   DBusAuth *auth;
   DBusCounter *counter;
+  char *address_copy;
   
   loader = _dbus_message_loader_new ();
   if (loader == NULL)
@@ -113,6 +116,24 @@ _dbus_transport_init_base (DBusTransport             *transport,
       _dbus_auth_unref (auth);
       _dbus_message_loader_unref (loader);
       return FALSE;
+    }  
+  
+  if (server)
+    {
+      _dbus_assert (address == NULL);
+      address_copy = NULL;
+    }
+  else
+    {
+      _dbus_assert (address != NULL);
+
+      if (!_dbus_string_copy_data (address, &address_copy))
+        {
+          _dbus_counter_unref (counter);
+          _dbus_auth_unref (auth);
+          _dbus_message_loader_unref (loader);
+          return FALSE;
+        }
     }
   
   transport->refcount = 1;
@@ -126,7 +147,8 @@ _dbus_transport_init_base (DBusTransport             *transport,
   transport->send_credentials_pending = !server;
   transport->receive_credentials_pending = server;
   transport->is_server = server;
-
+  transport->address = address_copy;
+  
   transport->unix_user_function = NULL;
   transport->unix_user_data = NULL;
   transport->free_unix_user_data = NULL;
@@ -144,6 +166,9 @@ _dbus_transport_init_base (DBusTransport             *transport,
                             transport->max_live_messages_size,
                             live_messages_size_notify,
                             transport);
+
+  if (transport->address)
+    _dbus_verbose ("Initialized transport on address %s\n", transport->address);
   
   return TRUE;
 }
@@ -168,6 +193,7 @@ _dbus_transport_finalize_base (DBusTransport *transport)
   _dbus_counter_set_notify (transport->live_messages_size,
                             0, NULL, NULL);
   _dbus_counter_unref (transport->live_messages_size);
+  dbus_free (transport->address);
 }
 
 /**
@@ -178,21 +204,29 @@ _dbus_transport_finalize_base (DBusTransport *transport)
  * DBusResultCode is a bit limiting here.
  * 
  * @param address the address.
- * @param result location to store reason for failure.
+ * @param error location to store reason for failure.
  * @returns new transport of #NULL on failure.
  */
 DBusTransport*
 _dbus_transport_open (const char     *address,
-                      DBusResultCode *result)
+                      DBusError      *error)
 {
   DBusTransport *transport;
   DBusAddressEntry **entries;
   int len, i;
+  const char *address_problem_type;
+  const char *address_problem_field;
+  const char *address_problem_other;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  if (!dbus_parse_address (address, &entries, &len, result))
+  if (!dbus_parse_address (address, &entries, &len, error))
     return NULL;
 
   transport = NULL;
+  address_problem_type = NULL;
+  address_problem_field = NULL;
+  address_problem_other = NULL;
   
   for (i = 0; i < len; i++)
     {
@@ -203,9 +237,13 @@ _dbus_transport_open (const char     *address,
          const char *path = dbus_address_entry_get_value (entries[i], "path");
 
          if (path == NULL)
-           goto bad_address;
+            {
+              address_problem_type = "unix";
+              address_problem_field = "path";              
+              goto bad_address;
+            }
 
-         transport = _dbus_transport_new_for_domain_socket (path, FALSE, result);
+         transport = _dbus_transport_new_for_domain_socket (path, error);
        }
       else if (strcmp (method, "tcp") == 0)
        {
@@ -215,17 +253,24 @@ _dbus_transport_open (const char     *address,
           long lport;
           dbus_bool_t sresult;
           
-         if (port == NULL)
-           goto bad_address;
+          if (port == NULL)
+            {
+              address_problem_type = "tcp";
+              address_problem_field = "port";
+              goto bad_address;
+            }
 
           _dbus_string_init_const (&str, port);
           sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
           _dbus_string_free (&str);
           
           if (sresult == FALSE || lport <= 0 || lport > 65535)
-            goto bad_address;
+            {
+              address_problem_other = "Port is not an integer between 0 and 65535";
+              goto bad_address;
+            }
           
-         transport = _dbus_transport_new_for_tcp_socket (host, lport, FALSE, result);
+         transport = _dbus_transport_new_for_tcp_socket (host, lport, error);
        }
 #ifdef DBUS_BUILD_TESTS
       else if (strcmp (method, "debug") == 0)
@@ -233,22 +278,33 @@ _dbus_transport_open (const char     *address,
          const char *name = dbus_address_entry_get_value (entries[i], "name");
 
          if (name == NULL)
-           goto bad_address;
+            {
+              address_problem_type = "debug";
+              address_problem_field = "name";
+              goto bad_address;
+            }
 
-         transport = _dbus_transport_debug_client_new (name, result);
+         transport = _dbus_transport_debug_client_new (name, error);
        }
       else if (strcmp (method, "debug-pipe") == 0)
        {
          const char *name = dbus_address_entry_get_value (entries[i], "name");
 
-         if (name == NULL)
-           goto bad_address;
+          if (name == NULL)
+            {
+              address_problem_type = "debug-pipe";
+              address_problem_field = "name";
+              goto bad_address;
+            }
 
-         transport = _dbus_transport_debug_pipe_new (name, result);
+         transport = _dbus_transport_debug_pipe_new (name, error);
        }
 #endif
       else
-       goto bad_address;
+        {
+          address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
+          goto bad_address;
+        }
 
       if (transport)
        break;    
@@ -259,7 +315,15 @@ _dbus_transport_open (const char     *address,
 
  bad_address:
   dbus_address_entries_free (entries);
-  dbus_set_result (result, DBUS_RESULT_BAD_ADDRESS);
+
+  if (address_problem_type != NULL)
+    dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                    "Address of type %s was missing argument %s",
+                    address_problem_type, address_problem_field);
+  else
+    dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                    "Could not parse address: %s",
+                    address_problem_other);
 
   return NULL;
 }
@@ -353,10 +417,12 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
     return TRUE;
   else
     {
+      dbus_bool_t maybe_authenticated;
+      
       if (transport->disconnected)
         return FALSE;
       
-      transport->authenticated =
+      maybe_authenticated =
         (!(transport->send_credentials_pending ||
            transport->receive_credentials_pending)) &&
         _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_AUTHENTICATED;
@@ -369,7 +435,7 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
        * Or they may give certain identities extra privileges.
        */
       
-      if (transport->authenticated && transport->is_server)
+      if (maybe_authenticated && transport->is_server)
         {
           DBusCredentials auth_identity;
 
@@ -413,12 +479,27 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
                 }
             }
         }
+
+      transport->authenticated = maybe_authenticated;
       
       return transport->authenticated;
     }
 }
 
 /**
+ * Gets the address of a transport. It will be
+ * #NULL for a server-side transport.
+ *
+ * @param transport the transport
+ * @returns transport's address
+ */
+const char*
+_dbus_transport_get_address (DBusTransport *transport)
+{
+  return transport->address;
+}
+
+/**
  * Handles a watch by reading data, writing data, or disconnecting
  * the transport, as appropriate for the given condition.
  *
@@ -555,7 +636,7 @@ recover_unused_bytes (DBusTransport *transport)
       DBusString *buffer;
       int orig_len;
       
-      if (!_dbus_string_init (&plaintext, _DBUS_INT_MAX))
+      if (!_dbus_string_init (&plaintext))
         goto nomem;
       
       _dbus_auth_get_unused_bytes (transport->auth,