D-Bus  1.10.12
dbus-message.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-validate.h"
00029 #include "dbus-marshal-byteswap.h"
00030 #include "dbus-marshal-header.h"
00031 #include "dbus-signature.h"
00032 #include "dbus-message-private.h"
00033 #include "dbus-object-tree.h"
00034 #include "dbus-memory.h"
00035 #include "dbus-list.h"
00036 #include "dbus-threads-internal.h"
00037 #ifdef HAVE_UNIX_FD_PASSING
00038 #include "dbus-sysdeps.h"
00039 #include "dbus-sysdeps-unix.h"
00040 #endif
00041 
00042 #include <string.h>
00043 
00044 #define _DBUS_TYPE_IS_STRINGLIKE(type) \
00045   (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
00046    type == DBUS_TYPE_OBJECT_PATH)
00047 
00048 static void dbus_message_finalize (DBusMessage *message);
00049 
00060 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00061 static dbus_bool_t
00062 _dbus_enable_message_cache (void)
00063 {
00064   static int enabled = -1;
00065 
00066   if (enabled < 0)
00067     {
00068       const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
00069 
00070       enabled = TRUE;
00071 
00072       if (s && *s)
00073         {
00074           if (*s == '0')
00075             enabled = FALSE;
00076           else if (*s == '1')
00077             enabled = TRUE;
00078           else
00079             _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
00080                 s);
00081         }
00082     }
00083 
00084   return enabled;
00085 }
00086 #else
00087     /* constant expression, should be optimized away */
00088 #   define _dbus_enable_message_cache() (TRUE)
00089 #endif
00090 
00091 #ifndef _dbus_message_trace_ref
00092 void
00093 _dbus_message_trace_ref (DBusMessage *message,
00094                          int          old_refcount,
00095                          int          new_refcount,
00096                          const char  *why)
00097 {
00098   static int enabled = -1;
00099 
00100   _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
00101       "DBUS_MESSAGE_TRACE", &enabled);
00102 }
00103 #endif
00104 
00105 /* Not thread locked, but strictly const/read-only so should be OK
00106  */
00108 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
00109 
00110 /* these have wacky values to help trap uninitialized iterators;
00111  * but has to fit in 3 bits
00112  */
00113 enum {
00114   DBUS_MESSAGE_ITER_TYPE_READER = 3,
00115   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
00116 };
00117 
00119 typedef struct DBusMessageRealIter DBusMessageRealIter;
00120 
00126 struct DBusMessageRealIter
00127 {
00128   DBusMessage *message; 
00129   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 
00130   dbus_uint32_t iter_type : 3;      
00131   dbus_uint32_t sig_refcount : 8;   
00132   union
00133   {
00134     DBusTypeWriter writer; 
00135     DBusTypeReader reader; 
00136   } u; 
00137 };
00138 
00144 typedef struct
00145 {
00146   void *dummy1;
00147   void *dummy2;
00148   dbus_uint32_t dummy3;
00149   int dummy4;
00150   int dummy5;
00151   int dummy6;
00152   int dummy7;
00153   int dummy8;
00154   int dummy9;
00155   int dummy10;
00156   int dummy11;
00157   int pad1;
00158   int pad2;
00159   void *pad3;
00160 } DBusMessageIter_1_10_0;
00161 
00162 static void
00163 get_const_signature (DBusHeader        *header,
00164                      const DBusString **type_str_p,
00165                      int               *type_pos_p)
00166 {
00167   if (_dbus_header_get_field_raw (header,
00168                                   DBUS_HEADER_FIELD_SIGNATURE,
00169                                   type_str_p,
00170                                   type_pos_p))
00171     {
00172       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00173     }
00174   else
00175     {
00176       *type_str_p = &_dbus_empty_signature_str;
00177       *type_pos_p = 0;
00178     }
00179 }
00180 
00186 static void
00187 _dbus_message_byteswap (DBusMessage *message)
00188 {
00189   const DBusString *type_str;
00190   int type_pos;
00191   char byte_order;
00192 
00193   byte_order = _dbus_header_get_byte_order (&message->header);
00194 
00195   if (byte_order == DBUS_COMPILER_BYTE_ORDER)
00196     return;
00197 
00198   _dbus_verbose ("Swapping message into compiler byte order\n");
00199   
00200   get_const_signature (&message->header, &type_str, &type_pos);
00201   
00202   _dbus_marshal_byteswap (type_str, type_pos,
00203                           byte_order,
00204                           DBUS_COMPILER_BYTE_ORDER,
00205                           &message->body, 0);
00206 
00207   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00208   _dbus_assert (_dbus_header_get_byte_order (&message->header) ==
00209                 DBUS_COMPILER_BYTE_ORDER);
00210 }
00211 
00218 #define ensure_byte_order(message) _dbus_message_byteswap (message)
00219 
00230 void
00231 _dbus_message_get_network_data (DBusMessage          *message,
00232                                 const DBusString    **header,
00233                                 const DBusString    **body)
00234 {
00235   _dbus_assert (message->locked);
00236 
00237   *header = &message->header.data;
00238   *body = &message->body;
00239 }
00240 
00250 void _dbus_message_get_unix_fds(DBusMessage *message,
00251                                 const int  **fds,
00252                                 unsigned    *n_fds)
00253 {
00254   _dbus_assert (message->locked);
00255 
00256 #ifdef HAVE_UNIX_FD_PASSING
00257   *fds = message->unix_fds;
00258   *n_fds = message->n_unix_fds;
00259 #else
00260   *fds = NULL;
00261   *n_fds = 0;
00262 #endif
00263 }
00264 
00276 void 
00277 dbus_message_set_serial (DBusMessage   *message,
00278                          dbus_uint32_t  serial)
00279 {
00280   _dbus_return_if_fail (message != NULL);
00281   _dbus_return_if_fail (!message->locked);
00282 
00283   _dbus_header_set_serial (&message->header, serial);
00284 }
00285 
00302 void
00303 _dbus_message_add_counter_link (DBusMessage  *message,
00304                                 DBusList     *link)
00305 {
00306   /* right now we don't recompute the delta when message
00307    * size changes, and that's OK for current purposes
00308    * I think, but could be important to change later.
00309    * Do recompute it whenever there are no outstanding counters,
00310    * since it's basically free.
00311    */
00312   if (message->counters == NULL)
00313     {
00314       message->size_counter_delta =
00315         _dbus_string_get_length (&message->header.data) +
00316         _dbus_string_get_length (&message->body);
00317 
00318 #ifdef HAVE_UNIX_FD_PASSING
00319       message->unix_fd_counter_delta = message->n_unix_fds;
00320 #endif
00321 
00322 #if 0
00323       _dbus_verbose ("message has size %ld\n",
00324                      message->size_counter_delta);
00325 #endif
00326     }
00327 
00328   _dbus_list_append_link (&message->counters, link);
00329 
00330   _dbus_counter_adjust_size (link->data, message->size_counter_delta);
00331 
00332 #ifdef HAVE_UNIX_FD_PASSING
00333   _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
00334 #endif
00335 }
00336 
00351 dbus_bool_t
00352 _dbus_message_add_counter (DBusMessage *message,
00353                            DBusCounter *counter)
00354 {
00355   DBusList *link;
00356 
00357   link = _dbus_list_alloc_link (counter);
00358   if (link == NULL)
00359     return FALSE;
00360 
00361   _dbus_counter_ref (counter);
00362   _dbus_message_add_counter_link (message, link);
00363 
00364   return TRUE;
00365 }
00366 
00374 void
00375 _dbus_message_remove_counter (DBusMessage  *message,
00376                               DBusCounter  *counter)
00377 {
00378   DBusList *link;
00379 
00380   link = _dbus_list_find_last (&message->counters,
00381                                counter);
00382   _dbus_assert (link != NULL);
00383 
00384   _dbus_list_remove_link (&message->counters, link);
00385 
00386   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00387 
00388 #ifdef HAVE_UNIX_FD_PASSING
00389   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00390 #endif
00391 
00392   _dbus_counter_notify (counter);
00393   _dbus_counter_unref (counter);
00394 }
00395 
00406 void
00407 dbus_message_lock (DBusMessage  *message)
00408 {
00409   if (!message->locked)
00410     {
00411       _dbus_header_update_lengths (&message->header,
00412                                    _dbus_string_get_length (&message->body));
00413 
00414       /* must have a signature if you have a body */
00415       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00416                     dbus_message_get_signature (message) != NULL);
00417 
00418       message->locked = TRUE;
00419     }
00420 }
00421 
00422 static dbus_bool_t
00423 set_or_delete_string_field (DBusMessage *message,
00424                             int          field,
00425                             int          typecode,
00426                             const char  *value)
00427 {
00428   if (value == NULL)
00429     return _dbus_header_delete_field (&message->header, field);
00430   else
00431     return _dbus_header_set_field_basic (&message->header,
00432                                          field,
00433                                          typecode,
00434                                          &value);
00435 }
00436 
00437 #if 0
00438 /* Probably we don't need to use this */
00462 static dbus_bool_t
00463 _dbus_message_set_signature (DBusMessage *message,
00464                              const char  *signature)
00465 {
00466   _dbus_return_val_if_fail (message != NULL, FALSE);
00467   _dbus_return_val_if_fail (!message->locked, FALSE);
00468   _dbus_return_val_if_fail (signature == NULL ||
00469                             _dbus_check_is_valid_signature (signature));
00470   /* can't delete the signature if you have a message body */
00471   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00472                             signature != NULL);
00473 
00474   return set_or_delete_string_field (message,
00475                                      DBUS_HEADER_FIELD_SIGNATURE,
00476                                      DBUS_TYPE_SIGNATURE,
00477                                      signature);
00478 }
00479 #endif
00480 
00481 /* Message Cache
00482  *
00483  * We cache some DBusMessage to reduce the overhead of allocating
00484  * them.  In my profiling this consistently made about an 8%
00485  * difference.  It avoids the malloc for the message, the malloc for
00486  * the slot list, the malloc for the header string and body string,
00487  * and the associated free() calls. It does introduce another global
00488  * lock which could be a performance issue in certain cases.
00489  *
00490  * For the echo client/server the round trip time goes from around
00491  * .000077 to .000069 with the message cache on my laptop. The sysprof
00492  * change is as follows (numbers are cumulative percentage):
00493  *
00494  *  with message cache implemented as array as it is now (0.000069 per):
00495  *    new_empty_header           1.46
00496  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00497  *      mutex_unlock             0.25
00498  *      self                     0.41
00499  *    unref                      2.24
00500  *      self                     0.68
00501  *      list_clear               0.43
00502  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00503  *      mutex_unlock             0.25
00504  *
00505  *  with message cache implemented as list (0.000070 per roundtrip):
00506  *    new_empty_header           2.72
00507  *      list_pop_first           1.88
00508  *    unref                      3.3
00509  *      list_prepend             1.63
00510  *
00511  * without cache (0.000077 per roundtrip):
00512  *    new_empty_header           6.7
00513  *      string_init_preallocated 3.43
00514  *        dbus_malloc            2.43
00515  *      dbus_malloc0             2.59
00516  *
00517  *    unref                      4.02
00518  *      string_free              1.82
00519  *        dbus_free              1.63
00520  *      dbus_free                0.71
00521  *
00522  * If you implement the message_cache with a list, the primary reason
00523  * it's slower is that you add another thread lock (on the DBusList
00524  * mempool).
00525  */
00526 
00528 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00529 
00531 #define MAX_MESSAGE_CACHE_SIZE    5
00532 
00533 /* Protected by _DBUS_LOCK (message_cache) */
00534 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00535 static int message_cache_count = 0;
00536 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00537 
00538 static void
00539 dbus_message_cache_shutdown (void *data)
00540 {
00541   int i;
00542 
00543   if (!_DBUS_LOCK (message_cache))
00544     _dbus_assert_not_reached ("we would have initialized global locks "
00545         "before registering a shutdown function");
00546 
00547   i = 0;
00548   while (i < MAX_MESSAGE_CACHE_SIZE)
00549     {
00550       if (message_cache[i])
00551         dbus_message_finalize (message_cache[i]);
00552 
00553       ++i;
00554     }
00555 
00556   message_cache_count = 0;
00557   message_cache_shutdown_registered = FALSE;
00558 
00559   _DBUS_UNLOCK (message_cache);
00560 }
00561 
00569 static DBusMessage*
00570 dbus_message_get_cached (void)
00571 {
00572   DBusMessage *message;
00573   int i;
00574 
00575   message = NULL;
00576 
00577   if (!_DBUS_LOCK (message_cache))
00578     {
00579       /* we'd have initialized global locks before caching anything,
00580        * so there can't be anything in the cache */
00581       return NULL;
00582     }
00583 
00584   _dbus_assert (message_cache_count >= 0);
00585 
00586   if (message_cache_count == 0)
00587     {
00588       _DBUS_UNLOCK (message_cache);
00589       return NULL;
00590     }
00591 
00592   /* This is not necessarily true unless count > 0, and
00593    * message_cache is uninitialized until the shutdown is
00594    * registered
00595    */
00596   _dbus_assert (message_cache_shutdown_registered);
00597 
00598   i = 0;
00599   while (i < MAX_MESSAGE_CACHE_SIZE)
00600     {
00601       if (message_cache[i])
00602         {
00603           message = message_cache[i];
00604           message_cache[i] = NULL;
00605           message_cache_count -= 1;
00606           break;
00607         }
00608       ++i;
00609     }
00610   _dbus_assert (message_cache_count >= 0);
00611   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00612   _dbus_assert (message != NULL);
00613 
00614   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00615 
00616   _dbus_assert (message->counters == NULL);
00617   
00618   _DBUS_UNLOCK (message_cache);
00619 
00620   return message;
00621 }
00622 
00623 #ifdef HAVE_UNIX_FD_PASSING
00624 static void
00625 close_unix_fds(int *fds, unsigned *n_fds)
00626 {
00627   DBusError e;
00628   unsigned int i;
00629 
00630   if (*n_fds <= 0)
00631     return;
00632 
00633   dbus_error_init(&e);
00634 
00635   for (i = 0; i < *n_fds; i++)
00636     {
00637       if (!_dbus_close(fds[i], &e))
00638         {
00639           _dbus_warn("Failed to close file descriptor: %s\n", e.message);
00640           dbus_error_free(&e);
00641         }
00642     }
00643 
00644   *n_fds = 0;
00645 
00646   /* We don't free the array here, in case we can recycle it later */
00647 }
00648 #endif
00649 
00650 static void
00651 free_counter (void *element,
00652               void *data)
00653 {
00654   DBusCounter *counter = element;
00655   DBusMessage *message = data;
00656 
00657   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00658 #ifdef HAVE_UNIX_FD_PASSING
00659   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00660 #endif
00661 
00662   _dbus_counter_notify (counter);
00663   _dbus_counter_unref (counter);
00664 }
00665 
00671 static void
00672 dbus_message_cache_or_finalize (DBusMessage *message)
00673 {
00674   dbus_bool_t was_cached;
00675   int i;
00676 
00677   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00678 
00679   /* This calls application code and has to be done first thing
00680    * without holding the lock
00681    */
00682   _dbus_data_slot_list_clear (&message->slot_list);
00683 
00684   _dbus_list_foreach (&message->counters,
00685                       free_counter, message);
00686   _dbus_list_clear (&message->counters);
00687 
00688 #ifdef HAVE_UNIX_FD_PASSING
00689   close_unix_fds(message->unix_fds, &message->n_unix_fds);
00690 #endif
00691 
00692   was_cached = FALSE;
00693 
00694   if (!_DBUS_LOCK (message_cache))
00695     {
00696       /* The only way to get a non-null message goes through
00697        * dbus_message_get_cached() which takes the lock. */
00698       _dbus_assert_not_reached ("we would have initialized global locks "
00699           "the first time we constructed a message");
00700     }
00701 
00702   if (!message_cache_shutdown_registered)
00703     {
00704       _dbus_assert (message_cache_count == 0);
00705 
00706       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00707         goto out;
00708 
00709       i = 0;
00710       while (i < MAX_MESSAGE_CACHE_SIZE)
00711         {
00712           message_cache[i] = NULL;
00713           ++i;
00714         }
00715 
00716       message_cache_shutdown_registered = TRUE;
00717     }
00718 
00719   _dbus_assert (message_cache_count >= 0);
00720 
00721   if (!_dbus_enable_message_cache ())
00722     goto out;
00723 
00724   if ((_dbus_string_get_length (&message->header.data) +
00725        _dbus_string_get_length (&message->body)) >
00726       MAX_MESSAGE_SIZE_TO_CACHE)
00727     goto out;
00728 
00729   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00730     goto out;
00731 
00732   /* Find empty slot */
00733   i = 0;
00734   while (message_cache[i] != NULL)
00735     ++i;
00736 
00737   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00738 
00739   _dbus_assert (message_cache[i] == NULL);
00740   message_cache[i] = message;
00741   message_cache_count += 1;
00742   was_cached = TRUE;
00743 #ifndef DBUS_DISABLE_CHECKS
00744   message->in_cache = TRUE;
00745 #endif
00746 
00747  out:
00748   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00749 
00750   _DBUS_UNLOCK (message_cache);
00751   
00752   if (!was_cached)
00753     dbus_message_finalize (message);
00754 }
00755 
00756 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
00757 static dbus_bool_t
00758 _dbus_message_iter_check (DBusMessageRealIter *iter)
00759 {
00760   char byte_order;
00761 
00762   if (iter == NULL)
00763     {
00764       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00765       return FALSE;
00766     }
00767 
00768   byte_order = _dbus_header_get_byte_order (&iter->message->header);
00769 
00770   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00771     {
00772       if (iter->u.reader.byte_order != byte_order)
00773         {
00774           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00775           return FALSE;
00776         }
00777       /* because we swap the message into compiler order when you init an iter */
00778       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00779     }
00780   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00781     {
00782       if (iter->u.writer.byte_order != byte_order)
00783         {
00784           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00785           return FALSE;
00786         }
00787       /* because we swap the message into compiler order when you init an iter */
00788       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00789     }
00790   else
00791     {
00792       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00793       return FALSE;
00794     }
00795 
00796   if (iter->changed_stamp != iter->message->changed_stamp)
00797     {
00798       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00799       return FALSE;
00800     }
00801 
00802   return TRUE;
00803 }
00804 #endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
00805 
00818 dbus_bool_t
00819 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00820                                     DBusError       *error,
00821                                     int              first_arg_type,
00822                                     va_list          var_args)
00823 {
00824   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00825   int spec_type, msg_type, i, j;
00826   dbus_bool_t retval;
00827   va_list copy_args;
00828 
00829   _dbus_assert (_dbus_message_iter_check (real));
00830 
00831   retval = FALSE;
00832 
00833   spec_type = first_arg_type;
00834   i = 0;
00835 
00836   /* copy var_args first, then we can do another iteration over it to
00837    * free memory and close unix fds if parse failed at some point.
00838    */
00839   DBUS_VA_COPY (copy_args, var_args);
00840 
00841   while (spec_type != DBUS_TYPE_INVALID)
00842     {
00843       msg_type = dbus_message_iter_get_arg_type (iter);
00844 
00845       if (msg_type != spec_type)
00846         {
00847           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00848                           "Argument %d is specified to be of type \"%s\", but "
00849                           "is actually of type \"%s\"\n", i,
00850                           _dbus_type_to_string (spec_type),
00851                           _dbus_type_to_string (msg_type));
00852 
00853           goto out;
00854         }
00855 
00856       if (spec_type == DBUS_TYPE_UNIX_FD)
00857         {
00858 #ifdef HAVE_UNIX_FD_PASSING
00859           DBusBasicValue idx;
00860           int *pfd, nfd;
00861 
00862           pfd = va_arg (var_args, int*);
00863           _dbus_assert(pfd);
00864 
00865           _dbus_type_reader_read_basic(&real->u.reader, &idx);
00866 
00867           if (idx.u32 >= real->message->n_unix_fds)
00868             {
00869               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
00870                               "Message refers to file descriptor at index %i,"
00871                               "but has only %i descriptors attached.\n",
00872                               idx.u32,
00873                               real->message->n_unix_fds);
00874               goto out;
00875             }
00876 
00877           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
00878             goto out;
00879 
00880           *pfd = nfd;
00881 #else
00882           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00883                           "Platform does not support file desciptor passing.\n");
00884           goto out;
00885 #endif
00886         }
00887       else if (dbus_type_is_basic (spec_type))
00888         {
00889           DBusBasicValue *ptr;
00890 
00891           ptr = va_arg (var_args, DBusBasicValue*);
00892 
00893           _dbus_assert (ptr != NULL);
00894 
00895           _dbus_type_reader_read_basic (&real->u.reader,
00896                                         ptr);
00897         }
00898       else if (spec_type == DBUS_TYPE_ARRAY)
00899         {
00900           int element_type;
00901           int spec_element_type;
00902           const DBusBasicValue **ptr;
00903           int *n_elements_p;
00904           DBusTypeReader array;
00905 
00906           spec_element_type = va_arg (var_args, int);
00907           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00908 
00909           if (spec_element_type != element_type)
00910             {
00911               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00912                               "Argument %d is specified to be an array of \"%s\", but "
00913                               "is actually an array of \"%s\"\n",
00914                               i,
00915                               _dbus_type_to_string (spec_element_type),
00916                               _dbus_type_to_string (element_type));
00917 
00918               goto out;
00919             }
00920 
00921           if (dbus_type_is_fixed (spec_element_type) &&
00922               element_type != DBUS_TYPE_UNIX_FD)
00923             {
00924               ptr = va_arg (var_args, const DBusBasicValue**);
00925               n_elements_p = va_arg (var_args, int*);
00926 
00927               _dbus_assert (ptr != NULL);
00928               _dbus_assert (n_elements_p != NULL);
00929 
00930               _dbus_type_reader_recurse (&real->u.reader, &array);
00931 
00932               _dbus_type_reader_read_fixed_multi (&array,
00933                                                   (void *) ptr, n_elements_p);
00934             }
00935           else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
00936             {
00937               char ***str_array_p;
00938               int n_elements;
00939               char **str_array;
00940 
00941               str_array_p = va_arg (var_args, char***);
00942               n_elements_p = va_arg (var_args, int*);
00943 
00944               _dbus_assert (str_array_p != NULL);
00945               _dbus_assert (n_elements_p != NULL);
00946 
00947               /* Count elements in the array */
00948               _dbus_type_reader_recurse (&real->u.reader, &array);
00949 
00950               n_elements = 0;
00951               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00952                 {
00953                   ++n_elements;
00954                   _dbus_type_reader_next (&array);
00955                 }
00956 
00957               str_array = dbus_new0 (char*, n_elements + 1);
00958               if (str_array == NULL)
00959                 {
00960                   _DBUS_SET_OOM (error);
00961                   goto out;
00962                 }
00963 
00964               /* Now go through and dup each string */
00965               _dbus_type_reader_recurse (&real->u.reader, &array);
00966 
00967               j = 0;
00968               while (j < n_elements)
00969                 {
00970                   const char *s;
00971                   _dbus_type_reader_read_basic (&array,
00972                                                 (void *) &s);
00973                   
00974                   str_array[j] = _dbus_strdup (s);
00975                   if (str_array[j] == NULL)
00976                     {
00977                       dbus_free_string_array (str_array);
00978                       _DBUS_SET_OOM (error);
00979                       goto out;
00980                     }
00981                   
00982                   ++j;
00983                   
00984                   if (!_dbus_type_reader_next (&array))
00985                     _dbus_assert (j == n_elements);
00986                 }
00987 
00988               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00989               _dbus_assert (j == n_elements);
00990               _dbus_assert (str_array[j] == NULL);
00991 
00992               *str_array_p = str_array;
00993               *n_elements_p = n_elements;
00994             }
00995 #ifndef DBUS_DISABLE_CHECKS
00996           else
00997             {
00998               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00999                           _DBUS_FUNCTION_NAME);
01000               goto out;
01001             }
01002 #endif
01003         }
01004 #ifndef DBUS_DISABLE_CHECKS
01005       else
01006         {
01007           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
01008                       _DBUS_FUNCTION_NAME);
01009           goto out;
01010         }
01011 #endif
01012 
01013       /* how many arguments already handled */
01014       i++;
01015 
01016       spec_type = va_arg (var_args, int);
01017       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
01018         {
01019           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01020                           "Message has only %d arguments, but more were expected", i);
01021           goto out;
01022         }
01023     }
01024 
01025   retval = TRUE;
01026 
01027  out:
01028   /* there may memory or unix fd leak in the above iteration if parse failed.
01029    * so we have another iteration over copy_args to free memory and close
01030    * unix fds.
01031    */
01032   if (!retval)
01033     {
01034       spec_type = first_arg_type;
01035       j = 0;
01036 
01037       while (j < i)
01038         {
01039           if (spec_type == DBUS_TYPE_UNIX_FD)
01040             {
01041 #ifdef HAVE_UNIX_FD_PASSING
01042               int *pfd;
01043 
01044               pfd = va_arg (copy_args, int *);
01045               _dbus_assert(pfd);
01046               if (*pfd >= 0)
01047                 {
01048                   _dbus_close (*pfd, NULL);
01049                   *pfd = -1;
01050                 }
01051 #endif
01052             }
01053           else if (dbus_type_is_basic (spec_type))
01054             {
01055               /* move the index forward */
01056               va_arg (copy_args, DBusBasicValue *);
01057             }
01058           else if (spec_type == DBUS_TYPE_ARRAY)
01059             {
01060               int spec_element_type;
01061 
01062               spec_element_type = va_arg (copy_args, int);
01063               if (dbus_type_is_fixed (spec_element_type))
01064                 {
01065                   /* move the index forward */
01066                   va_arg (copy_args, const DBusBasicValue **);
01067                   va_arg (copy_args, int *);
01068                 }
01069               else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
01070                 {
01071                   char ***str_array_p;
01072 
01073                   str_array_p = va_arg (copy_args, char ***);
01074                   /* move the index forward */
01075                   va_arg (copy_args, int *);
01076                   _dbus_assert (str_array_p != NULL);
01077                   dbus_free_string_array (*str_array_p);
01078                   *str_array_p = NULL;
01079                 }
01080             }
01081 
01082           spec_type = va_arg (copy_args, int);
01083           j++;
01084         }
01085     }
01086 
01087   va_end (copy_args);
01088   return retval;
01089 }
01090 
01149 dbus_uint32_t
01150 dbus_message_get_serial (DBusMessage *message)
01151 {
01152   _dbus_return_val_if_fail (message != NULL, 0);
01153 
01154   return _dbus_header_get_serial (&message->header);
01155 }
01156 
01165 dbus_bool_t
01166 dbus_message_set_reply_serial (DBusMessage   *message,
01167                                dbus_uint32_t  reply_serial)
01168 {
01169   DBusBasicValue value;
01170 
01171   _dbus_return_val_if_fail (message != NULL, FALSE);
01172   _dbus_return_val_if_fail (!message->locked, FALSE);
01173   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01174 
01175   value.u32 = reply_serial;
01176 
01177   return _dbus_header_set_field_basic (&message->header,
01178                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01179                                        DBUS_TYPE_UINT32,
01180                                        &value);
01181 }
01182 
01189 dbus_uint32_t
01190 dbus_message_get_reply_serial  (DBusMessage *message)
01191 {
01192   dbus_uint32_t v_UINT32;
01193 
01194   _dbus_return_val_if_fail (message != NULL, 0);
01195 
01196   if (_dbus_header_get_field_basic (&message->header,
01197                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01198                                     DBUS_TYPE_UINT32,
01199                                     &v_UINT32))
01200     return v_UINT32;
01201   else
01202     return 0;
01203 }
01204 
01205 static void
01206 dbus_message_finalize (DBusMessage *message)
01207 {
01208   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01209 
01210   /* This calls application callbacks! */
01211   _dbus_data_slot_list_free (&message->slot_list);
01212 
01213   _dbus_list_foreach (&message->counters,
01214                       free_counter, message);
01215   _dbus_list_clear (&message->counters);
01216 
01217   _dbus_header_free (&message->header);
01218   _dbus_string_free (&message->body);
01219 
01220 #ifdef HAVE_UNIX_FD_PASSING
01221   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01222   dbus_free(message->unix_fds);
01223 #endif
01224 
01225   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01226 
01227   dbus_free (message);
01228 }
01229 
01230 static DBusMessage*
01231 dbus_message_new_empty_header (void)
01232 {
01233   DBusMessage *message;
01234   dbus_bool_t from_cache;
01235 
01236   message = dbus_message_get_cached ();
01237 
01238   if (message != NULL)
01239     {
01240       from_cache = TRUE;
01241     }
01242   else
01243     {
01244       from_cache = FALSE;
01245       message = dbus_new0 (DBusMessage, 1);
01246       if (message == NULL)
01247         return NULL;
01248 #ifndef DBUS_DISABLE_CHECKS
01249       message->generation = _dbus_current_generation;
01250 #endif
01251 
01252 #ifdef HAVE_UNIX_FD_PASSING
01253       message->unix_fds = NULL;
01254       message->n_unix_fds_allocated = 0;
01255 #endif
01256     }
01257 
01258   _dbus_atomic_inc (&message->refcount);
01259 
01260   _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
01261 
01262   message->locked = FALSE;
01263 #ifndef DBUS_DISABLE_CHECKS
01264   message->in_cache = FALSE;
01265 #endif
01266   message->counters = NULL;
01267   message->size_counter_delta = 0;
01268   message->changed_stamp = 0;
01269 
01270 #ifdef HAVE_UNIX_FD_PASSING
01271   message->n_unix_fds = 0;
01272   message->n_unix_fds_allocated = 0;
01273   message->unix_fd_counter_delta = 0;
01274 #endif
01275 
01276   if (!from_cache)
01277     _dbus_data_slot_list_init (&message->slot_list);
01278 
01279   if (from_cache)
01280     {
01281       _dbus_header_reinit (&message->header);
01282       _dbus_string_set_length (&message->body, 0);
01283     }
01284   else
01285     {
01286       if (!_dbus_header_init (&message->header))
01287         {
01288           dbus_free (message);
01289           return NULL;
01290         }
01291 
01292       if (!_dbus_string_init_preallocated (&message->body, 32))
01293         {
01294           _dbus_header_free (&message->header);
01295           dbus_free (message);
01296           return NULL;
01297         }
01298     }
01299 
01300   return message;
01301 }
01302 
01315 DBusMessage*
01316 dbus_message_new (int message_type)
01317 {
01318   DBusMessage *message;
01319 
01320   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01321 
01322   message = dbus_message_new_empty_header ();
01323   if (message == NULL)
01324     return NULL;
01325 
01326   if (!_dbus_header_create (&message->header,
01327                             DBUS_COMPILER_BYTE_ORDER,
01328                             message_type,
01329                             NULL, NULL, NULL, NULL, NULL))
01330     {
01331       dbus_message_unref (message);
01332       return NULL;
01333     }
01334 
01335   return message;
01336 }
01337 
01359 DBusMessage*
01360 dbus_message_new_method_call (const char *destination,
01361                               const char *path,
01362                               const char *iface,
01363                               const char *method)
01364 {
01365   DBusMessage *message;
01366 
01367   _dbus_return_val_if_fail (path != NULL, NULL);
01368   _dbus_return_val_if_fail (method != NULL, NULL);
01369   _dbus_return_val_if_fail (destination == NULL ||
01370                             _dbus_check_is_valid_bus_name (destination), NULL);
01371   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01372   _dbus_return_val_if_fail (iface == NULL ||
01373                             _dbus_check_is_valid_interface (iface), NULL);
01374   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01375 
01376   message = dbus_message_new_empty_header ();
01377   if (message == NULL)
01378     return NULL;
01379 
01380   if (!_dbus_header_create (&message->header,
01381                             DBUS_COMPILER_BYTE_ORDER,
01382                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01383                             destination, path, iface, method, NULL))
01384     {
01385       dbus_message_unref (message);
01386       return NULL;
01387     }
01388 
01389   return message;
01390 }
01391 
01399 DBusMessage*
01400 dbus_message_new_method_return (DBusMessage *method_call)
01401 {
01402   DBusMessage *message;
01403   const char *sender;
01404 
01405   _dbus_return_val_if_fail (method_call != NULL, NULL);
01406 
01407   sender = dbus_message_get_sender (method_call);
01408 
01409   /* sender is allowed to be null here in peer-to-peer case */
01410 
01411   message = dbus_message_new_empty_header ();
01412   if (message == NULL)
01413     return NULL;
01414 
01415   if (!_dbus_header_create (&message->header,
01416                             DBUS_COMPILER_BYTE_ORDER,
01417                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01418                             sender, NULL, NULL, NULL, NULL))
01419     {
01420       dbus_message_unref (message);
01421       return NULL;
01422     }
01423 
01424   dbus_message_set_no_reply (message, TRUE);
01425 
01426   if (!dbus_message_set_reply_serial (message,
01427                                       dbus_message_get_serial (method_call)))
01428     {
01429       dbus_message_unref (message);
01430       return NULL;
01431     }
01432 
01433   return message;
01434 }
01435 
01450 DBusMessage*
01451 dbus_message_new_signal (const char *path,
01452                          const char *iface,
01453                          const char *name)
01454 {
01455   DBusMessage *message;
01456 
01457   _dbus_return_val_if_fail (path != NULL, NULL);
01458   _dbus_return_val_if_fail (iface != NULL, NULL);
01459   _dbus_return_val_if_fail (name != NULL, NULL);
01460   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01461   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
01462   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01463 
01464   message = dbus_message_new_empty_header ();
01465   if (message == NULL)
01466     return NULL;
01467 
01468   if (!_dbus_header_create (&message->header,
01469                             DBUS_COMPILER_BYTE_ORDER,
01470                             DBUS_MESSAGE_TYPE_SIGNAL,
01471                             NULL, path, iface, name, NULL))
01472     {
01473       dbus_message_unref (message);
01474       return NULL;
01475     }
01476 
01477   dbus_message_set_no_reply (message, TRUE);
01478 
01479   return message;
01480 }
01481 
01496 DBusMessage*
01497 dbus_message_new_error (DBusMessage *reply_to,
01498                         const char  *error_name,
01499                         const char  *error_message)
01500 {
01501   DBusMessage *message;
01502   const char *sender;
01503   DBusMessageIter iter;
01504 
01505   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01506   _dbus_return_val_if_fail (error_name != NULL, NULL);
01507   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01508 
01509   sender = dbus_message_get_sender (reply_to);
01510 
01511   /* sender may be NULL for non-message-bus case or
01512    * when the message bus is dealing with an unregistered
01513    * connection.
01514    */
01515   message = dbus_message_new_empty_header ();
01516   if (message == NULL)
01517     return NULL;
01518 
01519   if (!_dbus_header_create (&message->header,
01520                             DBUS_COMPILER_BYTE_ORDER,
01521                             DBUS_MESSAGE_TYPE_ERROR,
01522                             sender, NULL, NULL, NULL, error_name))
01523     {
01524       dbus_message_unref (message);
01525       return NULL;
01526     }
01527 
01528   dbus_message_set_no_reply (message, TRUE);
01529 
01530   if (!dbus_message_set_reply_serial (message,
01531                                       dbus_message_get_serial (reply_to)))
01532     {
01533       dbus_message_unref (message);
01534       return NULL;
01535     }
01536 
01537   if (error_message != NULL)
01538     {
01539       dbus_message_iter_init_append (message, &iter);
01540       if (!dbus_message_iter_append_basic (&iter,
01541                                            DBUS_TYPE_STRING,
01542                                            &error_message))
01543         {
01544           dbus_message_unref (message);
01545           return NULL;
01546         }
01547     }
01548 
01549   return message;
01550 }
01551 
01568 DBusMessage*
01569 dbus_message_new_error_printf (DBusMessage *reply_to,
01570                                const char  *error_name,
01571                                const char  *error_format,
01572                                ...)
01573 {
01574   va_list args;
01575   DBusString str;
01576   DBusMessage *message;
01577 
01578   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01579   _dbus_return_val_if_fail (error_name != NULL, NULL);
01580   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01581 
01582   if (!_dbus_string_init (&str))
01583     return NULL;
01584 
01585   va_start (args, error_format);
01586 
01587   if (_dbus_string_append_printf_valist (&str, error_format, args))
01588     message = dbus_message_new_error (reply_to, error_name,
01589                                       _dbus_string_get_const_data (&str));
01590   else
01591     message = NULL;
01592 
01593   _dbus_string_free (&str);
01594 
01595   va_end (args);
01596 
01597   return message;
01598 }
01599 
01600 
01613 DBusMessage *
01614 dbus_message_copy (const DBusMessage *message)
01615 {
01616   DBusMessage *retval;
01617 
01618   _dbus_return_val_if_fail (message != NULL, NULL);
01619 
01620   retval = dbus_new0 (DBusMessage, 1);
01621   if (retval == NULL)
01622     return NULL;
01623 
01624   _dbus_atomic_inc (&retval->refcount);
01625 
01626   retval->locked = FALSE;
01627 #ifndef DBUS_DISABLE_CHECKS
01628   retval->generation = message->generation;
01629 #endif
01630 
01631   if (!_dbus_header_copy (&message->header, &retval->header))
01632     {
01633       dbus_free (retval);
01634       return NULL;
01635     }
01636 
01637   if (!_dbus_string_init_preallocated (&retval->body,
01638                                        _dbus_string_get_length (&message->body)))
01639     {
01640       _dbus_header_free (&retval->header);
01641       dbus_free (retval);
01642       return NULL;
01643     }
01644 
01645   if (!_dbus_string_copy (&message->body, 0,
01646                           &retval->body, 0))
01647     goto failed_copy;
01648 
01649 #ifdef HAVE_UNIX_FD_PASSING
01650   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01651   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01652     goto failed_copy;
01653 
01654   retval->n_unix_fds_allocated = message->n_unix_fds;
01655 
01656   for (retval->n_unix_fds = 0;
01657        retval->n_unix_fds < message->n_unix_fds;
01658        retval->n_unix_fds++)
01659     {
01660       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01661 
01662       if (retval->unix_fds[retval->n_unix_fds] < 0)
01663         goto failed_copy;
01664     }
01665 
01666 #endif
01667 
01668   _dbus_message_trace_ref (retval, 0, 1, "copy");
01669   return retval;
01670 
01671  failed_copy:
01672   _dbus_header_free (&retval->header);
01673   _dbus_string_free (&retval->body);
01674 
01675 #ifdef HAVE_UNIX_FD_PASSING
01676   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01677   dbus_free(retval->unix_fds);
01678 #endif
01679 
01680   dbus_free (retval);
01681 
01682   return NULL;
01683 }
01684 
01685 
01693 DBusMessage *
01694 dbus_message_ref (DBusMessage *message)
01695 {
01696   dbus_int32_t old_refcount;
01697 
01698   _dbus_return_val_if_fail (message != NULL, NULL);
01699   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01700   _dbus_return_val_if_fail (!message->in_cache, NULL);
01701 
01702   old_refcount = _dbus_atomic_inc (&message->refcount);
01703   _dbus_assert (old_refcount >= 1);
01704   _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
01705 
01706   return message;
01707 }
01708 
01716 void
01717 dbus_message_unref (DBusMessage *message)
01718 {
01719  dbus_int32_t old_refcount;
01720 
01721   _dbus_return_if_fail (message != NULL);
01722   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01723   _dbus_return_if_fail (!message->in_cache);
01724 
01725   old_refcount = _dbus_atomic_dec (&message->refcount);
01726 
01727   _dbus_assert (old_refcount >= 1);
01728 
01729   _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
01730 
01731   if (old_refcount == 1)
01732     {
01733       /* Calls application callbacks! */
01734       dbus_message_cache_or_finalize (message);
01735     }
01736 }
01737 
01748 int
01749 dbus_message_get_type (DBusMessage *message)
01750 {
01751   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01752 
01753   return _dbus_header_get_message_type (&message->header);
01754 }
01755 
01818 dbus_bool_t
01819 dbus_message_append_args (DBusMessage *message,
01820                           int          first_arg_type,
01821                           ...)
01822 {
01823   dbus_bool_t retval;
01824   va_list var_args;
01825 
01826   _dbus_return_val_if_fail (message != NULL, FALSE);
01827 
01828   va_start (var_args, first_arg_type);
01829   retval = dbus_message_append_args_valist (message,
01830                                             first_arg_type,
01831                                             var_args);
01832   va_end (var_args);
01833 
01834   return retval;
01835 }
01836 
01850 dbus_bool_t
01851 dbus_message_append_args_valist (DBusMessage *message,
01852                                  int          first_arg_type,
01853                                  va_list      var_args)
01854 {
01855   int type;
01856   DBusMessageIter iter;
01857 
01858   _dbus_return_val_if_fail (message != NULL, FALSE);
01859 
01860   type = first_arg_type;
01861 
01862   dbus_message_iter_init_append (message, &iter);
01863 
01864   while (type != DBUS_TYPE_INVALID)
01865     {
01866       if (dbus_type_is_basic (type))
01867         {
01868           const DBusBasicValue *value;
01869           value = va_arg (var_args, const DBusBasicValue*);
01870 
01871           if (!dbus_message_iter_append_basic (&iter,
01872                                                type,
01873                                                value))
01874             goto failed;
01875         }
01876       else if (type == DBUS_TYPE_ARRAY)
01877         {
01878           int element_type;
01879           DBusMessageIter array;
01880           char buf[2];
01881 
01882           element_type = va_arg (var_args, int);
01883               
01884           buf[0] = element_type;
01885           buf[1] = '\0';
01886           if (!dbus_message_iter_open_container (&iter,
01887                                                  DBUS_TYPE_ARRAY,
01888                                                  buf,
01889                                                  &array))
01890             goto failed;
01891 
01892           if (dbus_type_is_fixed (element_type) &&
01893               element_type != DBUS_TYPE_UNIX_FD)
01894             {
01895               const DBusBasicValue **value;
01896               int n_elements;
01897 
01898               value = va_arg (var_args, const DBusBasicValue**);
01899               n_elements = va_arg (var_args, int);
01900               
01901               if (!dbus_message_iter_append_fixed_array (&array,
01902                                                          element_type,
01903                                                          value,
01904                                                          n_elements)) {
01905                 dbus_message_iter_abandon_container (&iter, &array);
01906                 goto failed;
01907               }
01908             }
01909           else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
01910             {
01911               const char ***value_p;
01912               const char **value;
01913               int n_elements;
01914               int i;
01915               
01916               value_p = va_arg (var_args, const char***);
01917               n_elements = va_arg (var_args, int);
01918 
01919               value = *value_p;
01920               
01921               i = 0;
01922               while (i < n_elements)
01923                 {
01924                   if (!dbus_message_iter_append_basic (&array,
01925                                                        element_type,
01926                                                        &value[i])) {
01927                     dbus_message_iter_abandon_container (&iter, &array);
01928                     goto failed;
01929                   }
01930                   ++i;
01931                 }
01932             }
01933           else
01934             {
01935               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01936                           _dbus_type_to_string (element_type),
01937                           _DBUS_FUNCTION_NAME);
01938               goto failed;
01939             }
01940 
01941           if (!dbus_message_iter_close_container (&iter, &array))
01942             goto failed;
01943         }
01944 #ifndef DBUS_DISABLE_CHECKS
01945       else
01946         {
01947           _dbus_warn ("type %s isn't supported yet in %s\n",
01948                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01949           goto failed;
01950         }
01951 #endif
01952 
01953       type = va_arg (var_args, int);
01954     }
01955 
01956   return TRUE;
01957 
01958  failed:
01959   return FALSE;
01960 }
01961 
02006 dbus_bool_t
02007 dbus_message_get_args (DBusMessage     *message,
02008                        DBusError       *error,
02009                        int              first_arg_type,
02010                        ...)
02011 {
02012   dbus_bool_t retval;
02013   va_list var_args;
02014 
02015   _dbus_return_val_if_fail (message != NULL, FALSE);
02016   _dbus_return_val_if_error_is_set (error, FALSE);
02017 
02018   va_start (var_args, first_arg_type);
02019   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
02020   va_end (var_args);
02021 
02022   return retval;
02023 }
02024 
02035 dbus_bool_t
02036 dbus_message_get_args_valist (DBusMessage     *message,
02037                               DBusError       *error,
02038                               int              first_arg_type,
02039                               va_list          var_args)
02040 {
02041   DBusMessageIter iter;
02042 
02043   _dbus_return_val_if_fail (message != NULL, FALSE);
02044   _dbus_return_val_if_error_is_set (error, FALSE);
02045 
02046   dbus_message_iter_init (message, &iter);
02047   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
02048 }
02049 
02050 static void
02051 _dbus_message_iter_init_common (DBusMessage         *message,
02052                                 DBusMessageRealIter *real,
02053                                 int                  iter_type)
02054 {
02055   /* If these static assertions fail on your platform, report it as a bug. */
02056   _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
02057   _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
02058       _DBUS_ALIGNOF (DBusMessageIter));
02059   /* A failure of these two assertions would indicate that we've broken
02060    * ABI on this platform since 1.10.0. */
02061   _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
02062       sizeof (DBusMessageIter));
02063   _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
02064       _DBUS_ALIGNOF (DBusMessageIter));
02065   /* If this static assertion fails, it means the DBusMessageIter struct
02066    * is not "packed", which might result in "iter = other_iter" not copying
02067    * every byte. */
02068   _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
02069       4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
02070 
02071   /* Since the iterator will read or write who-knows-what from the
02072    * message, we need to get in the right byte order
02073    */
02074   ensure_byte_order (message);
02075   
02076   real->message = message;
02077   real->changed_stamp = message->changed_stamp;
02078   real->iter_type = iter_type;
02079   real->sig_refcount = 0;
02080 }
02081 
02104 dbus_bool_t
02105 dbus_message_iter_init (DBusMessage     *message,
02106                         DBusMessageIter *iter)
02107 {
02108   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02109   const DBusString *type_str;
02110   int type_pos;
02111 
02112   _dbus_return_val_if_fail (message != NULL, FALSE);
02113   _dbus_return_val_if_fail (iter != NULL, FALSE);
02114 
02115   get_const_signature (&message->header, &type_str, &type_pos);
02116 
02117   _dbus_message_iter_init_common (message, real,
02118                                   DBUS_MESSAGE_ITER_TYPE_READER);
02119 
02120   _dbus_type_reader_init (&real->u.reader,
02121                           _dbus_header_get_byte_order (&message->header),
02122                           type_str, type_pos,
02123                           &message->body,
02124                           0);
02125 
02126   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
02127 }
02128 
02135 dbus_bool_t
02136 dbus_message_iter_has_next (DBusMessageIter *iter)
02137 {
02138   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02139 
02140   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02141   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02142 
02143   return _dbus_type_reader_has_next (&real->u.reader);
02144 }
02145 
02154 dbus_bool_t
02155 dbus_message_iter_next (DBusMessageIter *iter)
02156 {
02157   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02158 
02159   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02160   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02161 
02162   return _dbus_type_reader_next (&real->u.reader);
02163 }
02164 
02179 int
02180 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02181 {
02182   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02183 
02184   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02185   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02186 
02187   return _dbus_type_reader_get_current_type (&real->u.reader);
02188 }
02189 
02198 int
02199 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02200 {
02201   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02202 
02203   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02204   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02205   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02206 
02207   return _dbus_type_reader_get_element_type (&real->u.reader);
02208 }
02209 
02235 void
02236 dbus_message_iter_recurse (DBusMessageIter  *iter,
02237                            DBusMessageIter  *sub)
02238 {
02239   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02240   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02241 
02242   _dbus_return_if_fail (_dbus_message_iter_check (real));
02243   _dbus_return_if_fail (sub != NULL);
02244 
02245   *real_sub = *real;
02246   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02247 }
02248 
02260 char *
02261 dbus_message_iter_get_signature (DBusMessageIter *iter)
02262 {
02263   const DBusString *sig;
02264   DBusString retstr;
02265   char *ret;
02266   int start, len;
02267   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02268 
02269   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02270 
02271   if (!_dbus_string_init (&retstr))
02272     return NULL;
02273 
02274   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02275                                    &start, &len);
02276   if (!_dbus_string_append_len (&retstr,
02277                                 _dbus_string_get_const_data (sig) + start,
02278                                 len))
02279     return NULL;
02280   if (!_dbus_string_steal_data (&retstr, &ret))
02281     return NULL;
02282   _dbus_string_free (&retstr);
02283   return ret;
02284 }
02285 
02333 void
02334 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02335                              void             *value)
02336 {
02337   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02338 
02339   _dbus_return_if_fail (_dbus_message_iter_check (real));
02340   _dbus_return_if_fail (value != NULL);
02341 
02342   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02343     {
02344 #ifdef HAVE_UNIX_FD_PASSING
02345       DBusBasicValue idx;
02346 
02347       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02348 
02349       if (idx.u32 >= real->message->n_unix_fds) {
02350         /* Hmm, we cannot really signal an error here, so let's make
02351            sure to return an invalid fd. */
02352         *((int*) value) = -1;
02353         return;
02354       }
02355 
02356       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02357 #else
02358       *((int*) value) = -1;
02359 #endif
02360     }
02361   else
02362     {
02363       _dbus_type_reader_read_basic (&real->u.reader,
02364                                     value);
02365     }
02366 }
02367 
02378 int
02379 dbus_message_iter_get_element_count (DBusMessageIter *iter)
02380 {
02381   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02382   DBusTypeReader array;
02383   int element_type;
02384   int n_elements = 0;
02385 
02386   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02387   _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
02388                             == DBUS_TYPE_ARRAY, 0);
02389 
02390   element_type = _dbus_type_reader_get_element_type (&real->u.reader);
02391   _dbus_type_reader_recurse (&real->u.reader, &array);
02392   if (dbus_type_is_fixed (element_type))
02393     {
02394       int alignment = _dbus_type_get_alignment (element_type);
02395       int total_len = _dbus_type_reader_get_array_length (&array);
02396       n_elements = total_len / alignment;
02397     }
02398   else
02399     {
02400       while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
02401         {
02402           ++n_elements;
02403           _dbus_type_reader_next (&array);
02404         }
02405     }
02406 
02407    return n_elements;
02408 }
02409 
02422 int
02423 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02424 {
02425   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02426 
02427   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02428 
02429   return _dbus_type_reader_get_array_length (&real->u.reader);
02430 }
02431 
02467 void
02468 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02469                                    void             *value,
02470                                    int              *n_elements)
02471 {
02472   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02473 #ifndef DBUS_DISABLE_CHECKS
02474   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02475 
02476   _dbus_return_if_fail (_dbus_message_iter_check (real));
02477   _dbus_return_if_fail (value != NULL);
02478   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02479                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02480 #endif
02481 
02482   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02483                                       value, n_elements);
02484 }
02485 
02497 void
02498 dbus_message_iter_init_append (DBusMessage     *message,
02499                                DBusMessageIter *iter)
02500 {
02501   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02502 
02503   _dbus_return_if_fail (message != NULL);
02504   _dbus_return_if_fail (iter != NULL);
02505 
02506   _dbus_message_iter_init_common (message, real,
02507                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02508 
02509   /* We create the signature string and point iterators at it "on demand"
02510    * when a value is actually appended. That means that init() never fails
02511    * due to OOM.
02512    */
02513   _dbus_type_writer_init_types_delayed (&real->u.writer,
02514                                         _dbus_header_get_byte_order (&message->header),
02515                                         &message->body,
02516                                         _dbus_string_get_length (&message->body));
02517 }
02518 
02527 static dbus_bool_t
02528 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02529 {
02530   DBusString *str;
02531   const DBusString *current_sig;
02532   int current_sig_pos;
02533 
02534   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02535 
02536   if (real->u.writer.type_str != NULL)
02537     {
02538       _dbus_assert (real->sig_refcount > 0);
02539       real->sig_refcount += 1;
02540       return TRUE;
02541     }
02542 
02543   str = dbus_new (DBusString, 1);
02544   if (str == NULL)
02545     return FALSE;
02546 
02547   if (!_dbus_header_get_field_raw (&real->message->header,
02548                                    DBUS_HEADER_FIELD_SIGNATURE,
02549                                    &current_sig, &current_sig_pos))
02550     current_sig = NULL;
02551 
02552   if (current_sig)
02553     {
02554       int current_len;
02555 
02556       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02557       current_sig_pos += 1; /* move on to sig data */
02558 
02559       if (!_dbus_string_init_preallocated (str, current_len + 4))
02560         {
02561           dbus_free (str);
02562           return FALSE;
02563         }
02564 
02565       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02566                                   str, 0))
02567         {
02568           _dbus_string_free (str);
02569           dbus_free (str);
02570           return FALSE;
02571         }
02572     }
02573   else
02574     {
02575       if (!_dbus_string_init_preallocated (str, 4))
02576         {
02577           dbus_free (str);
02578           return FALSE;
02579         }
02580     }
02581 
02582   real->sig_refcount = 1;
02583 
02584   _dbus_type_writer_add_types (&real->u.writer,
02585                                str, _dbus_string_get_length (str));
02586   return TRUE;
02587 }
02588 
02598 static dbus_bool_t
02599 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02600 {
02601   DBusString *str;
02602   const char *v_STRING;
02603   dbus_bool_t retval;
02604 
02605   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02606   _dbus_assert (real->u.writer.type_str != NULL);
02607   _dbus_assert (real->sig_refcount > 0);
02608 
02609   real->sig_refcount -= 1;
02610 
02611   if (real->sig_refcount > 0)
02612     return TRUE;
02613   _dbus_assert (real->sig_refcount == 0);
02614 
02615   retval = TRUE;
02616 
02617   str = real->u.writer.type_str;
02618 
02619   v_STRING = _dbus_string_get_const_data (str);
02620   if (!_dbus_header_set_field_basic (&real->message->header,
02621                                      DBUS_HEADER_FIELD_SIGNATURE,
02622                                      DBUS_TYPE_SIGNATURE,
02623                                      &v_STRING))
02624     retval = FALSE;
02625 
02626   _dbus_type_writer_remove_types (&real->u.writer);
02627   _dbus_string_free (str);
02628   dbus_free (str);
02629 
02630   return retval;
02631 }
02632 
02640 static void
02641 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02642 {
02643   DBusString *str;
02644 
02645   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02646   _dbus_assert (real->u.writer.type_str != NULL);
02647   _dbus_assert (real->sig_refcount > 0);
02648 
02649   real->sig_refcount -= 1;
02650 
02651   if (real->sig_refcount > 0)
02652     return;
02653   _dbus_assert (real->sig_refcount == 0);
02654 
02655   str = real->u.writer.type_str;
02656 
02657   _dbus_type_writer_remove_types (&real->u.writer);
02658   _dbus_string_free (str);
02659   dbus_free (str);
02660 }
02661 
02662 #ifndef DBUS_DISABLE_CHECKS
02663 static dbus_bool_t
02664 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02665 {
02666   if (!_dbus_message_iter_check (iter))
02667     return FALSE;
02668 
02669   if (iter->message->locked)
02670     {
02671       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02672       return FALSE;
02673     }
02674 
02675   return TRUE;
02676 }
02677 #endif /* DBUS_DISABLE_CHECKS */
02678 
02679 #ifdef HAVE_UNIX_FD_PASSING
02680 static int *
02681 expand_fd_array(DBusMessage *m,
02682                 unsigned     n)
02683 {
02684   _dbus_assert(m);
02685 
02686   /* This makes space for adding n new fds to the array and returns a
02687      pointer to the place were the first fd should be put. */
02688 
02689   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02690     {
02691       unsigned k;
02692       int *p;
02693 
02694       /* Make twice as much space as necessary */
02695       k = (m->n_unix_fds + n) * 2;
02696 
02697       /* Allocate at least four */
02698       if (k < 4)
02699         k = 4;
02700 
02701       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02702       if (p == NULL)
02703         return NULL;
02704 
02705       m->unix_fds = p;
02706       m->n_unix_fds_allocated = k;
02707     }
02708 
02709   return m->unix_fds + m->n_unix_fds;
02710 }
02711 #endif
02712 
02732 dbus_bool_t
02733 dbus_message_iter_append_basic (DBusMessageIter *iter,
02734                                 int              type,
02735                                 const void      *value)
02736 {
02737   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02738   dbus_bool_t ret;
02739 
02740   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02741   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02742   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02743   _dbus_return_val_if_fail (value != NULL, FALSE);
02744 
02745 #ifndef DBUS_DISABLE_CHECKS
02746   switch (type)
02747     {
02748       const char * const *string_p;
02749       const dbus_bool_t *bool_p;
02750 
02751       case DBUS_TYPE_STRING:
02752         string_p = value;
02753         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02754         break;
02755 
02756       case DBUS_TYPE_OBJECT_PATH:
02757         string_p = value;
02758         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02759         break;
02760 
02761       case DBUS_TYPE_SIGNATURE:
02762         string_p = value;
02763         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02764         break;
02765 
02766       case DBUS_TYPE_BOOLEAN:
02767         bool_p = value;
02768         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02769         break;
02770 
02771       default:
02772           {
02773             /* nothing to check, all possible values are allowed */
02774           }
02775     }
02776 #endif
02777 
02778   if (!_dbus_message_iter_open_signature (real))
02779     return FALSE;
02780 
02781   if (type == DBUS_TYPE_UNIX_FD)
02782     {
02783 #ifdef HAVE_UNIX_FD_PASSING
02784       int *fds;
02785       dbus_uint32_t u;
02786 
02787       /* First step, include the fd in the fd list of this message */
02788       if (!(fds = expand_fd_array(real->message, 1)))
02789         return FALSE;
02790 
02791       *fds = _dbus_dup(*(int*) value, NULL);
02792       if (*fds < 0)
02793         return FALSE;
02794 
02795       u = real->message->n_unix_fds;
02796 
02797       /* Second step, write the index to the fd */
02798       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02799         _dbus_close(*fds, NULL);
02800         return FALSE;
02801       }
02802 
02803       real->message->n_unix_fds += 1;
02804       u += 1;
02805 
02806       /* Final step, update the header accordingly */
02807       ret = _dbus_header_set_field_basic (&real->message->header,
02808                                           DBUS_HEADER_FIELD_UNIX_FDS,
02809                                           DBUS_TYPE_UINT32,
02810                                           &u);
02811 
02812       /* If any of these operations fail the message is
02813          hosed. However, no memory or fds should be leaked since what
02814          has been added to message has been added to the message, and
02815          can hence be accounted for when the message is being
02816          freed. */
02817 #else
02818       ret = FALSE;
02819 #endif
02820     }
02821   else
02822     {
02823       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02824     }
02825 
02826   if (!_dbus_message_iter_close_signature (real))
02827     ret = FALSE;
02828 
02829   return ret;
02830 }
02831 
02867 dbus_bool_t
02868 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02869                                       int              element_type,
02870                                       const void      *value,
02871                                       int              n_elements)
02872 {
02873   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02874   dbus_bool_t ret;
02875 
02876   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02877   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02878   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02879   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02880   _dbus_return_val_if_fail (value != NULL, FALSE);
02881   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02882   _dbus_return_val_if_fail (n_elements <=
02883                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02884                             FALSE);
02885 
02886 #ifndef DBUS_DISABLE_CHECKS
02887   if (element_type == DBUS_TYPE_BOOLEAN)
02888     {
02889       const dbus_bool_t * const *bools = value;
02890       int i;
02891 
02892       for (i = 0; i < n_elements; i++)
02893         {
02894           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02895         }
02896     }
02897 #endif
02898 
02899   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02900 
02901   return ret;
02902 }
02903 
02925 dbus_bool_t
02926 dbus_message_iter_open_container (DBusMessageIter *iter,
02927                                   int              type,
02928                                   const char      *contained_signature,
02929                                   DBusMessageIter *sub)
02930 {
02931   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02932   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02933   DBusString contained_str;
02934 
02935   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02936   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02937   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02938   _dbus_return_val_if_fail (sub != NULL, FALSE);
02939   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02940                              contained_signature == NULL) ||
02941                             (type == DBUS_TYPE_DICT_ENTRY &&
02942                              contained_signature == NULL) ||
02943                             (type == DBUS_TYPE_VARIANT &&
02944                              contained_signature != NULL) ||
02945                             (type == DBUS_TYPE_ARRAY &&
02946                              contained_signature != NULL), FALSE);
02947   
02948   /* this would fail if the contained_signature is a dict entry, since
02949    * dict entries are invalid signatures standalone (they must be in
02950    * an array)
02951    */
02952   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02953                             (contained_signature == NULL ||
02954                              _dbus_check_is_valid_signature (contained_signature)),
02955                             FALSE);
02956 
02957   if (!_dbus_message_iter_open_signature (real))
02958     return FALSE;
02959 
02960   *real_sub = *real;
02961 
02962   if (contained_signature != NULL)
02963     {
02964       _dbus_string_init_const (&contained_str, contained_signature);
02965 
02966       return _dbus_type_writer_recurse (&real->u.writer,
02967                                         type,
02968                                         &contained_str, 0,
02969                                         &real_sub->u.writer);
02970     }
02971   else
02972     {
02973       return _dbus_type_writer_recurse (&real->u.writer,
02974                                         type,
02975                                         NULL, 0,
02976                                         &real_sub->u.writer);
02977     } 
02978 }
02979 
02980 
02994 dbus_bool_t
02995 dbus_message_iter_close_container (DBusMessageIter *iter,
02996                                    DBusMessageIter *sub)
02997 {
02998   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02999   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
03000   dbus_bool_t ret;
03001 
03002   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
03003   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
03004   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
03005   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
03006 
03007   ret = _dbus_type_writer_unrecurse (&real->u.writer,
03008                                      &real_sub->u.writer);
03009 
03010   if (!_dbus_message_iter_close_signature (real))
03011     ret = FALSE;
03012 
03013   return ret;
03014 }
03015 
03027 void
03028 dbus_message_iter_abandon_container (DBusMessageIter *iter,
03029                                      DBusMessageIter *sub)
03030 {
03031   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03032 #ifndef DBUS_DISABLE_CHECKS
03033   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
03034 
03035   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
03036   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
03037   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
03038   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
03039 #endif
03040 
03041   _dbus_message_iter_abandon_signature (real);
03042 }
03043 
03060 void
03061 dbus_message_set_no_reply (DBusMessage *message,
03062                            dbus_bool_t  no_reply)
03063 {
03064   _dbus_return_if_fail (message != NULL);
03065   _dbus_return_if_fail (!message->locked);
03066 
03067   _dbus_header_toggle_flag (&message->header,
03068                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
03069                             no_reply);
03070 }
03071 
03079 dbus_bool_t
03080 dbus_message_get_no_reply (DBusMessage *message)
03081 {
03082   _dbus_return_val_if_fail (message != NULL, FALSE);
03083 
03084   return _dbus_header_get_flag (&message->header,
03085                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
03086 }
03087 
03102 void
03103 dbus_message_set_auto_start (DBusMessage *message,
03104                              dbus_bool_t  auto_start)
03105 {
03106   _dbus_return_if_fail (message != NULL);
03107   _dbus_return_if_fail (!message->locked);
03108 
03109   _dbus_header_toggle_flag (&message->header,
03110                             DBUS_HEADER_FLAG_NO_AUTO_START,
03111                             !auto_start);
03112 }
03113 
03121 dbus_bool_t
03122 dbus_message_get_auto_start (DBusMessage *message)
03123 {
03124   _dbus_return_val_if_fail (message != NULL, FALSE);
03125 
03126   return !_dbus_header_get_flag (&message->header,
03127                                  DBUS_HEADER_FLAG_NO_AUTO_START);
03128 }
03129 
03130 
03143 dbus_bool_t
03144 dbus_message_set_path (DBusMessage   *message,
03145                        const char    *object_path)
03146 {
03147   _dbus_return_val_if_fail (message != NULL, FALSE);
03148   _dbus_return_val_if_fail (!message->locked, FALSE);
03149   _dbus_return_val_if_fail (object_path == NULL ||
03150                             _dbus_check_is_valid_path (object_path),
03151                             FALSE);
03152 
03153   return set_or_delete_string_field (message,
03154                                      DBUS_HEADER_FIELD_PATH,
03155                                      DBUS_TYPE_OBJECT_PATH,
03156                                      object_path);
03157 }
03158 
03172 const char*
03173 dbus_message_get_path (DBusMessage   *message)
03174 {
03175   const char *v;
03176 
03177   _dbus_return_val_if_fail (message != NULL, NULL);
03178 
03179   v = NULL; /* in case field doesn't exist */
03180   _dbus_header_get_field_basic (&message->header,
03181                                 DBUS_HEADER_FIELD_PATH,
03182                                 DBUS_TYPE_OBJECT_PATH,
03183                                 (void *) &v);
03184   return v;
03185 }
03186 
03196 dbus_bool_t
03197 dbus_message_has_path (DBusMessage   *message,
03198                        const char    *path)
03199 {
03200   const char *msg_path;
03201   msg_path = dbus_message_get_path (message);
03202   
03203   if (msg_path == NULL)
03204     {
03205       if (path == NULL)
03206         return TRUE;
03207       else
03208         return FALSE;
03209     }
03210 
03211   if (path == NULL)
03212     return FALSE;
03213    
03214   if (strcmp (msg_path, path) == 0)
03215     return TRUE;
03216 
03217   return FALSE;
03218 }
03219 
03240 dbus_bool_t
03241 dbus_message_get_path_decomposed (DBusMessage   *message,
03242                                   char        ***path)
03243 {
03244   const char *v;
03245 
03246   _dbus_return_val_if_fail (message != NULL, FALSE);
03247   _dbus_return_val_if_fail (path != NULL, FALSE);
03248 
03249   *path = NULL;
03250 
03251   v = dbus_message_get_path (message);
03252   if (v != NULL)
03253     {
03254       if (!_dbus_decompose_path (v, strlen (v),
03255                                  path, NULL))
03256         return FALSE;
03257     }
03258   return TRUE;
03259 }
03260 
03274 dbus_bool_t
03275 dbus_message_set_interface (DBusMessage  *message,
03276                             const char   *iface)
03277 {
03278   _dbus_return_val_if_fail (message != NULL, FALSE);
03279   _dbus_return_val_if_fail (!message->locked, FALSE);
03280   _dbus_return_val_if_fail (iface == NULL ||
03281                             _dbus_check_is_valid_interface (iface),
03282                             FALSE);
03283 
03284   return set_or_delete_string_field (message,
03285                                      DBUS_HEADER_FIELD_INTERFACE,
03286                                      DBUS_TYPE_STRING,
03287                                      iface);
03288 }
03289 
03303 const char*
03304 dbus_message_get_interface (DBusMessage *message)
03305 {
03306   const char *v;
03307 
03308   _dbus_return_val_if_fail (message != NULL, NULL);
03309 
03310   v = NULL; /* in case field doesn't exist */
03311   _dbus_header_get_field_basic (&message->header,
03312                                 DBUS_HEADER_FIELD_INTERFACE,
03313                                 DBUS_TYPE_STRING,
03314                                 (void *) &v);
03315   return v;
03316 }
03317 
03325 dbus_bool_t
03326 dbus_message_has_interface (DBusMessage   *message,
03327                             const char    *iface)
03328 {
03329   const char *msg_interface;
03330   msg_interface = dbus_message_get_interface (message);
03331    
03332   if (msg_interface == NULL)
03333     {
03334       if (iface == NULL)
03335         return TRUE;
03336       else
03337         return FALSE;
03338     }
03339 
03340   if (iface == NULL)
03341     return FALSE;
03342      
03343   if (strcmp (msg_interface, iface) == 0)
03344     return TRUE;
03345 
03346   return FALSE;
03347 
03348 }
03349 
03362 dbus_bool_t
03363 dbus_message_set_member (DBusMessage  *message,
03364                          const char   *member)
03365 {
03366   _dbus_return_val_if_fail (message != NULL, FALSE);
03367   _dbus_return_val_if_fail (!message->locked, FALSE);
03368   _dbus_return_val_if_fail (member == NULL ||
03369                             _dbus_check_is_valid_member (member),
03370                             FALSE);
03371 
03372   return set_or_delete_string_field (message,
03373                                      DBUS_HEADER_FIELD_MEMBER,
03374                                      DBUS_TYPE_STRING,
03375                                      member);
03376 }
03377 
03389 const char*
03390 dbus_message_get_member (DBusMessage *message)
03391 {
03392   const char *v;
03393 
03394   _dbus_return_val_if_fail (message != NULL, NULL);
03395 
03396   v = NULL; /* in case field doesn't exist */
03397   _dbus_header_get_field_basic (&message->header,
03398                                 DBUS_HEADER_FIELD_MEMBER,
03399                                 DBUS_TYPE_STRING,
03400                                 (void *) &v);
03401   return v;
03402 }
03403 
03411 dbus_bool_t
03412 dbus_message_has_member (DBusMessage   *message,
03413                          const char    *member)
03414 {
03415   const char *msg_member;
03416   msg_member = dbus_message_get_member (message);
03417  
03418   if (msg_member == NULL)
03419     {
03420       if (member == NULL)
03421         return TRUE;
03422       else
03423         return FALSE;
03424     }
03425 
03426   if (member == NULL)
03427     return FALSE;
03428     
03429   if (strcmp (msg_member, member) == 0)
03430     return TRUE;
03431 
03432   return FALSE;
03433 
03434 }
03435 
03447 dbus_bool_t
03448 dbus_message_set_error_name (DBusMessage  *message,
03449                              const char   *error_name)
03450 {
03451   _dbus_return_val_if_fail (message != NULL, FALSE);
03452   _dbus_return_val_if_fail (!message->locked, FALSE);
03453   _dbus_return_val_if_fail (error_name == NULL ||
03454                             _dbus_check_is_valid_error_name (error_name),
03455                             FALSE);
03456 
03457   return set_or_delete_string_field (message,
03458                                      DBUS_HEADER_FIELD_ERROR_NAME,
03459                                      DBUS_TYPE_STRING,
03460                                      error_name);
03461 }
03462 
03473 const char*
03474 dbus_message_get_error_name (DBusMessage *message)
03475 {
03476   const char *v;
03477 
03478   _dbus_return_val_if_fail (message != NULL, NULL);
03479 
03480   v = NULL; /* in case field doesn't exist */
03481   _dbus_header_get_field_basic (&message->header,
03482                                 DBUS_HEADER_FIELD_ERROR_NAME,
03483                                 DBUS_TYPE_STRING,
03484                                 (void *) &v);
03485   return v;
03486 }
03487 
03501 dbus_bool_t
03502 dbus_message_set_destination (DBusMessage  *message,
03503                               const char   *destination)
03504 {
03505   _dbus_return_val_if_fail (message != NULL, FALSE);
03506   _dbus_return_val_if_fail (!message->locked, FALSE);
03507   _dbus_return_val_if_fail (destination == NULL ||
03508                             _dbus_check_is_valid_bus_name (destination),
03509                             FALSE);
03510 
03511   return set_or_delete_string_field (message,
03512                                      DBUS_HEADER_FIELD_DESTINATION,
03513                                      DBUS_TYPE_STRING,
03514                                      destination);
03515 }
03516 
03526 const char*
03527 dbus_message_get_destination (DBusMessage *message)
03528 {
03529   const char *v;
03530 
03531   _dbus_return_val_if_fail (message != NULL, NULL);
03532 
03533   v = NULL; /* in case field doesn't exist */
03534   _dbus_header_get_field_basic (&message->header,
03535                                 DBUS_HEADER_FIELD_DESTINATION,
03536                                 DBUS_TYPE_STRING,
03537                                 (void *) &v);
03538   return v;
03539 }
03540 
03555 dbus_bool_t
03556 dbus_message_set_sender (DBusMessage  *message,
03557                          const char   *sender)
03558 {
03559   _dbus_return_val_if_fail (message != NULL, FALSE);
03560   _dbus_return_val_if_fail (!message->locked, FALSE);
03561   _dbus_return_val_if_fail (sender == NULL ||
03562                             _dbus_check_is_valid_bus_name (sender),
03563                             FALSE);
03564 
03565   return set_or_delete_string_field (message,
03566                                      DBUS_HEADER_FIELD_SENDER,
03567                                      DBUS_TYPE_STRING,
03568                                      sender);
03569 }
03570 
03586 const char*
03587 dbus_message_get_sender (DBusMessage *message)
03588 {
03589   const char *v;
03590 
03591   _dbus_return_val_if_fail (message != NULL, NULL);
03592 
03593   v = NULL; /* in case field doesn't exist */
03594   _dbus_header_get_field_basic (&message->header,
03595                                 DBUS_HEADER_FIELD_SENDER,
03596                                 DBUS_TYPE_STRING,
03597                                 (void *) &v);
03598   return v;
03599 }
03600 
03619 const char*
03620 dbus_message_get_signature (DBusMessage *message)
03621 {
03622   const DBusString *type_str;
03623   int type_pos;
03624 
03625   _dbus_return_val_if_fail (message != NULL, NULL);
03626 
03627   get_const_signature (&message->header, &type_str, &type_pos);
03628 
03629   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03630 }
03631 
03632 static dbus_bool_t
03633 _dbus_message_has_type_interface_member (DBusMessage *message,
03634                                          int          type,
03635                                          const char  *iface,
03636                                          const char  *member)
03637 {
03638   const char *n;
03639 
03640   _dbus_assert (message != NULL);
03641   _dbus_assert (iface != NULL);
03642   _dbus_assert (member != NULL);
03643 
03644   if (dbus_message_get_type (message) != type)
03645     return FALSE;
03646 
03647   /* Optimize by checking the short member name first
03648    * instead of the longer interface name
03649    */
03650 
03651   n = dbus_message_get_member (message);
03652 
03653   if (n && strcmp (n, member) == 0)
03654     {
03655       n = dbus_message_get_interface (message);
03656 
03657       if (n == NULL || strcmp (n, iface) == 0)
03658         return TRUE;
03659     }
03660 
03661   return FALSE;
03662 }
03663 
03678 dbus_bool_t
03679 dbus_message_is_method_call (DBusMessage *message,
03680                              const char  *iface,
03681                              const char  *method)
03682 {
03683   _dbus_return_val_if_fail (message != NULL, FALSE);
03684   _dbus_return_val_if_fail (iface != NULL, FALSE);
03685   _dbus_return_val_if_fail (method != NULL, FALSE);
03686   /* don't check that interface/method are valid since it would be
03687    * expensive, and not catch many common errors
03688    */
03689 
03690   return _dbus_message_has_type_interface_member (message,
03691                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03692                                                   iface, method);
03693 }
03694 
03706 dbus_bool_t
03707 dbus_message_is_signal (DBusMessage *message,
03708                         const char  *iface,
03709                         const char  *signal_name)
03710 {
03711   _dbus_return_val_if_fail (message != NULL, FALSE);
03712   _dbus_return_val_if_fail (iface != NULL, FALSE);
03713   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03714   /* don't check that interface/name are valid since it would be
03715    * expensive, and not catch many common errors
03716    */
03717 
03718   return _dbus_message_has_type_interface_member (message,
03719                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03720                                                   iface, signal_name);
03721 }
03722 
03733 dbus_bool_t
03734 dbus_message_is_error (DBusMessage *message,
03735                        const char  *error_name)
03736 {
03737   const char *n;
03738 
03739   _dbus_return_val_if_fail (message != NULL, FALSE);
03740   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03741   /* don't check that error_name is valid since it would be expensive,
03742    * and not catch many common errors
03743    */
03744 
03745   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03746     return FALSE;
03747 
03748   n = dbus_message_get_error_name (message);
03749 
03750   if (n && strcmp (n, error_name) == 0)
03751     return TRUE;
03752   else
03753     return FALSE;
03754 }
03755 
03766 dbus_bool_t
03767 dbus_message_has_destination (DBusMessage  *message,
03768                               const char   *name)
03769 {
03770   const char *s;
03771 
03772   _dbus_return_val_if_fail (message != NULL, FALSE);
03773   _dbus_return_val_if_fail (name != NULL, FALSE);
03774   /* don't check that name is valid since it would be expensive, and
03775    * not catch many common errors
03776    */
03777 
03778   s = dbus_message_get_destination (message);
03779 
03780   if (s && strcmp (s, name) == 0)
03781     return TRUE;
03782   else
03783     return FALSE;
03784 }
03785 
03801 dbus_bool_t
03802 dbus_message_has_sender (DBusMessage  *message,
03803                          const char   *name)
03804 {
03805   const char *s;
03806 
03807   _dbus_return_val_if_fail (message != NULL, FALSE);
03808   _dbus_return_val_if_fail (name != NULL, FALSE);
03809   /* don't check that name is valid since it would be expensive, and
03810    * not catch many common errors
03811    */
03812 
03813   s = dbus_message_get_sender (message);
03814 
03815   if (s && strcmp (s, name) == 0)
03816     return TRUE;
03817   else
03818     return FALSE;
03819 }
03820 
03830 dbus_bool_t
03831 dbus_message_has_signature (DBusMessage   *message,
03832                             const char    *signature)
03833 {
03834   const char *s;
03835 
03836   _dbus_return_val_if_fail (message != NULL, FALSE);
03837   _dbus_return_val_if_fail (signature != NULL, FALSE);
03838   /* don't check that signature is valid since it would be expensive,
03839    * and not catch many common errors
03840    */
03841 
03842   s = dbus_message_get_signature (message);
03843 
03844   if (s && strcmp (s, signature) == 0)
03845     return TRUE;
03846   else
03847     return FALSE;
03848 }
03849 
03872 dbus_bool_t
03873 dbus_set_error_from_message (DBusError   *error,
03874                              DBusMessage *message)
03875 {
03876   const char *str;
03877 
03878   _dbus_return_val_if_fail (message != NULL, FALSE);
03879   _dbus_return_val_if_error_is_set (error, FALSE);
03880 
03881   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03882     return FALSE;
03883 
03884   str = NULL;
03885   dbus_message_get_args (message, NULL,
03886                          DBUS_TYPE_STRING, &str,
03887                          DBUS_TYPE_INVALID);
03888 
03889   dbus_set_error (error, dbus_message_get_error_name (message),
03890                   str ? "%s" : NULL, str);
03891 
03892   return TRUE;
03893 }
03894 
03901 dbus_bool_t
03902 dbus_message_contains_unix_fds(DBusMessage *message)
03903 {
03904 #ifdef HAVE_UNIX_FD_PASSING
03905   _dbus_assert(message);
03906 
03907   return message->n_unix_fds > 0;
03908 #else
03909   return FALSE;
03910 #endif
03911 }
03912 
03931 #define INITIAL_LOADER_DATA_LEN 32
03932 
03939 DBusMessageLoader*
03940 _dbus_message_loader_new (void)
03941 {
03942   DBusMessageLoader *loader;
03943 
03944   loader = dbus_new0 (DBusMessageLoader, 1);
03945   if (loader == NULL)
03946     return NULL;
03947   
03948   loader->refcount = 1;
03949 
03950   loader->corrupted = FALSE;
03951   loader->corruption_reason = DBUS_VALID;
03952 
03953   /* this can be configured by the app, but defaults to the protocol max */
03954   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03955 
03956   /* We set a very relatively conservative default here since due to how
03957   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03958   number of unix fds we want to receive in advance. A
03959   try-and-reallocate loop is not possible. */
03960   loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
03961 
03962   if (!_dbus_string_init (&loader->data))
03963     {
03964       dbus_free (loader);
03965       return NULL;
03966     }
03967 
03968   /* preallocate the buffer for speed, ignore failure */
03969   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03970   _dbus_string_set_length (&loader->data, 0);
03971 
03972 #ifdef HAVE_UNIX_FD_PASSING
03973   loader->unix_fds = NULL;
03974   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03975   loader->unix_fds_outstanding = FALSE;
03976 #endif
03977 
03978   return loader;
03979 }
03980 
03987 DBusMessageLoader *
03988 _dbus_message_loader_ref (DBusMessageLoader *loader)
03989 {
03990   loader->refcount += 1;
03991 
03992   return loader;
03993 }
03994 
04001 void
04002 _dbus_message_loader_unref (DBusMessageLoader *loader)
04003 {
04004   loader->refcount -= 1;
04005   if (loader->refcount == 0)
04006     {
04007 #ifdef HAVE_UNIX_FD_PASSING
04008       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
04009       dbus_free(loader->unix_fds);
04010 #endif
04011       _dbus_list_foreach (&loader->messages,
04012                           (DBusForeachFunction) dbus_message_unref,
04013                           NULL);
04014       _dbus_list_clear (&loader->messages);
04015       _dbus_string_free (&loader->data);
04016       dbus_free (loader);
04017     }
04018 }
04019 
04038 void
04039 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
04040                                  DBusString        **buffer)
04041 {
04042   _dbus_assert (!loader->buffer_outstanding);
04043 
04044   *buffer = &loader->data;
04045 
04046   loader->buffer_outstanding = TRUE;
04047 }
04048 
04058 void
04059 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
04060                                     DBusString         *buffer)
04061 {
04062   _dbus_assert (loader->buffer_outstanding);
04063   _dbus_assert (buffer == &loader->data);
04064 
04065   loader->buffer_outstanding = FALSE;
04066 }
04067 
04078 dbus_bool_t
04079 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
04080                                   int               **fds,
04081                                   unsigned           *max_n_fds)
04082 {
04083 #ifdef HAVE_UNIX_FD_PASSING
04084   _dbus_assert (!loader->unix_fds_outstanding);
04085 
04086   /* Allocate space where we can put the fds we read. We allocate
04087      space for max_message_unix_fds since this is an
04088      upper limit how many fds can be received within a single
04089      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
04090      we are allocating the maximum possible array size right from the
04091      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
04092      there is no better way. */
04093 
04094   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
04095     {
04096       int *a = dbus_realloc(loader->unix_fds,
04097                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
04098 
04099       if (!a)
04100         return FALSE;
04101 
04102       loader->unix_fds = a;
04103       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
04104     }
04105 
04106   *fds = loader->unix_fds + loader->n_unix_fds;
04107   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
04108 
04109   loader->unix_fds_outstanding = TRUE;
04110   return TRUE;
04111 #else
04112   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
04113   return FALSE;
04114 #endif
04115 }
04116 
04127 void
04128 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
04129                                      int                *fds,
04130                                      unsigned            n_fds)
04131 {
04132 #ifdef HAVE_UNIX_FD_PASSING
04133   _dbus_assert(loader->unix_fds_outstanding);
04134   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
04135   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
04136 
04137   loader->n_unix_fds += n_fds;
04138   loader->unix_fds_outstanding = FALSE;
04139 
04140   if (n_fds && loader->unix_fds_change)
04141     loader->unix_fds_change (loader->unix_fds_change_data);
04142 #else
04143   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
04144 #endif
04145 }
04146 
04147 /*
04148  * FIXME when we move the header out of the buffer, that memmoves all
04149  * buffered messages. Kind of crappy.
04150  *
04151  * Also we copy the header and body, which is kind of crappy.  To
04152  * avoid this, we have to allow header and body to be in a single
04153  * memory block, which is good for messages we read and bad for
04154  * messages we are creating. But we could move_len() the buffer into
04155  * this single memory block, and move_len() will just swap the buffers
04156  * if you're moving the entire buffer replacing the dest string.
04157  *
04158  * We could also have the message loader tell the transport how many
04159  * bytes to read; so it would first ask for some arbitrary number like
04160  * 256, then if the message was incomplete it would use the
04161  * header/body len to ask for exactly the size of the message (or
04162  * blocks the size of a typical kernel buffer for the socket). That
04163  * way we don't get trailing bytes in the buffer that have to be
04164  * memmoved. Though I suppose we also don't have a chance of reading a
04165  * bunch of small messages at once, so the optimization may be stupid.
04166  *
04167  * Another approach would be to keep a "start" index into
04168  * loader->data and only delete it occasionally, instead of after
04169  * each message is loaded.
04170  *
04171  * load_message() returns FALSE if not enough memory OR the loader was corrupted
04172  */
04173 static dbus_bool_t
04174 load_message (DBusMessageLoader *loader,
04175               DBusMessage       *message,
04176               int                byte_order,
04177               int                fields_array_len,
04178               int                header_len,
04179               int                body_len)
04180 {
04181   dbus_bool_t oom;
04182   DBusValidity validity;
04183   const DBusString *type_str;
04184   int type_pos;
04185   DBusValidationMode mode;
04186   dbus_uint32_t n_unix_fds = 0;
04187 
04188   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
04189   
04190   oom = FALSE;
04191 
04192 #if 0
04193   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
04194 #endif
04195 
04196   /* 1. VALIDATE AND COPY OVER HEADER */
04197   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
04198   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
04199 
04200   if (!_dbus_header_load (&message->header,
04201                           mode,
04202                           &validity,
04203                           byte_order,
04204                           fields_array_len,
04205                           header_len,
04206                           body_len,
04207                           &loader->data, 0,
04208                           _dbus_string_get_length (&loader->data)))
04209     {
04210       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
04211 
04212       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
04213          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
04214       _dbus_assert (validity != DBUS_VALID);
04215 
04216       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
04217         oom = TRUE;
04218       else
04219         {
04220           loader->corrupted = TRUE;
04221           loader->corruption_reason = validity;
04222         }
04223       goto failed;
04224     }
04225 
04226   _dbus_assert (validity == DBUS_VALID);
04227 
04228   /* 2. VALIDATE BODY */
04229   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04230     {
04231       get_const_signature (&message->header, &type_str, &type_pos);
04232       
04233       /* Because the bytes_remaining arg is NULL, this validates that the
04234        * body is the right length
04235        */
04236       validity = _dbus_validate_body_with_reason (type_str,
04237                                                   type_pos,
04238                                                   byte_order,
04239                                                   NULL,
04240                                                   &loader->data,
04241                                                   header_len,
04242                                                   body_len);
04243       if (validity != DBUS_VALID)
04244         {
04245           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04246 
04247           loader->corrupted = TRUE;
04248           loader->corruption_reason = validity;
04249           
04250           goto failed;
04251         }
04252     }
04253 
04254   /* 3. COPY OVER UNIX FDS */
04255   _dbus_header_get_field_basic(&message->header,
04256                                DBUS_HEADER_FIELD_UNIX_FDS,
04257                                DBUS_TYPE_UINT32,
04258                                &n_unix_fds);
04259 
04260 #ifdef HAVE_UNIX_FD_PASSING
04261 
04262   if (n_unix_fds > loader->n_unix_fds)
04263     {
04264       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04265                     n_unix_fds, loader->n_unix_fds);
04266 
04267       loader->corrupted = TRUE;
04268       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04269       goto failed;
04270     }
04271 
04272   /* If this was a recycled message there might still be
04273      some memory allocated for the fds */
04274   dbus_free(message->unix_fds);
04275 
04276   if (n_unix_fds > 0)
04277     {
04278       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04279       if (message->unix_fds == NULL)
04280         {
04281           _dbus_verbose ("Failed to allocate file descriptor array\n");
04282           oom = TRUE;
04283           goto failed;
04284         }
04285 
04286       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04287       loader->n_unix_fds -= n_unix_fds;
04288       memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
04289 
04290       if (loader->unix_fds_change)
04291         loader->unix_fds_change (loader->unix_fds_change_data);
04292     }
04293   else
04294     message->unix_fds = NULL;
04295 
04296 #else
04297 
04298   if (n_unix_fds > 0)
04299     {
04300       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04301                      "but that's not supported on our platform, disconnecting.\n");
04302 
04303       loader->corrupted = TRUE;
04304       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04305       goto failed;
04306     }
04307 
04308 #endif
04309 
04310   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04311 
04312   if (!_dbus_list_append (&loader->messages, message))
04313     {
04314       _dbus_verbose ("Failed to append new message to loader queue\n");
04315       oom = TRUE;
04316       goto failed;
04317     }
04318 
04319   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04320   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04321                 (header_len + body_len));
04322 
04323   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04324     {
04325       _dbus_verbose ("Failed to move body into new message\n");
04326       oom = TRUE;
04327       goto failed;
04328     }
04329 
04330   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04331 
04332   /* don't waste more than 2k of memory */
04333   _dbus_string_compact (&loader->data, 2048);
04334 
04335   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04336   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04337 
04338   _dbus_verbose ("Loaded message %p\n", message);
04339 
04340   _dbus_assert (!oom);
04341   _dbus_assert (!loader->corrupted);
04342   _dbus_assert (loader->messages != NULL);
04343   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04344 
04345   return TRUE;
04346 
04347  failed:
04348 
04349   /* Clean up */
04350 
04351   /* does nothing if the message isn't in the list */
04352   _dbus_list_remove_last (&loader->messages, message);
04353   
04354   if (oom)
04355     _dbus_assert (!loader->corrupted);
04356   else
04357     _dbus_assert (loader->corrupted);
04358 
04359   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04360 
04361   return FALSE;
04362 }
04363 
04378 dbus_bool_t
04379 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04380 {
04381   while (!loader->corrupted &&
04382          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04383     {
04384       DBusValidity validity;
04385       int byte_order, fields_array_len, header_len, body_len;
04386 
04387       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04388                                                &validity,
04389                                                &byte_order,
04390                                                &fields_array_len,
04391                                                &header_len,
04392                                                &body_len,
04393                                                &loader->data, 0,
04394                                                _dbus_string_get_length (&loader->data)))
04395         {
04396           DBusMessage *message;
04397 
04398           _dbus_assert (validity == DBUS_VALID);
04399 
04400           message = dbus_message_new_empty_header ();
04401           if (message == NULL)
04402             return FALSE;
04403 
04404           if (!load_message (loader, message,
04405                              byte_order, fields_array_len,
04406                              header_len, body_len))
04407             {
04408               dbus_message_unref (message);
04409               /* load_message() returns false if corrupted or OOM; if
04410                * corrupted then return TRUE for not OOM
04411                */
04412               return loader->corrupted;
04413             }
04414 
04415           _dbus_assert (loader->messages != NULL);
04416           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04417         }
04418       else
04419         {
04420           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04421                          validity);
04422           if (validity != DBUS_VALID)
04423             {
04424               loader->corrupted = TRUE;
04425               loader->corruption_reason = validity;
04426             }
04427           return TRUE;
04428         }
04429     }
04430 
04431   return TRUE;
04432 }
04433 
04441 DBusMessage*
04442 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04443 {
04444   if (loader->messages)
04445     return loader->messages->data;
04446   else
04447     return NULL;
04448 }
04449 
04458 DBusMessage*
04459 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04460 {
04461   return _dbus_list_pop_first (&loader->messages);
04462 }
04463 
04472 DBusList*
04473 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04474 {
04475   return _dbus_list_pop_first_link (&loader->messages);
04476 }
04477 
04484 void
04485 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04486                                            DBusList           *link)
04487 {
04488   _dbus_list_prepend_link (&loader->messages, link);
04489 }
04490 
04500 dbus_bool_t
04501 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04502 {
04503   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04504                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04505   return loader->corrupted;
04506 }
04507 
04514 DBusValidity
04515 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04516 {
04517   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04518                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04519 
04520   return loader->corruption_reason;
04521 }
04522 
04529 void
04530 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04531                                            long                size)
04532 {
04533   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04534     {
04535       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04536                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04537       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04538     }
04539   loader->max_message_size = size;
04540 }
04541 
04548 long
04549 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04550 {
04551   return loader->max_message_size;
04552 }
04553 
04560 void
04561 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04562                                                long                n)
04563 {
04564   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04565     {
04566       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04567                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04568       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04569     }
04570   loader->max_message_unix_fds = n;
04571 }
04572 
04579 long
04580 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04581 {
04582   return loader->max_message_unix_fds;
04583 }
04584 
04590 int
04591 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
04592 {
04593 #ifdef HAVE_UNIX_FD_PASSING
04594   return loader->n_unix_fds;
04595 #else
04596   return 0;
04597 #endif
04598 }
04599 
04608 void
04609 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
04610                                                void (* callback) (void *),
04611                                                void *data)
04612 {
04613 #ifdef HAVE_UNIX_FD_PASSING
04614   loader->unix_fds_change = callback;
04615   loader->unix_fds_change_data = data;
04616 #endif
04617 }
04618 
04619 static DBusDataSlotAllocator slot_allocator =
04620   _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
04621 
04636 dbus_bool_t
04637 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04638 {
04639   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04640                                           slot_p);
04641 }
04642 
04654 void
04655 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04656 {
04657   _dbus_return_if_fail (*slot_p >= 0);
04658 
04659   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04660 }
04661 
04675 dbus_bool_t
04676 dbus_message_set_data (DBusMessage     *message,
04677                        dbus_int32_t     slot,
04678                        void            *data,
04679                        DBusFreeFunction free_data_func)
04680 {
04681   DBusFreeFunction old_free_func;
04682   void *old_data;
04683   dbus_bool_t retval;
04684 
04685   _dbus_return_val_if_fail (message != NULL, FALSE);
04686   _dbus_return_val_if_fail (slot >= 0, FALSE);
04687 
04688   retval = _dbus_data_slot_list_set (&slot_allocator,
04689                                      &message->slot_list,
04690                                      slot, data, free_data_func,
04691                                      &old_free_func, &old_data);
04692 
04693   if (retval)
04694     {
04695       /* Do the actual free outside the message lock */
04696       if (old_free_func)
04697         (* old_free_func) (old_data);
04698     }
04699 
04700   return retval;
04701 }
04702 
04711 void*
04712 dbus_message_get_data (DBusMessage   *message,
04713                        dbus_int32_t   slot)
04714 {
04715   void *res;
04716 
04717   _dbus_return_val_if_fail (message != NULL, NULL);
04718 
04719   res = _dbus_data_slot_list_get (&slot_allocator,
04720                                   &message->slot_list,
04721                                   slot);
04722 
04723   return res;
04724 }
04725 
04739 int
04740 dbus_message_type_from_string (const char *type_str)
04741 {
04742   if (strcmp (type_str, "method_call") == 0)
04743     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04744   if (strcmp (type_str, "method_return") == 0)
04745     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04746   else if (strcmp (type_str, "signal") == 0)
04747     return DBUS_MESSAGE_TYPE_SIGNAL;
04748   else if (strcmp (type_str, "error") == 0)
04749     return DBUS_MESSAGE_TYPE_ERROR;
04750   else
04751     return DBUS_MESSAGE_TYPE_INVALID;
04752 }
04753 
04767 const char *
04768 dbus_message_type_to_string (int type)
04769 {
04770   switch (type)
04771     {
04772     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04773       return "method_call";
04774     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04775       return "method_return";
04776     case DBUS_MESSAGE_TYPE_SIGNAL:
04777       return "signal";
04778     case DBUS_MESSAGE_TYPE_ERROR:
04779       return "error";
04780     default:
04781       return "invalid";
04782     }
04783 }
04784 
04797 dbus_bool_t
04798 dbus_message_marshal (DBusMessage  *msg,
04799                       char        **marshalled_data_p,
04800                       int          *len_p)
04801 {
04802   DBusString tmp;
04803   dbus_bool_t was_locked;
04804 
04805   _dbus_return_val_if_fail (msg != NULL, FALSE);
04806   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04807   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04808   
04809   if (!_dbus_string_init (&tmp))
04810     return FALSE;
04811 
04812   /* Ensure the message is locked, to ensure the length header is filled in. */
04813   was_locked = msg->locked;
04814 
04815   if (!was_locked)
04816     dbus_message_lock (msg);
04817 
04818   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04819     goto fail;
04820 
04821   *len_p = _dbus_string_get_length (&tmp);
04822 
04823   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04824     goto fail;
04825 
04826   *len_p = _dbus_string_get_length (&tmp);
04827 
04828   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04829     goto fail;
04830 
04831   _dbus_string_free (&tmp);
04832 
04833   if (!was_locked)
04834     msg->locked = FALSE;
04835 
04836   return TRUE;
04837 
04838  fail:
04839   _dbus_string_free (&tmp);
04840 
04841   if (!was_locked)
04842     msg->locked = FALSE;
04843 
04844   return FALSE;
04845 }
04846 
04859 DBusMessage *
04860 dbus_message_demarshal (const char *str,
04861                         int         len,
04862                         DBusError  *error)
04863 {
04864   DBusMessageLoader *loader;
04865   DBusString *buffer;
04866   DBusMessage *msg;
04867 
04868   _dbus_return_val_if_fail (str != NULL, NULL);
04869 
04870   loader = _dbus_message_loader_new ();
04871 
04872   if (loader == NULL)
04873     return NULL;
04874 
04875   _dbus_message_loader_get_buffer (loader, &buffer);
04876 
04877   if (!_dbus_string_append_len (buffer, str, len))
04878     goto fail_oom;
04879 
04880   _dbus_message_loader_return_buffer (loader, buffer);
04881 
04882   if (!_dbus_message_loader_queue_messages (loader))
04883     goto fail_oom;
04884 
04885   if (_dbus_message_loader_get_is_corrupted (loader))
04886     goto fail_corrupt;
04887 
04888   msg = _dbus_message_loader_pop_message (loader);
04889 
04890   if (!msg)
04891     goto fail_oom;
04892 
04893   _dbus_message_loader_unref (loader);
04894   return msg;
04895 
04896  fail_corrupt:
04897   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04898                   _dbus_validity_to_error_message (loader->corruption_reason));
04899   _dbus_message_loader_unref (loader);
04900   return NULL;
04901 
04902  fail_oom:
04903   _DBUS_SET_OOM (error);
04904   _dbus_message_loader_unref (loader);
04905   return NULL;
04906 }
04907 
04920 int 
04921 dbus_message_demarshal_bytes_needed(const char *buf, 
04922                                     int         len)
04923 {
04924   DBusString str;
04925   int byte_order, fields_array_len, header_len, body_len;
04926   DBusValidity validity = DBUS_VALID;
04927   int have_message;
04928 
04929   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04930     return 0;
04931 
04932   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04933     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04934   _dbus_string_init_const_len (&str, buf, len);
04935   
04936   validity = DBUS_VALID;
04937   have_message
04938     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04939                                           &validity, &byte_order,
04940                                           &fields_array_len,
04941                                           &header_len,
04942                                           &body_len,
04943                                           &str, 0,
04944                                           len);
04945   _dbus_string_free (&str);
04946 
04947   if (validity == DBUS_VALID)
04948     {
04949       _dbus_assert (have_message || (header_len + body_len) > len);
04950       (void) have_message; /* unused unless asserting */
04951       return header_len + body_len;
04952     }
04953   else
04954     {
04955       return -1; /* broken! */
04956     }
04957 }
04958 
04980 void
04981 dbus_message_set_allow_interactive_authorization (DBusMessage *message,
04982                                                   dbus_bool_t  allow)
04983 {
04984   _dbus_return_if_fail (message != NULL);
04985   _dbus_return_if_fail (!message->locked);
04986 
04987   _dbus_header_toggle_flag (&message->header,
04988                             DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION,
04989                             allow);
04990 }
04991 
04998 dbus_bool_t
04999 dbus_message_get_allow_interactive_authorization (DBusMessage *message)
05000 {
05001   _dbus_return_val_if_fail (message != NULL, FALSE);
05002 
05003   return _dbus_header_get_flag (&message->header,
05004                                 DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION);
05005 }
05006 
05009 /* tests in dbus-message-util.c */