-/* -*- mode: C; c-file-style: "gnu" -*- */
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* dbus-transport-socket.c Socket subclasses of DBusTransport
*
* Copyright (C) 2002, 2003, 2004, 2006 Red Hat Inc.
#include "dbus-transport-socket.h"
#include "dbus-transport-protected.h"
#include "dbus-watch.h"
+#include "dbus-credentials.h"
/**
{
/* EINTR already handled for us */
- if (errno == ENOMEM)
+ if (_dbus_get_is_errno_enomem ())
{
*oom = TRUE;
}
- else if (errno == EAGAIN ||
- errno == EWOULDBLOCK)
+ else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
; /* do nothing, just return FALSE below */
else
{
_dbus_verbose ("Error reading from remote app: %s\n",
- _dbus_strerror (errno));
+ _dbus_strerror_from_errno ());
do_io_error (transport);
}
{
/* EINTR already handled for us */
- if (errno == EAGAIN ||
- errno == EWOULDBLOCK)
+ if (_dbus_get_is_errno_eagain_or_ewouldblock ())
;
else
{
_dbus_verbose ("Error writing to remote app: %s\n",
- _dbus_strerror (errno));
+ _dbus_strerror_from_errno ());
do_io_error (transport);
}
}
return FALSE;
}
-static void
+/* FALSE on OOM */
+static dbus_bool_t
exchange_credentials (DBusTransport *transport,
dbus_bool_t do_reading,
dbus_bool_t do_writing)
{
DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+ DBusError error;
+
+ _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n",
+ do_reading, do_writing);
+ dbus_error_init (&error);
if (do_writing && transport->send_credentials_pending)
{
- if (_dbus_send_credentials_unix_socket (socket_transport->fd,
- NULL))
+ if (_dbus_send_credentials_socket (socket_transport->fd,
+ &error))
{
transport->send_credentials_pending = FALSE;
}
else
{
- _dbus_verbose ("Failed to write credentials\n");
+ _dbus_verbose ("Failed to write credentials: %s\n", error.message);
+ dbus_error_free (&error);
do_io_error (transport);
}
}
if (do_reading && transport->receive_credentials_pending)
{
- if (_dbus_read_credentials_unix_socket (socket_transport->fd,
- &transport->credentials,
- NULL))
+ /* FIXME this can fail due to IO error _or_ OOM, broken
+ * (somewhat tricky to fix since the OOM error can be set after
+ * we already read the credentials byte, so basically we need to
+ * separate reading the byte and storing it in the
+ * transport->credentials). Does not really matter for now
+ * because storing in credentials never actually fails on unix.
+ */
+ if (_dbus_read_credentials_socket (socket_transport->fd,
+ transport->credentials,
+ &error))
{
transport->receive_credentials_pending = FALSE;
}
else
{
- _dbus_verbose ("Failed to read credentials\n");
+ _dbus_verbose ("Failed to read credentials %s\n", error.message);
+ dbus_error_free (&error);
do_io_error (transport);
}
}
if (!(transport->send_credentials_pending ||
transport->receive_credentials_pending))
{
- _dbus_auth_set_credentials (transport->auth,
- &transport->credentials);
+ if (!_dbus_auth_set_credentials (transport->auth,
+ transport->credentials))
+ return FALSE;
}
+
+ return TRUE;
}
static dbus_bool_t
while (!_dbus_transport_get_is_authenticated (transport) &&
_dbus_transport_get_is_connected (transport))
{
- exchange_credentials (transport, do_reading, do_writing);
+ if (!exchange_credentials (transport, do_reading, do_writing))
+ {
+ /* OOM */
+ oom = TRUE;
+ goto out;
+ }
if (transport->send_credentials_pending ||
transport->receive_credentials_pending)
{
/* EINTR already handled for us */
- if (errno == EAGAIN ||
- errno == EWOULDBLOCK)
+ if (_dbus_get_is_errno_eagain_or_ewouldblock ())
goto out;
else
{
_dbus_verbose ("Error writing to remote app: %s\n",
- _dbus_strerror (errno));
+ _dbus_strerror_from_errno ());
do_io_error (transport);
goto out;
}
{
socket_transport->message_bytes_written = 0;
_dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
+ _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
_dbus_connection_message_sent (transport->connection,
message);
_dbus_string_get_length (buffer) - orig_len);
_dbus_string_set_length (&socket_transport->encoded_incoming, 0);
+ _dbus_string_compact (&socket_transport->encoded_incoming, 2048);
}
}
else
{
/* EINTR already handled for us */
- if (errno == ENOMEM)
+ if (_dbus_get_is_errno_enomem ())
{
_dbus_verbose ("Out of memory in read()/do_reading()\n");
oom = TRUE;
goto out;
}
- else if (errno == EAGAIN ||
- errno == EWOULDBLOCK)
+ else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
goto out;
else
{
_dbus_verbose ("Error reading from remote app: %s\n",
- _dbus_strerror (errno));
+ _dbus_strerror_from_errno ());
do_io_error (transport);
goto out;
}
flags);
else
_dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
- watch, dbus_watch_get_fd (watch));
+ watch, dbus_watch_get_socket (watch));
}
#endif /* DBUS_ENABLE_VERBOSE_MODE */
again:
poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
- if (poll_res < 0 && errno == EINTR)
+ if (poll_res < 0 && _dbus_get_is_errno_eintr ())
goto again;
if (flags & DBUS_ITERATION_BLOCK)
else
{
_dbus_verbose ("Error from _dbus_poll(): %s\n",
- _dbus_strerror (errno));
+ _dbus_strerror_from_errno ());
}
}
NULL, NULL, NULL);
if (socket_transport->read_watch == NULL)
goto failed_3;
-
+
if (!_dbus_transport_init_base (&socket_transport->base,
&socket_vtable,
server_guid, address))
/**
* Creates a new transport for the given hostname and port.
+ * If host is NULL, it will default to localhost
*
* @param host the host to connect to
* @param port the port to connect to
+ * @param family the address family to connect to
* @param error location to store reason for failure.
* @returns a new transport, or #NULL on failure.
*/
DBusTransport*
_dbus_transport_new_for_tcp_socket (const char *host,
- dbus_int32_t port,
+ const char *port,
+ const char *family,
DBusError *error)
{
int fd;
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return NULL;
}
-
+
+ if (host == NULL)
+ host = "localhost";
+
if (!_dbus_string_append (&address, "tcp:"))
goto error;
- if (host != NULL &&
- (!_dbus_string_append (&address, "host=") ||
- !_dbus_string_append (&address, host)))
+ if (!_dbus_string_append (&address, "host=") ||
+ !_dbus_string_append (&address, host))
goto error;
if (!_dbus_string_append (&address, ",port=") ||
- !_dbus_string_append_int (&address, port))
+ !_dbus_string_append (&address, port))
goto error;
- fd = _dbus_connect_tcp_socket (host, port, error);
+ if (family != NULL &&
+ (!_dbus_string_append (&address, "family=") ||
+ !_dbus_string_append (&address, family)))
+ goto error;
+
+ fd = _dbus_connect_tcp_socket (host, port, family, error);
if (fd < 0)
{
_DBUS_ASSERT_ERROR_IS_SET (error);
_dbus_fd_set_close_on_exec (fd);
- _dbus_verbose ("Successfully connected to tcp socket %s:%d\n",
+ _dbus_verbose ("Successfully connected to tcp socket %s:%s\n",
host, port);
transport = _dbus_transport_new_for_socket (fd, NULL, &address);
return NULL;
}
+/**
+ * Opens a TCP socket transport.
+ *
+ * @param entry the address entry to try opening as a tcp transport.
+ * @param transport_p return location for the opened transport
+ * @param error error to be set
+ * @returns result of the attempt
+ */
+DBusTransportOpenResult
+_dbus_transport_open_socket(DBusAddressEntry *entry,
+ DBusTransport **transport_p,
+ DBusError *error)
+{
+ const char *method;
+
+ method = dbus_address_entry_get_method (entry);
+ _dbus_assert (method != NULL);
+
+ if (strcmp (method, "tcp") == 0)
+ {
+ const char *host = dbus_address_entry_get_value (entry, "host");
+ const char *port = dbus_address_entry_get_value (entry, "port");
+ const char *family = dbus_address_entry_get_value (entry, "family");
+
+ if (port == NULL)
+ {
+ _dbus_set_bad_address (error, "tcp", "port", NULL);
+ return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+ }
+
+ *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, error);
+ if (*transport_p == NULL)
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+ }
+ else
+ {
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ return DBUS_TRANSPORT_OPEN_OK;
+ }
+ }
+ else
+ {
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+ return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
+ }
+}
+
/** @} */