+ DBusTimeout *timeout;
+ ReplyHandlerData *data;
+ DBusMessage *reply;
+ DBusList *reply_link;
+ dbus_int32_t serial = -1;
+
+ if (timeout_milliseconds == -1)
+ timeout_milliseconds = DEFAULT_TIMEOUT_VALUE;
+
+ data = dbus_new0 (ReplyHandlerData, 1);
+
+ if (!data)
+ {
+ dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ return FALSE;
+ }
+
+ timeout = _dbus_timeout_new (timeout_milliseconds, reply_handler_timeout,
+ data, NULL);
+
+ if (!timeout)
+ {
+ reply_handler_data_free (data);
+ dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ return FALSE;
+ }
+
+ dbus_mutex_lock (connection->mutex);
+
+ /* Add timeout */
+ if (!_dbus_connection_add_timeout (connection, timeout))
+ {
+ reply_handler_data_free (data);
+ _dbus_timeout_unref (timeout);
+ dbus_mutex_unlock (connection->mutex);
+
+ dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ return FALSE;
+ }
+
+ /* The connection now owns the reference to the timeout. */
+ _dbus_timeout_unref (timeout);
+
+ data->timeout_added = TRUE;
+ data->timeout = timeout;
+ data->connection = connection;
+
+ if (!_dbus_message_handler_add_connection (reply_handler, 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)
+ {
+ serial = _dbus_connection_get_next_client_serial (connection);
+ _dbus_message_set_client_serial (message, serial);
+ }
+
+ data->handler = reply_handler;
+ data->serial = serial;
+
+ dbus_message_handler_ref (reply_handler);
+
+ reply = dbus_message_new_error_reply (message, DBUS_ERROR_NO_REPLY,
+ "No reply within specified time");
+ if (!reply)
+ {
+ dbus_mutex_unlock (connection->mutex);
+ reply_handler_data_free (data);
+
+ dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ return FALSE;
+ }
+
+ reply_link = _dbus_list_alloc_link (reply);
+ if (!reply)
+ {
+ dbus_mutex_unlock (connection->mutex);
+ dbus_message_unref (reply);
+ reply_handler_data_free (data);
+
+ dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ return FALSE;
+ }
+
+ data->timeout_link = reply_link;
+
+ /* 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);
+
+ return FALSE;
+ }
+
+ dbus_mutex_unlock (connection->mutex);
+
+ if (!dbus_connection_send_message (connection, message, NULL, result))
+ {
+ /* 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;