summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-transport.c
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-03-17 01:54:37 +0000
committerHavoc Pennington <hp@redhat.com>2003-03-17 01:54:37 +0000
commitb4a1100f4f81534e2aac0141afda750f318223d4 (patch)
tree9573e47181fc32c40f4784df0d22b2c6ee4143c4 /dbus/dbus-transport.c
parent3caaa342e8db2cba690bb9e1a228ef3862e203d8 (diff)
2003-03-16 Havoc Pennington <hp@pobox.com>
* dbus/dbus-watch.c (_dbus_watch_new): handle failure to malloc the watch * dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new): add some missing dbus_set_result * bus/dispatch.c (bus_dispatch_add_connection): handle failure to alloc the DBusMessageHandler * dbus/dbus-transport.c (_dbus_transport_disconnect): don't ref the transport here, since we call this from the finalizer; it resulted in a double-finalize. * dbus/dbus-transport.c (_dbus_transport_disconnect): fix a bug where we tried to use transport->connection that was NULL, happened when transport was disconnected early on due to OOM * bus/*.c: adapt to handle OOM for watches/timeouts * dbus/dbus-transport-unix.c: port to handle OOM during watch handling * dbus/dbus-auth.c (_dbus_auth_get_unused_bytes): return a reference to unused bytes instead of a copy * dbus/dbus-server.c (dbus_server_handle_watch): return FALSE for out of memory * dbus/dbus-connection.c (dbus_connection_handle_watch): return FALSE on OOM * dbus/dbus-timeout.c (dbus_timeout_handle): return FALSE for out of memory
Diffstat (limited to 'dbus/dbus-transport.c')
-rw-r--r--dbus/dbus-transport.c128
1 files changed, 120 insertions, 8 deletions
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index b2355ea5..8087f5b0 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -265,6 +265,8 @@ _dbus_transport_open (const char *address,
void
_dbus_transport_ref (DBusTransport *transport)
{
+ _dbus_assert (transport->refcount > 0);
+
transport->refcount += 1;
}
@@ -306,14 +308,12 @@ _dbus_transport_disconnect (DBusTransport *transport)
if (transport->disconnected)
return;
- _dbus_transport_ref (transport);
(* transport->vtable->disconnect) (transport);
transport->disconnected = TRUE;
- _dbus_connection_notify_disconnected (transport->connection);
-
- _dbus_transport_unref (transport);
+ if (transport->connection)
+ _dbus_connection_notify_disconnected (transport->connection);
}
/**
@@ -394,30 +394,35 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
* @param transport the transport.
* @param watch the watch.
* @param condition the current state of the watched file descriptor.
+ * @returns #FALSE if not enough memory to fully handle the watch
*/
-void
+dbus_bool_t
_dbus_transport_handle_watch (DBusTransport *transport,
DBusWatch *watch,
unsigned int condition)
{
+ dbus_bool_t retval;
+
_dbus_assert (transport->vtable->handle_watch != NULL);
if (transport->disconnected)
- return;
+ return TRUE;
if (dbus_watch_get_fd (watch) < 0)
{
_dbus_warn ("Tried to handle an invalidated watch; this watch should have been removed\n");
- return;
+ return TRUE;
}
_dbus_watch_sanitize_condition (watch, &condition);
_dbus_transport_ref (transport);
_dbus_watch_ref (watch);
- (* transport->vtable->handle_watch) (transport, watch, condition);
+ retval = (* transport->vtable->handle_watch) (transport, watch, condition);
_dbus_watch_unref (watch);
_dbus_transport_unref (transport);
+
+ return retval;
}
/**
@@ -506,6 +511,98 @@ _dbus_transport_do_iteration (DBusTransport *transport,
_dbus_transport_unref (transport);
}
+static dbus_bool_t
+recover_unused_bytes (DBusTransport *transport)
+{
+ if (_dbus_auth_do_work (transport->auth) != DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES)
+ return TRUE;
+
+ if (_dbus_auth_needs_decoding (transport->auth))
+ {
+ DBusString plaintext;
+ const DBusString *encoded;
+ DBusString *buffer;
+ int orig_len;
+
+ if (!_dbus_string_init (&plaintext, _DBUS_INT_MAX))
+ goto nomem;
+
+ _dbus_auth_get_unused_bytes (transport->auth,
+ &encoded);
+
+ if (!_dbus_auth_decode_data (transport->auth,
+ encoded, &plaintext))
+ {
+ _dbus_string_free (&plaintext);
+ goto nomem;
+ }
+
+ _dbus_message_loader_get_buffer (transport->loader,
+ &buffer);
+
+ orig_len = _dbus_string_get_length (buffer);
+
+ if (!_dbus_string_move (&plaintext, 0, buffer,
+ orig_len))
+ {
+ _dbus_string_free (&plaintext);
+ goto nomem;
+ }
+
+ _dbus_verbose (" %d unused bytes sent to message loader\n",
+ _dbus_string_get_length (buffer) -
+ orig_len);
+
+ _dbus_message_loader_return_buffer (transport->loader,
+ buffer,
+ _dbus_string_get_length (buffer) -
+ orig_len);
+
+ _dbus_auth_delete_unused_bytes (transport->auth);
+
+ _dbus_string_free (&plaintext);
+ }
+ else
+ {
+ const DBusString *bytes;
+ DBusString *buffer;
+ int orig_len;
+ dbus_bool_t succeeded;
+
+ _dbus_message_loader_get_buffer (transport->loader,
+ &buffer);
+
+ orig_len = _dbus_string_get_length (buffer);
+
+ _dbus_auth_get_unused_bytes (transport->auth,
+ &bytes);
+
+ succeeded = TRUE;
+ if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
+ succeeded = FALSE;
+
+ _dbus_verbose (" %d unused bytes sent to message loader\n",
+ _dbus_string_get_length (buffer) -
+ orig_len);
+
+ _dbus_message_loader_return_buffer (transport->loader,
+ buffer,
+ _dbus_string_get_length (buffer) -
+ orig_len);
+
+ if (succeeded)
+ _dbus_auth_delete_unused_bytes (transport->auth);
+ else
+ goto nomem;
+ }
+
+ return TRUE;
+
+ nomem:
+ _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
+ return FALSE;
+}
+
/**
* Reports our current dispatch status (whether there's buffered
* data to be queued as messages, or not, or we need memory).
@@ -519,6 +616,21 @@ _dbus_transport_get_dispatch_status (DBusTransport *transport)
if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
return DBUS_DISPATCH_COMPLETE; /* complete for now */
+ if (!_dbus_transport_get_is_authenticated (transport))
+ {
+ switch (_dbus_auth_do_work (transport->auth))
+ {
+ case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
+ return DBUS_DISPATCH_NEED_MEMORY;
+ case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
+ if (!recover_unused_bytes (transport))
+ return DBUS_DISPATCH_NEED_MEMORY;
+ break;
+ default:
+ break;
+ }
+ }
+
if (!_dbus_message_loader_queue_messages (transport->loader))
return DBUS_DISPATCH_NEED_MEMORY;