diff options
author | Havoc Pennington <hp@redhat.com> | 2003-03-17 01:54:37 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2003-03-17 01:54:37 +0000 |
commit | b4a1100f4f81534e2aac0141afda750f318223d4 (patch) | |
tree | 9573e47181fc32c40f4784df0d22b2c6ee4143c4 /dbus/dbus-transport.c | |
parent | 3caaa342e8db2cba690bb9e1a228ef3862e203d8 (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.c | 128 |
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; |