diff options
Diffstat (limited to 'dbus/dbus-connection.c')
-rw-r--r-- | dbus/dbus-connection.c | 220 |
1 files changed, 135 insertions, 85 deletions
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 3611b871..bfc27e2a 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -187,7 +187,7 @@ _dbus_connection_queue_received_message (DBusConnection *connection, return FALSE; /* If this is a reply we're waiting on, remove timeout for it */ - reply_serial = _dbus_message_get_reply_serial (message); + reply_serial = dbus_message_get_reply_serial (message); if (reply_serial != -1) { reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies, @@ -205,9 +205,11 @@ _dbus_connection_queue_received_message (DBusConnection *connection, connection->n_incoming += 1; _dbus_connection_wakeup_mainloop (connection); - - _dbus_verbose ("Incoming message %p added to queue, %d incoming\n", - message, connection->n_incoming); + + _dbus_assert (dbus_message_get_name (message) != NULL); + _dbus_verbose ("Incoming message %p (%s) added to queue, %d incoming\n", + message, dbus_message_get_name (message), + connection->n_incoming); return TRUE; } @@ -963,54 +965,88 @@ dbus_connection_get_is_authenticated (DBusConnection *connection) } /** - * Adds a message to the outgoing message queue. Does not block to - * write the message to the network; that happens asynchronously. to - * force the message to be written, call dbus_connection_flush(). + * Preallocates resources needed to send a message, allowing the message + * to be sent without the possibility of memory allocation failure. + * Allows apps to create a future guarantee that they can send + * a message regardless of memory shortages. * - * If the function fails, it returns #FALSE and returns the - * reason for failure via the result parameter. - * The result parameter can be #NULL if you aren't interested - * in the reason for the failure. - * - * @param connection the connection. - * @param message the message to write. - * @param client_serial return location for client serial. - * @param result address where result code can be placed. - * @returns #TRUE on success. + * @param connection the connection we're preallocating for. + * @returns the preallocated resources, or #NULL */ -dbus_bool_t -dbus_connection_send_message (DBusConnection *connection, - DBusMessage *message, - dbus_int32_t *client_serial, - DBusResultCode *result) +DBusPreallocatedSend* +dbus_connection_preallocate_send (DBusConnection *connection) +{ + /* we store "connection" in the link just to enforce via + * assertion that preallocated links are only used + * with the connection they were created for. + */ + return (DBusPreallocatedSend*) _dbus_list_alloc_link (connection); +} +/** + * Frees preallocated message-sending resources from + * dbus_connection_preallocate_send(). Should only + * be called if the preallocated resources are not used + * to send a message. + * + * @param connection the connection + * @param preallocated the resources + */ +void +dbus_connection_free_preallocated_send (DBusConnection *connection, + DBusPreallocatedSend *preallocated) { - dbus_int32_t serial; + DBusList *link = (DBusList*) preallocated; + _dbus_assert (link->data == connection); + _dbus_list_free_link (link); +} +/** + * Sends a message using preallocated resources. This function cannot fail. + * It works identically to dbus_connection_send() in other respects. + * Preallocated resources comes from dbus_connection_preallocate_send(). + * This function "consumes" the preallocated resources, they need not + * be freed separately. + * + * @param connection the connection + * @param preallocated the preallocated resources + * @param message the message to send + * @param client_serial return location for client serial assigned to the message + */ +void +dbus_connection_send_preallocated (DBusConnection *connection, + DBusPreallocatedSend *preallocated, + DBusMessage *message, + dbus_int32_t *client_serial) +{ + DBusList *link = (DBusList*) preallocated; + dbus_int32_t serial; + + _dbus_assert (link->data == connection); + _dbus_assert (dbus_message_get_name (message) != NULL); + dbus_mutex_lock (connection->mutex); - if (!_dbus_list_prepend (&connection->outgoing_messages, - message)) - { - dbus_set_result (result, DBUS_RESULT_NO_MEMORY); - dbus_mutex_unlock (connection->mutex); - return FALSE; - } + link->data = message; + _dbus_list_prepend_link (&connection->outgoing_messages, + link); dbus_message_ref (message); connection->n_outgoing += 1; - _dbus_verbose ("Message %p added to outgoing queue, %d pending to send\n", - message, connection->n_outgoing); + _dbus_verbose ("Message %p (%s) added to outgoing queue, %d pending to send\n", + message, + dbus_message_get_name (message), + connection->n_outgoing); - if (_dbus_message_get_client_serial (message) == -1) + if (dbus_message_get_serial (message) == -1) { serial = _dbus_connection_get_next_client_serial (connection); - _dbus_message_set_client_serial (message, serial); + _dbus_message_set_serial (message, serial); } if (client_serial) - *client_serial = _dbus_message_get_client_serial (message); + *client_serial = dbus_message_get_serial (message); _dbus_message_lock (message); @@ -1021,8 +1057,43 @@ dbus_connection_send_message (DBusConnection *connection, _dbus_connection_wakeup_mainloop (connection); dbus_mutex_unlock (connection->mutex); - - return TRUE; +} + +/** + * Adds a message to the outgoing message queue. Does not block to + * write the message to the network; that happens asynchronously. To + * force the message to be written, call dbus_connection_flush(). + * Because this only queues the message, the only reason it can + * fail is lack of memory. Even if the connection is disconnected, + * no error will be returned. + * + * If the function fails, it returns #FALSE and returns the + * reason for failure via the result parameter. + * The result parameter can be #NULL if you aren't interested + * in the reason for the failure. + * + * @param connection the connection. + * @param message the message to write. + * @param client_serial return location for client serial. + * @returns #TRUE on success. + */ +dbus_bool_t +dbus_connection_send (DBusConnection *connection, + DBusMessage *message, + dbus_int32_t *client_serial) +{ + DBusPreallocatedSend *preallocated; + + preallocated = dbus_connection_preallocate_send (connection); + if (preallocated == NULL) + { + return FALSE; + } + else + { + dbus_connection_send_preallocated (connection, preallocated, message, client_serial); + return TRUE; + } } static void @@ -1100,25 +1171,19 @@ reply_handler_data_free (ReplyHandlerData *data) * you want a very short or very long timeout. There is no way to * avoid a timeout entirely, other than passing INT_MAX for the * timeout to postpone it indefinitely. - * - * @todo I think we should rename this function family - * dbus_connection_send(), send_with_reply(), etc. (i.e. - * drop the "message" part), the names are too long. * * @param connection the connection * @param message the message to send * @param reply_handler message handler expecting the reply, or #NULL * @param timeout_milliseconds timeout in milliseconds or -1 for default - * @param result return location for result code * @returns #TRUE if the message is successfully queued, #FALSE if no memory. * */ dbus_bool_t -dbus_connection_send_message_with_reply (DBusConnection *connection, - DBusMessage *message, - DBusMessageHandler *reply_handler, - int timeout_milliseconds, - DBusResultCode *result) +dbus_connection_send_with_reply (DBusConnection *connection, + DBusMessage *message, + DBusMessageHandler *reply_handler, + int timeout_milliseconds) { DBusTimeout *timeout; ReplyHandlerData *data; @@ -1132,10 +1197,7 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, data = dbus_new0 (ReplyHandlerData, 1); if (!data) - { - dbus_set_result (result, DBUS_RESULT_NO_MEMORY); - return FALSE; - } + return FALSE; timeout = _dbus_timeout_new (timeout_milliseconds, reply_handler_timeout, data, NULL); @@ -1143,7 +1205,6 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, if (!timeout) { reply_handler_data_free (data); - dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return FALSE; } @@ -1155,8 +1216,6 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, reply_handler_data_free (data); _dbus_timeout_unref (timeout); dbus_mutex_unlock (connection->mutex); - - dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return FALSE; } @@ -1171,17 +1230,15 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, { dbus_mutex_unlock (connection->mutex); reply_handler_data_free (data); - - dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return FALSE; } data->connection_added = TRUE; /* Assign a serial to the message */ - if (_dbus_message_get_client_serial (message) == -1) + if (dbus_message_get_serial (message) == -1) { serial = _dbus_connection_get_next_client_serial (connection); - _dbus_message_set_client_serial (message, serial); + _dbus_message_set_serial (message, serial); } data->handler = reply_handler; @@ -1195,8 +1252,6 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, { dbus_mutex_unlock (connection->mutex); reply_handler_data_free (data); - - dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return FALSE; } @@ -1206,8 +1261,6 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, dbus_mutex_unlock (connection->mutex); dbus_message_unref (reply); reply_handler_data_free (data); - - dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return FALSE; } @@ -1216,23 +1269,20 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, /* Insert the serial in the pending replies hash. */ if (!_dbus_hash_table_insert_int (connection->pending_replies, serial, data)) { - dbus_set_result (result, DBUS_RESULT_NO_MEMORY); dbus_mutex_unlock (connection->mutex); - reply_handler_data_free (data); - + reply_handler_data_free (data); return FALSE; } dbus_mutex_unlock (connection->mutex); - if (!dbus_connection_send_message (connection, message, NULL, result)) + if (!dbus_connection_send (connection, message, NULL)) { /* This will free the handler data too */ _dbus_hash_table_remove_int (connection->pending_replies, serial); return FALSE; } - dbus_set_result (result, DBUS_RESULT_SUCCESS); return TRUE; } @@ -1242,9 +1292,9 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, * has been reached. This function is used to do non-reentrant "method calls." * If a reply is received, it is returned, and removed from the incoming * message queue. If it is not received, #NULL is returned and the - * result is set to #DBUS_RESULT_NO_REPLY. If something else goes + * error is set to #DBUS_ERROR_NO_REPLY. If something else goes * wrong, result is set to whatever is appropriate, such as - * #DBUS_RESULT_NO_MEMORY. + * #DBUS_ERROR_NO_MEMORY or #DBUS_ERROR_DISCONNECTED. * * @todo could use performance improvements (it keeps scanning * the whole message queue for example) and has thread issues, @@ -1253,15 +1303,15 @@ dbus_connection_send_message_with_reply (DBusConnection *connection, * @param connection the connection * @param message the message to send * @param timeout_milliseconds timeout in milliseconds or -1 for default - * @param result return location for result code + * @param error return location for error message * @returns the message that is the reply or #NULL with an error code if the * function fails. */ DBusMessage * -dbus_connection_send_message_with_reply_and_block (DBusConnection *connection, - DBusMessage *message, - int timeout_milliseconds, - DBusResultCode *result) +dbus_connection_send_with_reply_and_block (DBusConnection *connection, + DBusMessage *message, + int timeout_milliseconds, + DBusError *error) { dbus_int32_t client_serial; DBusList *link; @@ -1279,8 +1329,11 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6) timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6; - if (!dbus_connection_send_message (connection, message, &client_serial, result)) - return NULL; + if (!dbus_connection_send (connection, message, &client_serial)) + { + _DBUS_SET_OOM (error); + return NULL; + } message = NULL; @@ -1318,13 +1371,10 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio { DBusMessage *reply = link->data; - if (_dbus_message_get_reply_serial (reply) == client_serial) + if (dbus_message_get_reply_serial (reply) == client_serial) { _dbus_list_remove_link (&connection->incoming_messages, link); dbus_message_ref (reply); - - if (result) - *result = DBUS_RESULT_SUCCESS; dbus_mutex_unlock (connection->mutex); return reply; @@ -1345,14 +1395,14 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio (end_tv_usec - tv_usec) / 1000; _dbus_verbose ("%d milliseconds remain\n", timeout_milliseconds); _dbus_assert (timeout_milliseconds > 0); - + goto block_again; /* not expired yet */ } - + if (dbus_connection_get_is_connected (connection)) - dbus_set_result (result, DBUS_RESULT_NO_REPLY); + dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply"); else - dbus_set_result (result, DBUS_RESULT_DISCONNECTED); + dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply"); dbus_mutex_unlock (connection->mutex); @@ -1631,7 +1681,7 @@ dbus_connection_dispatch_message (DBusConnection *connection) result = DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; - reply_serial = _dbus_message_get_reply_serial (message); + reply_serial = dbus_message_get_reply_serial (message); reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies, reply_serial); |