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   _dbus_return_val_if_fail (message != NULL, FALSE);
01170   _dbus_return_val_if_fail (!message->locked, FALSE);
01171   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01172 
01173   return _dbus_header_set_field_basic (&message->header,
01174                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01175                                        DBUS_TYPE_UINT32,
01176                                        &reply_serial);
01177 }
01178 
01185 dbus_uint32_t
01186 dbus_message_get_reply_serial  (DBusMessage *message)
01187 {
01188   dbus_uint32_t v_UINT32;
01189 
01190   _dbus_return_val_if_fail (message != NULL, 0);
01191 
01192   if (_dbus_header_get_field_basic (&message->header,
01193                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01194                                     DBUS_TYPE_UINT32,
01195                                     &v_UINT32))
01196     return v_UINT32;
01197   else
01198     return 0;
01199 }
01200 
01201 static void
01202 dbus_message_finalize (DBusMessage *message)
01203 {
01204   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01205 
01206   /* This calls application callbacks! */
01207   _dbus_data_slot_list_free (&message->slot_list);
01208 
01209   _dbus_list_foreach (&message->counters,
01210                       free_counter, message);
01211   _dbus_list_clear (&message->counters);
01212 
01213   _dbus_header_free (&message->header);
01214   _dbus_string_free (&message->body);
01215 
01216 #ifdef HAVE_UNIX_FD_PASSING
01217   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01218   dbus_free(message->unix_fds);
01219 #endif
01220 
01221   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01222 
01223   dbus_free (message);
01224 }
01225 
01226 static DBusMessage*
01227 dbus_message_new_empty_header (void)
01228 {
01229   DBusMessage *message;
01230   dbus_bool_t from_cache;
01231 
01232   message = dbus_message_get_cached ();
01233 
01234   if (message != NULL)
01235     {
01236       from_cache = TRUE;
01237     }
01238   else
01239     {
01240       from_cache = FALSE;
01241       message = dbus_new0 (DBusMessage, 1);
01242       if (message == NULL)
01243         return NULL;
01244 #ifndef DBUS_DISABLE_CHECKS
01245       message->generation = _dbus_current_generation;
01246 #endif
01247 
01248 #ifdef HAVE_UNIX_FD_PASSING
01249       message->unix_fds = NULL;
01250       message->n_unix_fds_allocated = 0;
01251 #endif
01252     }
01253 
01254   _dbus_atomic_inc (&message->refcount);
01255 
01256   _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
01257 
01258   message->locked = FALSE;
01259 #ifndef DBUS_DISABLE_CHECKS
01260   message->in_cache = FALSE;
01261 #endif
01262   message->counters = NULL;
01263   message->size_counter_delta = 0;
01264   message->changed_stamp = 0;
01265 
01266 #ifdef HAVE_UNIX_FD_PASSING
01267   message->n_unix_fds = 0;
01268   message->n_unix_fds_allocated = 0;
01269   message->unix_fd_counter_delta = 0;
01270 #endif
01271 
01272   if (!from_cache)
01273     _dbus_data_slot_list_init (&message->slot_list);
01274 
01275   if (from_cache)
01276     {
01277       _dbus_header_reinit (&message->header);
01278       _dbus_string_set_length (&message->body, 0);
01279     }
01280   else
01281     {
01282       if (!_dbus_header_init (&message->header))
01283         {
01284           dbus_free (message);
01285           return NULL;
01286         }
01287 
01288       if (!_dbus_string_init_preallocated (&message->body, 32))
01289         {
01290           _dbus_header_free (&message->header);
01291           dbus_free (message);
01292           return NULL;
01293         }
01294     }
01295 
01296   return message;
01297 }
01298 
01311 DBusMessage*
01312 dbus_message_new (int message_type)
01313 {
01314   DBusMessage *message;
01315 
01316   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01317 
01318   message = dbus_message_new_empty_header ();
01319   if (message == NULL)
01320     return NULL;
01321 
01322   if (!_dbus_header_create (&message->header,
01323                             DBUS_COMPILER_BYTE_ORDER,
01324                             message_type,
01325                             NULL, NULL, NULL, NULL, NULL))
01326     {
01327       dbus_message_unref (message);
01328       return NULL;
01329     }
01330 
01331   return message;
01332 }
01333 
01355 DBusMessage*
01356 dbus_message_new_method_call (const char *destination,
01357                               const char *path,
01358                               const char *iface,
01359                               const char *method)
01360 {
01361   DBusMessage *message;
01362 
01363   _dbus_return_val_if_fail (path != NULL, NULL);
01364   _dbus_return_val_if_fail (method != NULL, NULL);
01365   _dbus_return_val_if_fail (destination == NULL ||
01366                             _dbus_check_is_valid_bus_name (destination), NULL);
01367   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01368   _dbus_return_val_if_fail (iface == NULL ||
01369                             _dbus_check_is_valid_interface (iface), NULL);
01370   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01371 
01372   message = dbus_message_new_empty_header ();
01373   if (message == NULL)
01374     return NULL;
01375 
01376   if (!_dbus_header_create (&message->header,
01377                             DBUS_COMPILER_BYTE_ORDER,
01378                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01379                             destination, path, iface, method, NULL))
01380     {
01381       dbus_message_unref (message);
01382       return NULL;
01383     }
01384 
01385   return message;
01386 }
01387 
01395 DBusMessage*
01396 dbus_message_new_method_return (DBusMessage *method_call)
01397 {
01398   DBusMessage *message;
01399   const char *sender;
01400 
01401   _dbus_return_val_if_fail (method_call != NULL, NULL);
01402 
01403   sender = dbus_message_get_sender (method_call);
01404 
01405   /* sender is allowed to be null here in peer-to-peer case */
01406 
01407   message = dbus_message_new_empty_header ();
01408   if (message == NULL)
01409     return NULL;
01410 
01411   if (!_dbus_header_create (&message->header,
01412                             DBUS_COMPILER_BYTE_ORDER,
01413                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01414                             sender, NULL, NULL, NULL, NULL))
01415     {
01416       dbus_message_unref (message);
01417       return NULL;
01418     }
01419 
01420   dbus_message_set_no_reply (message, TRUE);
01421 
01422   if (!dbus_message_set_reply_serial (message,
01423                                       dbus_message_get_serial (method_call)))
01424     {
01425       dbus_message_unref (message);
01426       return NULL;
01427     }
01428 
01429   return message;
01430 }
01431 
01446 DBusMessage*
01447 dbus_message_new_signal (const char *path,
01448                          const char *iface,
01449                          const char *name)
01450 {
01451   DBusMessage *message;
01452 
01453   _dbus_return_val_if_fail (path != NULL, NULL);
01454   _dbus_return_val_if_fail (iface != NULL, NULL);
01455   _dbus_return_val_if_fail (name != NULL, NULL);
01456   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01457   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
01458   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01459 
01460   message = dbus_message_new_empty_header ();
01461   if (message == NULL)
01462     return NULL;
01463 
01464   if (!_dbus_header_create (&message->header,
01465                             DBUS_COMPILER_BYTE_ORDER,
01466                             DBUS_MESSAGE_TYPE_SIGNAL,
01467                             NULL, path, iface, name, NULL))
01468     {
01469       dbus_message_unref (message);
01470       return NULL;
01471     }
01472 
01473   dbus_message_set_no_reply (message, TRUE);
01474 
01475   return message;
01476 }
01477 
01492 DBusMessage*
01493 dbus_message_new_error (DBusMessage *reply_to,
01494                         const char  *error_name,
01495                         const char  *error_message)
01496 {
01497   DBusMessage *message;
01498   const char *sender;
01499   DBusMessageIter iter;
01500 
01501   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01502   _dbus_return_val_if_fail (error_name != NULL, NULL);
01503   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01504 
01505   sender = dbus_message_get_sender (reply_to);
01506 
01507   /* sender may be NULL for non-message-bus case or
01508    * when the message bus is dealing with an unregistered
01509    * connection.
01510    */
01511   message = dbus_message_new_empty_header ();
01512   if (message == NULL)
01513     return NULL;
01514 
01515   if (!_dbus_header_create (&message->header,
01516                             DBUS_COMPILER_BYTE_ORDER,
01517                             DBUS_MESSAGE_TYPE_ERROR,
01518                             sender, NULL, NULL, NULL, error_name))
01519     {
01520       dbus_message_unref (message);
01521       return NULL;
01522     }
01523 
01524   dbus_message_set_no_reply (message, TRUE);
01525 
01526   if (!dbus_message_set_reply_serial (message,
01527                                       dbus_message_get_serial (reply_to)))
01528     {
01529       dbus_message_unref (message);
01530       return NULL;
01531     }
01532 
01533   if (error_message != NULL)
01534     {
01535       dbus_message_iter_init_append (message, &iter);
01536       if (!dbus_message_iter_append_basic (&iter,
01537                                            DBUS_TYPE_STRING,
01538                                            &error_message))
01539         {
01540           dbus_message_unref (message);
01541           return NULL;
01542         }
01543     }
01544 
01545   return message;
01546 }
01547 
01564 DBusMessage*
01565 dbus_message_new_error_printf (DBusMessage *reply_to,
01566                                const char  *error_name,
01567                                const char  *error_format,
01568                                ...)
01569 {
01570   va_list args;
01571   DBusString str;
01572   DBusMessage *message;
01573 
01574   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01575   _dbus_return_val_if_fail (error_name != NULL, NULL);
01576   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01577 
01578   if (!_dbus_string_init (&str))
01579     return NULL;
01580 
01581   va_start (args, error_format);
01582 
01583   if (_dbus_string_append_printf_valist (&str, error_format, args))
01584     message = dbus_message_new_error (reply_to, error_name,
01585                                       _dbus_string_get_const_data (&str));
01586   else
01587     message = NULL;
01588 
01589   _dbus_string_free (&str);
01590 
01591   va_end (args);
01592 
01593   return message;
01594 }
01595 
01596 
01609 DBusMessage *
01610 dbus_message_copy (const DBusMessage *message)
01611 {
01612   DBusMessage *retval;
01613 
01614   _dbus_return_val_if_fail (message != NULL, NULL);
01615 
01616   retval = dbus_new0 (DBusMessage, 1);
01617   if (retval == NULL)
01618     return NULL;
01619 
01620   _dbus_atomic_inc (&retval->refcount);
01621 
01622   retval->locked = FALSE;
01623 #ifndef DBUS_DISABLE_CHECKS
01624   retval->generation = message->generation;
01625 #endif
01626 
01627   if (!_dbus_header_copy (&message->header, &retval->header))
01628     {
01629       dbus_free (retval);
01630       return NULL;
01631     }
01632 
01633   if (!_dbus_string_init_preallocated (&retval->body,
01634                                        _dbus_string_get_length (&message->body)))
01635     {
01636       _dbus_header_free (&retval->header);
01637       dbus_free (retval);
01638       return NULL;
01639     }
01640 
01641   if (!_dbus_string_copy (&message->body, 0,
01642                           &retval->body, 0))
01643     goto failed_copy;
01644 
01645 #ifdef HAVE_UNIX_FD_PASSING
01646   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01647   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01648     goto failed_copy;
01649 
01650   retval->n_unix_fds_allocated = message->n_unix_fds;
01651 
01652   for (retval->n_unix_fds = 0;
01653        retval->n_unix_fds < message->n_unix_fds;
01654        retval->n_unix_fds++)
01655     {
01656       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01657 
01658       if (retval->unix_fds[retval->n_unix_fds] < 0)
01659         goto failed_copy;
01660     }
01661 
01662 #endif
01663 
01664   _dbus_message_trace_ref (retval, 0, 1, "copy");
01665   return retval;
01666 
01667  failed_copy:
01668   _dbus_header_free (&retval->header);
01669   _dbus_string_free (&retval->body);
01670 
01671 #ifdef HAVE_UNIX_FD_PASSING
01672   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01673   dbus_free(retval->unix_fds);
01674 #endif
01675 
01676   dbus_free (retval);
01677 
01678   return NULL;
01679 }
01680 
01681 
01689 DBusMessage *
01690 dbus_message_ref (DBusMessage *message)
01691 {
01692   dbus_int32_t old_refcount;
01693 
01694   _dbus_return_val_if_fail (message != NULL, NULL);
01695   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01696   _dbus_return_val_if_fail (!message->in_cache, NULL);
01697 
01698   old_refcount = _dbus_atomic_inc (&message->refcount);
01699   _dbus_assert (old_refcount >= 1);
01700   _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
01701 
01702   return message;
01703 }
01704 
01712 void
01713 dbus_message_unref (DBusMessage *message)
01714 {
01715  dbus_int32_t old_refcount;
01716 
01717   _dbus_return_if_fail (message != NULL);
01718   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01719   _dbus_return_if_fail (!message->in_cache);
01720 
01721   old_refcount = _dbus_atomic_dec (&message->refcount);
01722 
01723   _dbus_assert (old_refcount >= 1);
01724 
01725   _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
01726 
01727   if (old_refcount == 1)
01728     {
01729       /* Calls application callbacks! */
01730       dbus_message_cache_or_finalize (message);
01731     }
01732 }
01733 
01744 int
01745 dbus_message_get_type (DBusMessage *message)
01746 {
01747   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01748 
01749   return _dbus_header_get_message_type (&message->header);
01750 }
01751 
01814 dbus_bool_t
01815 dbus_message_append_args (DBusMessage *message,
01816                           int          first_arg_type,
01817                           ...)
01818 {
01819   dbus_bool_t retval;
01820   va_list var_args;
01821 
01822   _dbus_return_val_if_fail (message != NULL, FALSE);
01823 
01824   va_start (var_args, first_arg_type);
01825   retval = dbus_message_append_args_valist (message,
01826                                             first_arg_type,
01827                                             var_args);
01828   va_end (var_args);
01829 
01830   return retval;
01831 }
01832 
01846 dbus_bool_t
01847 dbus_message_append_args_valist (DBusMessage *message,
01848                                  int          first_arg_type,
01849                                  va_list      var_args)
01850 {
01851   int type;
01852   DBusMessageIter iter;
01853 
01854   _dbus_return_val_if_fail (message != NULL, FALSE);
01855 
01856   type = first_arg_type;
01857 
01858   dbus_message_iter_init_append (message, &iter);
01859 
01860   while (type != DBUS_TYPE_INVALID)
01861     {
01862       if (dbus_type_is_basic (type))
01863         {
01864           const DBusBasicValue *value;
01865           value = va_arg (var_args, const DBusBasicValue*);
01866 
01867           if (!dbus_message_iter_append_basic (&iter,
01868                                                type,
01869                                                value))
01870             goto failed;
01871         }
01872       else if (type == DBUS_TYPE_ARRAY)
01873         {
01874           int element_type;
01875           DBusMessageIter array;
01876           char buf[2];
01877 
01878           element_type = va_arg (var_args, int);
01879               
01880           buf[0] = element_type;
01881           buf[1] = '\0';
01882           if (!dbus_message_iter_open_container (&iter,
01883                                                  DBUS_TYPE_ARRAY,
01884                                                  buf,
01885                                                  &array))
01886             goto failed;
01887 
01888           if (dbus_type_is_fixed (element_type) &&
01889               element_type != DBUS_TYPE_UNIX_FD)
01890             {
01891               const DBusBasicValue **value;
01892               int n_elements;
01893 
01894               value = va_arg (var_args, const DBusBasicValue**);
01895               n_elements = va_arg (var_args, int);
01896               
01897               if (!dbus_message_iter_append_fixed_array (&array,
01898                                                          element_type,
01899                                                          value,
01900                                                          n_elements)) {
01901                 dbus_message_iter_abandon_container (&iter, &array);
01902                 goto failed;
01903               }
01904             }
01905           else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
01906             {
01907               const char ***value_p;
01908               const char **value;
01909               int n_elements;
01910               int i;
01911               
01912               value_p = va_arg (var_args, const char***);
01913               n_elements = va_arg (var_args, int);
01914 
01915               value = *value_p;
01916               
01917               i = 0;
01918               while (i < n_elements)
01919                 {
01920                   if (!dbus_message_iter_append_basic (&array,
01921                                                        element_type,
01922                                                        &value[i])) {
01923                     dbus_message_iter_abandon_container (&iter, &array);
01924                     goto failed;
01925                   }
01926                   ++i;
01927                 }
01928             }
01929           else
01930             {
01931               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01932                           _dbus_type_to_string (element_type),
01933                           _DBUS_FUNCTION_NAME);
01934               goto failed;
01935             }
01936 
01937           if (!dbus_message_iter_close_container (&iter, &array))
01938             goto failed;
01939         }
01940 #ifndef DBUS_DISABLE_CHECKS
01941       else
01942         {
01943           _dbus_warn ("type %s isn't supported yet in %s\n",
01944                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01945           goto failed;
01946         }
01947 #endif
01948 
01949       type = va_arg (var_args, int);
01950     }
01951 
01952   return TRUE;
01953 
01954  failed:
01955   return FALSE;
01956 }
01957 
02002 dbus_bool_t
02003 dbus_message_get_args (DBusMessage     *message,
02004                        DBusError       *error,
02005                        int              first_arg_type,
02006                        ...)
02007 {
02008   dbus_bool_t retval;
02009   va_list var_args;
02010 
02011   _dbus_return_val_if_fail (message != NULL, FALSE);
02012   _dbus_return_val_if_error_is_set (error, FALSE);
02013 
02014   va_start (var_args, first_arg_type);
02015   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
02016   va_end (var_args);
02017 
02018   return retval;
02019 }
02020 
02031 dbus_bool_t
02032 dbus_message_get_args_valist (DBusMessage     *message,
02033                               DBusError       *error,
02034                               int              first_arg_type,
02035                               va_list          var_args)
02036 {
02037   DBusMessageIter iter;
02038 
02039   _dbus_return_val_if_fail (message != NULL, FALSE);
02040   _dbus_return_val_if_error_is_set (error, FALSE);
02041 
02042   dbus_message_iter_init (message, &iter);
02043   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
02044 }
02045 
02046 static void
02047 _dbus_message_iter_init_common (DBusMessage         *message,
02048                                 DBusMessageRealIter *real,
02049                                 int                  iter_type)
02050 {
02051   /* If these static assertions fail on your platform, report it as a bug. */
02052   _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
02053   _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
02054       _DBUS_ALIGNOF (DBusMessageIter));
02055   /* A failure of these two assertions would indicate that we've broken
02056    * ABI on this platform since 1.10.0. */
02057   _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
02058       sizeof (DBusMessageIter));
02059   _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
02060       _DBUS_ALIGNOF (DBusMessageIter));
02061   /* If this static assertion fails, it means the DBusMessageIter struct
02062    * is not "packed", which might result in "iter = other_iter" not copying
02063    * every byte. */
02064   _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
02065       4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
02066 
02067   /* Since the iterator will read or write who-knows-what from the
02068    * message, we need to get in the right byte order
02069    */
02070   ensure_byte_order (message);
02071   
02072   real->message = message;
02073   real->changed_stamp = message->changed_stamp;
02074   real->iter_type = iter_type;
02075   real->sig_refcount = 0;
02076 }
02077 
02100 dbus_bool_t
02101 dbus_message_iter_init (DBusMessage     *message,
02102                         DBusMessageIter *iter)
02103 {
02104   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02105   const DBusString *type_str;
02106   int type_pos;
02107 
02108   _dbus_return_val_if_fail (message != NULL, FALSE);
02109   _dbus_return_val_if_fail (iter != NULL, FALSE);
02110 
02111   get_const_signature (&message->header, &type_str, &type_pos);
02112 
02113   _dbus_message_iter_init_common (message, real,
02114                                   DBUS_MESSAGE_ITER_TYPE_READER);
02115 
02116   _dbus_type_reader_init (&real->u.reader,
02117                           _dbus_header_get_byte_order (&message->header),
02118                           type_str, type_pos,
02119                           &message->body,
02120                           0);
02121 
02122   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
02123 }
02124 
02131 dbus_bool_t
02132 dbus_message_iter_has_next (DBusMessageIter *iter)
02133 {
02134   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02135 
02136   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02137   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02138 
02139   return _dbus_type_reader_has_next (&real->u.reader);
02140 }
02141 
02150 dbus_bool_t
02151 dbus_message_iter_next (DBusMessageIter *iter)
02152 {
02153   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02154 
02155   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02156   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02157 
02158   return _dbus_type_reader_next (&real->u.reader);
02159 }
02160 
02175 int
02176 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02177 {
02178   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02179 
02180   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02181   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02182 
02183   return _dbus_type_reader_get_current_type (&real->u.reader);
02184 }
02185 
02194 int
02195 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02196 {
02197   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02198 
02199   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02200   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02201   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02202 
02203   return _dbus_type_reader_get_element_type (&real->u.reader);
02204 }
02205 
02231 void
02232 dbus_message_iter_recurse (DBusMessageIter  *iter,
02233                            DBusMessageIter  *sub)
02234 {
02235   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02236   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02237 
02238   _dbus_return_if_fail (_dbus_message_iter_check (real));
02239   _dbus_return_if_fail (sub != NULL);
02240 
02241   *real_sub = *real;
02242   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02243 }
02244 
02256 char *
02257 dbus_message_iter_get_signature (DBusMessageIter *iter)
02258 {
02259   const DBusString *sig;
02260   DBusString retstr;
02261   char *ret;
02262   int start, len;
02263   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02264 
02265   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02266 
02267   if (!_dbus_string_init (&retstr))
02268     return NULL;
02269 
02270   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02271                                    &start, &len);
02272   if (!_dbus_string_append_len (&retstr,
02273                                 _dbus_string_get_const_data (sig) + start,
02274                                 len))
02275     return NULL;
02276   if (!_dbus_string_steal_data (&retstr, &ret))
02277     return NULL;
02278   _dbus_string_free (&retstr);
02279   return ret;
02280 }
02281 
02329 void
02330 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02331                              void             *value)
02332 {
02333   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02334 
02335   _dbus_return_if_fail (_dbus_message_iter_check (real));
02336   _dbus_return_if_fail (value != NULL);
02337 
02338   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02339     {
02340 #ifdef HAVE_UNIX_FD_PASSING
02341       DBusBasicValue idx;
02342 
02343       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02344 
02345       if (idx.u32 >= real->message->n_unix_fds) {
02346         /* Hmm, we cannot really signal an error here, so let's make
02347            sure to return an invalid fd. */
02348         *((int*) value) = -1;
02349         return;
02350       }
02351 
02352       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02353 #else
02354       *((int*) value) = -1;
02355 #endif
02356     }
02357   else
02358     {
02359       _dbus_type_reader_read_basic (&real->u.reader,
02360                                     value);
02361     }
02362 }
02363 
02374 int
02375 dbus_message_iter_get_element_count (DBusMessageIter *iter)
02376 {
02377   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02378   DBusTypeReader array;
02379   int element_type;
02380   int n_elements = 0;
02381 
02382   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02383   _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
02384                             == DBUS_TYPE_ARRAY, 0);
02385 
02386   element_type = _dbus_type_reader_get_element_type (&real->u.reader);
02387   _dbus_type_reader_recurse (&real->u.reader, &array);
02388   if (dbus_type_is_fixed (element_type))
02389     {
02390       int alignment = _dbus_type_get_alignment (element_type);
02391       int total_len = _dbus_type_reader_get_array_length (&array);
02392       n_elements = total_len / alignment;
02393     }
02394   else
02395     {
02396       while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
02397         {
02398           ++n_elements;
02399           _dbus_type_reader_next (&array);
02400         }
02401     }
02402 
02403    return n_elements;
02404 }
02405 
02418 int
02419 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02420 {
02421   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02422 
02423   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02424 
02425   return _dbus_type_reader_get_array_length (&real->u.reader);
02426 }
02427 
02463 void
02464 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02465                                    void             *value,
02466                                    int              *n_elements)
02467 {
02468   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02469 #ifndef DBUS_DISABLE_CHECKS
02470   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02471 
02472   _dbus_return_if_fail (_dbus_message_iter_check (real));
02473   _dbus_return_if_fail (value != NULL);
02474   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02475                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02476 #endif
02477 
02478   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02479                                       value, n_elements);
02480 }
02481 
02493 void
02494 dbus_message_iter_init_append (DBusMessage     *message,
02495                                DBusMessageIter *iter)
02496 {
02497   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02498 
02499   _dbus_return_if_fail (message != NULL);
02500   _dbus_return_if_fail (iter != NULL);
02501 
02502   _dbus_message_iter_init_common (message, real,
02503                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02504 
02505   /* We create the signature string and point iterators at it "on demand"
02506    * when a value is actually appended. That means that init() never fails
02507    * due to OOM.
02508    */
02509   _dbus_type_writer_init_types_delayed (&real->u.writer,
02510                                         _dbus_header_get_byte_order (&message->header),
02511                                         &message->body,
02512                                         _dbus_string_get_length (&message->body));
02513 }
02514 
02523 static dbus_bool_t
02524 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02525 {
02526   DBusString *str;
02527   const DBusString *current_sig;
02528   int current_sig_pos;
02529 
02530   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02531 
02532   if (real->u.writer.type_str != NULL)
02533     {
02534       _dbus_assert (real->sig_refcount > 0);
02535       real->sig_refcount += 1;
02536       return TRUE;
02537     }
02538 
02539   str = dbus_new (DBusString, 1);
02540   if (str == NULL)
02541     return FALSE;
02542 
02543   if (!_dbus_header_get_field_raw (&real->message->header,
02544                                    DBUS_HEADER_FIELD_SIGNATURE,
02545                                    &current_sig, &current_sig_pos))
02546     current_sig = NULL;
02547 
02548   if (current_sig)
02549     {
02550       int current_len;
02551 
02552       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02553       current_sig_pos += 1; /* move on to sig data */
02554 
02555       if (!_dbus_string_init_preallocated (str, current_len + 4))
02556         {
02557           dbus_free (str);
02558           return FALSE;
02559         }
02560 
02561       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02562                                   str, 0))
02563         {
02564           _dbus_string_free (str);
02565           dbus_free (str);
02566           return FALSE;
02567         }
02568     }
02569   else
02570     {
02571       if (!_dbus_string_init_preallocated (str, 4))
02572         {
02573           dbus_free (str);
02574           return FALSE;
02575         }
02576     }
02577 
02578   real->sig_refcount = 1;
02579 
02580   _dbus_type_writer_add_types (&real->u.writer,
02581                                str, _dbus_string_get_length (str));
02582   return TRUE;
02583 }
02584 
02594 static dbus_bool_t
02595 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02596 {
02597   DBusString *str;
02598   const char *v_STRING;
02599   dbus_bool_t retval;
02600 
02601   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02602   _dbus_assert (real->u.writer.type_str != NULL);
02603   _dbus_assert (real->sig_refcount > 0);
02604 
02605   real->sig_refcount -= 1;
02606 
02607   if (real->sig_refcount > 0)
02608     return TRUE;
02609   _dbus_assert (real->sig_refcount == 0);
02610 
02611   retval = TRUE;
02612 
02613   str = real->u.writer.type_str;
02614 
02615   v_STRING = _dbus_string_get_const_data (str);
02616   if (!_dbus_header_set_field_basic (&real->message->header,
02617                                      DBUS_HEADER_FIELD_SIGNATURE,
02618                                      DBUS_TYPE_SIGNATURE,
02619                                      &v_STRING))
02620     retval = FALSE;
02621 
02622   _dbus_type_writer_remove_types (&real->u.writer);
02623   _dbus_string_free (str);
02624   dbus_free (str);
02625 
02626   return retval;
02627 }
02628 
02636 static void
02637 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02638 {
02639   DBusString *str;
02640 
02641   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02642   _dbus_assert (real->u.writer.type_str != NULL);
02643   _dbus_assert (real->sig_refcount > 0);
02644 
02645   real->sig_refcount -= 1;
02646 
02647   if (real->sig_refcount > 0)
02648     return;
02649   _dbus_assert (real->sig_refcount == 0);
02650 
02651   str = real->u.writer.type_str;
02652 
02653   _dbus_type_writer_remove_types (&real->u.writer);
02654   _dbus_string_free (str);
02655   dbus_free (str);
02656 }
02657 
02658 #ifndef DBUS_DISABLE_CHECKS
02659 static dbus_bool_t
02660 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02661 {
02662   if (!_dbus_message_iter_check (iter))
02663     return FALSE;
02664 
02665   if (iter->message->locked)
02666     {
02667       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02668       return FALSE;
02669     }
02670 
02671   return TRUE;
02672 }
02673 #endif /* DBUS_DISABLE_CHECKS */
02674 
02675 #ifdef HAVE_UNIX_FD_PASSING
02676 static int *
02677 expand_fd_array(DBusMessage *m,
02678                 unsigned     n)
02679 {
02680   _dbus_assert(m);
02681 
02682   /* This makes space for adding n new fds to the array and returns a
02683      pointer to the place were the first fd should be put. */
02684 
02685   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02686     {
02687       unsigned k;
02688       int *p;
02689 
02690       /* Make twice as much space as necessary */
02691       k = (m->n_unix_fds + n) * 2;
02692 
02693       /* Allocate at least four */
02694       if (k < 4)
02695         k = 4;
02696 
02697       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02698       if (p == NULL)
02699         return NULL;
02700 
02701       m->unix_fds = p;
02702       m->n_unix_fds_allocated = k;
02703     }
02704 
02705   return m->unix_fds + m->n_unix_fds;
02706 }
02707 #endif
02708 
02728 dbus_bool_t
02729 dbus_message_iter_append_basic (DBusMessageIter *iter,
02730                                 int              type,
02731                                 const void      *value)
02732 {
02733   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02734   dbus_bool_t ret;
02735 
02736   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02737   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02738   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02739   _dbus_return_val_if_fail (value != NULL, FALSE);
02740 
02741 #ifndef DBUS_DISABLE_CHECKS
02742   switch (type)
02743     {
02744       const char * const *string_p;
02745       const dbus_bool_t *bool_p;
02746 
02747       case DBUS_TYPE_STRING:
02748         string_p = value;
02749         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02750         break;
02751 
02752       case DBUS_TYPE_OBJECT_PATH:
02753         string_p = value;
02754         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02755         break;
02756 
02757       case DBUS_TYPE_SIGNATURE:
02758         string_p = value;
02759         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02760         break;
02761 
02762       case DBUS_TYPE_BOOLEAN:
02763         bool_p = value;
02764         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02765         break;
02766 
02767       default:
02768           {
02769             /* nothing to check, all possible values are allowed */
02770           }
02771     }
02772 #endif
02773 
02774   if (!_dbus_message_iter_open_signature (real))
02775     return FALSE;
02776 
02777   if (type == DBUS_TYPE_UNIX_FD)
02778     {
02779 #ifdef HAVE_UNIX_FD_PASSING
02780       int *fds;
02781       dbus_uint32_t u;
02782 
02783       /* First step, include the fd in the fd list of this message */
02784       if (!(fds = expand_fd_array(real->message, 1)))
02785         return FALSE;
02786 
02787       *fds = _dbus_dup(*(int*) value, NULL);
02788       if (*fds < 0)
02789         return FALSE;
02790 
02791       u = real->message->n_unix_fds;
02792 
02793       /* Second step, write the index to the fd */
02794       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02795         _dbus_close(*fds, NULL);
02796         return FALSE;
02797       }
02798 
02799       real->message->n_unix_fds += 1;
02800       u += 1;
02801 
02802       /* Final step, update the header accordingly */
02803       ret = _dbus_header_set_field_basic (&real->message->header,
02804                                           DBUS_HEADER_FIELD_UNIX_FDS,
02805                                           DBUS_TYPE_UINT32,
02806                                           &u);
02807 
02808       /* If any of these operations fail the message is
02809          hosed. However, no memory or fds should be leaked since what
02810          has been added to message has been added to the message, and
02811          can hence be accounted for when the message is being
02812          freed. */
02813 #else
02814       ret = FALSE;
02815 #endif
02816     }
02817   else
02818     {
02819       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02820     }
02821 
02822   if (!_dbus_message_iter_close_signature (real))
02823     ret = FALSE;
02824 
02825   return ret;
02826 }
02827 
02863 dbus_bool_t
02864 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02865                                       int              element_type,
02866                                       const void      *value,
02867                                       int              n_elements)
02868 {
02869   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02870   dbus_bool_t ret;
02871 
02872   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02873   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02874   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02875   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02876   _dbus_return_val_if_fail (value != NULL, FALSE);
02877   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02878   _dbus_return_val_if_fail (n_elements <=
02879                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02880                             FALSE);
02881 
02882 #ifndef DBUS_DISABLE_CHECKS
02883   if (element_type == DBUS_TYPE_BOOLEAN)
02884     {
02885       const dbus_bool_t * const *bools = value;
02886       int i;
02887 
02888       for (i = 0; i < n_elements; i++)
02889         {
02890           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02891         }
02892     }
02893 #endif
02894 
02895   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02896 
02897   return ret;
02898 }
02899 
02921 dbus_bool_t
02922 dbus_message_iter_open_container (DBusMessageIter *iter,
02923                                   int              type,
02924                                   const char      *contained_signature,
02925                                   DBusMessageIter *sub)
02926 {
02927   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02928   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02929   DBusString contained_str;
02930 
02931   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02932   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02933   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02934   _dbus_return_val_if_fail (sub != NULL, FALSE);
02935   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02936                              contained_signature == NULL) ||
02937                             (type == DBUS_TYPE_DICT_ENTRY &&
02938                              contained_signature == NULL) ||
02939                             (type == DBUS_TYPE_VARIANT &&
02940                              contained_signature != NULL) ||
02941                             (type == DBUS_TYPE_ARRAY &&
02942                              contained_signature != NULL), FALSE);
02943   
02944   /* this would fail if the contained_signature is a dict entry, since
02945    * dict entries are invalid signatures standalone (they must be in
02946    * an array)
02947    */
02948   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02949                             (contained_signature == NULL ||
02950                              _dbus_check_is_valid_signature (contained_signature)),
02951                             FALSE);
02952 
02953   if (!_dbus_message_iter_open_signature (real))
02954     return FALSE;
02955 
02956   *real_sub = *real;
02957 
02958   if (contained_signature != NULL)
02959     {
02960       _dbus_string_init_const (&contained_str, contained_signature);
02961 
02962       return _dbus_type_writer_recurse (&real->u.writer,
02963                                         type,
02964                                         &contained_str, 0,
02965                                         &real_sub->u.writer);
02966     }
02967   else
02968     {
02969       return _dbus_type_writer_recurse (&real->u.writer,
02970                                         type,
02971                                         NULL, 0,
02972                                         &real_sub->u.writer);
02973     } 
02974 }
02975 
02976 
02990 dbus_bool_t
02991 dbus_message_iter_close_container (DBusMessageIter *iter,
02992                                    DBusMessageIter *sub)
02993 {
02994   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02995   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02996   dbus_bool_t ret;
02997 
02998   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02999   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
03000   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
03001   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
03002 
03003   ret = _dbus_type_writer_unrecurse (&real->u.writer,
03004                                      &real_sub->u.writer);
03005 
03006   if (!_dbus_message_iter_close_signature (real))
03007     ret = FALSE;
03008 
03009   return ret;
03010 }
03011 
03023 void
03024 dbus_message_iter_abandon_container (DBusMessageIter *iter,
03025                                      DBusMessageIter *sub)
03026 {
03027   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03028 #ifndef DBUS_DISABLE_CHECKS
03029   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
03030 
03031   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
03032   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
03033   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
03034   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
03035 #endif
03036 
03037   _dbus_message_iter_abandon_signature (real);
03038 }
03039 
03056 void
03057 dbus_message_set_no_reply (DBusMessage *message,
03058                            dbus_bool_t  no_reply)
03059 {
03060   _dbus_return_if_fail (message != NULL);
03061   _dbus_return_if_fail (!message->locked);
03062 
03063   _dbus_header_toggle_flag (&message->header,
03064                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
03065                             no_reply);
03066 }
03067 
03075 dbus_bool_t
03076 dbus_message_get_no_reply (DBusMessage *message)
03077 {
03078   _dbus_return_val_if_fail (message != NULL, FALSE);
03079 
03080   return _dbus_header_get_flag (&message->header,
03081                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
03082 }
03083 
03098 void
03099 dbus_message_set_auto_start (DBusMessage *message,
03100                              dbus_bool_t  auto_start)
03101 {
03102   _dbus_return_if_fail (message != NULL);
03103   _dbus_return_if_fail (!message->locked);
03104 
03105   _dbus_header_toggle_flag (&message->header,
03106                             DBUS_HEADER_FLAG_NO_AUTO_START,
03107                             !auto_start);
03108 }
03109 
03117 dbus_bool_t
03118 dbus_message_get_auto_start (DBusMessage *message)
03119 {
03120   _dbus_return_val_if_fail (message != NULL, FALSE);
03121 
03122   return !_dbus_header_get_flag (&message->header,
03123                                  DBUS_HEADER_FLAG_NO_AUTO_START);
03124 }
03125 
03126 
03139 dbus_bool_t
03140 dbus_message_set_path (DBusMessage   *message,
03141                        const char    *object_path)
03142 {
03143   _dbus_return_val_if_fail (message != NULL, FALSE);
03144   _dbus_return_val_if_fail (!message->locked, FALSE);
03145   _dbus_return_val_if_fail (object_path == NULL ||
03146                             _dbus_check_is_valid_path (object_path),
03147                             FALSE);
03148 
03149   return set_or_delete_string_field (message,
03150                                      DBUS_HEADER_FIELD_PATH,
03151                                      DBUS_TYPE_OBJECT_PATH,
03152                                      object_path);
03153 }
03154 
03168 const char*
03169 dbus_message_get_path (DBusMessage   *message)
03170 {
03171   const char *v;
03172 
03173   _dbus_return_val_if_fail (message != NULL, NULL);
03174 
03175   v = NULL; /* in case field doesn't exist */
03176   _dbus_header_get_field_basic (&message->header,
03177                                 DBUS_HEADER_FIELD_PATH,
03178                                 DBUS_TYPE_OBJECT_PATH,
03179                                 (void *) &v);
03180   return v;
03181 }
03182 
03192 dbus_bool_t
03193 dbus_message_has_path (DBusMessage   *message,
03194                        const char    *path)
03195 {
03196   const char *msg_path;
03197   msg_path = dbus_message_get_path (message);
03198   
03199   if (msg_path == NULL)
03200     {
03201       if (path == NULL)
03202         return TRUE;
03203       else
03204         return FALSE;
03205     }
03206 
03207   if (path == NULL)
03208     return FALSE;
03209    
03210   if (strcmp (msg_path, path) == 0)
03211     return TRUE;
03212 
03213   return FALSE;
03214 }
03215 
03236 dbus_bool_t
03237 dbus_message_get_path_decomposed (DBusMessage   *message,
03238                                   char        ***path)
03239 {
03240   const char *v;
03241 
03242   _dbus_return_val_if_fail (message != NULL, FALSE);
03243   _dbus_return_val_if_fail (path != NULL, FALSE);
03244 
03245   *path = NULL;
03246 
03247   v = dbus_message_get_path (message);
03248   if (v != NULL)
03249     {
03250       if (!_dbus_decompose_path (v, strlen (v),
03251                                  path, NULL))
03252         return FALSE;
03253     }
03254   return TRUE;
03255 }
03256 
03270 dbus_bool_t
03271 dbus_message_set_interface (DBusMessage  *message,
03272                             const char   *iface)
03273 {
03274   _dbus_return_val_if_fail (message != NULL, FALSE);
03275   _dbus_return_val_if_fail (!message->locked, FALSE);
03276   _dbus_return_val_if_fail (iface == NULL ||
03277                             _dbus_check_is_valid_interface (iface),
03278                             FALSE);
03279 
03280   return set_or_delete_string_field (message,
03281                                      DBUS_HEADER_FIELD_INTERFACE,
03282                                      DBUS_TYPE_STRING,
03283                                      iface);
03284 }
03285 
03299 const char*
03300 dbus_message_get_interface (DBusMessage *message)
03301 {
03302   const char *v;
03303 
03304   _dbus_return_val_if_fail (message != NULL, NULL);
03305 
03306   v = NULL; /* in case field doesn't exist */
03307   _dbus_header_get_field_basic (&message->header,
03308                                 DBUS_HEADER_FIELD_INTERFACE,
03309                                 DBUS_TYPE_STRING,
03310                                 (void *) &v);
03311   return v;
03312 }
03313 
03321 dbus_bool_t
03322 dbus_message_has_interface (DBusMessage   *message,
03323                             const char    *iface)
03324 {
03325   const char *msg_interface;
03326   msg_interface = dbus_message_get_interface (message);
03327    
03328   if (msg_interface == NULL)
03329     {
03330       if (iface == NULL)
03331         return TRUE;
03332       else
03333         return FALSE;
03334     }
03335 
03336   if (iface == NULL)
03337     return FALSE;
03338      
03339   if (strcmp (msg_interface, iface) == 0)
03340     return TRUE;
03341 
03342   return FALSE;
03343 
03344 }
03345 
03358 dbus_bool_t
03359 dbus_message_set_member (DBusMessage  *message,
03360                          const char   *member)
03361 {
03362   _dbus_return_val_if_fail (message != NULL, FALSE);
03363   _dbus_return_val_if_fail (!message->locked, FALSE);
03364   _dbus_return_val_if_fail (member == NULL ||
03365                             _dbus_check_is_valid_member (member),
03366                             FALSE);
03367 
03368   return set_or_delete_string_field (message,
03369                                      DBUS_HEADER_FIELD_MEMBER,
03370                                      DBUS_TYPE_STRING,
03371                                      member);
03372 }
03373 
03385 const char*
03386 dbus_message_get_member (DBusMessage *message)
03387 {
03388   const char *v;
03389 
03390   _dbus_return_val_if_fail (message != NULL, NULL);
03391 
03392   v = NULL; /* in case field doesn't exist */
03393   _dbus_header_get_field_basic (&message->header,
03394                                 DBUS_HEADER_FIELD_MEMBER,
03395                                 DBUS_TYPE_STRING,
03396                                 (void *) &v);
03397   return v;
03398 }
03399 
03407 dbus_bool_t
03408 dbus_message_has_member (DBusMessage   *message,
03409                          const char    *member)
03410 {
03411   const char *msg_member;
03412   msg_member = dbus_message_get_member (message);
03413  
03414   if (msg_member == NULL)
03415     {
03416       if (member == NULL)
03417         return TRUE;
03418       else
03419         return FALSE;
03420     }
03421 
03422   if (member == NULL)
03423     return FALSE;
03424     
03425   if (strcmp (msg_member, member) == 0)
03426     return TRUE;
03427 
03428   return FALSE;
03429 
03430 }
03431 
03443 dbus_bool_t
03444 dbus_message_set_error_name (DBusMessage  *message,
03445                              const char   *error_name)
03446 {
03447   _dbus_return_val_if_fail (message != NULL, FALSE);
03448   _dbus_return_val_if_fail (!message->locked, FALSE);
03449   _dbus_return_val_if_fail (error_name == NULL ||
03450                             _dbus_check_is_valid_error_name (error_name),
03451                             FALSE);
03452 
03453   return set_or_delete_string_field (message,
03454                                      DBUS_HEADER_FIELD_ERROR_NAME,
03455                                      DBUS_TYPE_STRING,
03456                                      error_name);
03457 }
03458 
03469 const char*
03470 dbus_message_get_error_name (DBusMessage *message)
03471 {
03472   const char *v;
03473 
03474   _dbus_return_val_if_fail (message != NULL, NULL);
03475 
03476   v = NULL; /* in case field doesn't exist */
03477   _dbus_header_get_field_basic (&message->header,
03478                                 DBUS_HEADER_FIELD_ERROR_NAME,
03479                                 DBUS_TYPE_STRING,
03480                                 (void *) &v);
03481   return v;
03482 }
03483 
03497 dbus_bool_t
03498 dbus_message_set_destination (DBusMessage  *message,
03499                               const char   *destination)
03500 {
03501   _dbus_return_val_if_fail (message != NULL, FALSE);
03502   _dbus_return_val_if_fail (!message->locked, FALSE);
03503   _dbus_return_val_if_fail (destination == NULL ||
03504                             _dbus_check_is_valid_bus_name (destination),
03505                             FALSE);
03506 
03507   return set_or_delete_string_field (message,
03508                                      DBUS_HEADER_FIELD_DESTINATION,
03509                                      DBUS_TYPE_STRING,
03510                                      destination);
03511 }
03512 
03522 const char*
03523 dbus_message_get_destination (DBusMessage *message)
03524 {
03525   const char *v;
03526 
03527   _dbus_return_val_if_fail (message != NULL, NULL);
03528 
03529   v = NULL; /* in case field doesn't exist */
03530   _dbus_header_get_field_basic (&message->header,
03531                                 DBUS_HEADER_FIELD_DESTINATION,
03532                                 DBUS_TYPE_STRING,
03533                                 (void *) &v);
03534   return v;
03535 }
03536 
03551 dbus_bool_t
03552 dbus_message_set_sender (DBusMessage  *message,
03553                          const char   *sender)
03554 {
03555   _dbus_return_val_if_fail (message != NULL, FALSE);
03556   _dbus_return_val_if_fail (!message->locked, FALSE);
03557   _dbus_return_val_if_fail (sender == NULL ||
03558                             _dbus_check_is_valid_bus_name (sender),
03559                             FALSE);
03560 
03561   return set_or_delete_string_field (message,
03562                                      DBUS_HEADER_FIELD_SENDER,
03563                                      DBUS_TYPE_STRING,
03564                                      sender);
03565 }
03566 
03582 const char*
03583 dbus_message_get_sender (DBusMessage *message)
03584 {
03585   const char *v;
03586 
03587   _dbus_return_val_if_fail (message != NULL, NULL);
03588 
03589   v = NULL; /* in case field doesn't exist */
03590   _dbus_header_get_field_basic (&message->header,
03591                                 DBUS_HEADER_FIELD_SENDER,
03592                                 DBUS_TYPE_STRING,
03593                                 (void *) &v);
03594   return v;
03595 }
03596 
03615 const char*
03616 dbus_message_get_signature (DBusMessage *message)
03617 {
03618   const DBusString *type_str;
03619   int type_pos;
03620 
03621   _dbus_return_val_if_fail (message != NULL, NULL);
03622 
03623   get_const_signature (&message->header, &type_str, &type_pos);
03624 
03625   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03626 }
03627 
03628 static dbus_bool_t
03629 _dbus_message_has_type_interface_member (DBusMessage *message,
03630                                          int          type,
03631                                          const char  *iface,
03632                                          const char  *member)
03633 {
03634   const char *n;
03635 
03636   _dbus_assert (message != NULL);
03637   _dbus_assert (iface != NULL);
03638   _dbus_assert (member != NULL);
03639 
03640   if (dbus_message_get_type (message) != type)
03641     return FALSE;
03642 
03643   /* Optimize by checking the short member name first
03644    * instead of the longer interface name
03645    */
03646 
03647   n = dbus_message_get_member (message);
03648 
03649   if (n && strcmp (n, member) == 0)
03650     {
03651       n = dbus_message_get_interface (message);
03652 
03653       if (n == NULL || strcmp (n, iface) == 0)
03654         return TRUE;
03655     }
03656 
03657   return FALSE;
03658 }
03659 
03674 dbus_bool_t
03675 dbus_message_is_method_call (DBusMessage *message,
03676                              const char  *iface,
03677                              const char  *method)
03678 {
03679   _dbus_return_val_if_fail (message != NULL, FALSE);
03680   _dbus_return_val_if_fail (iface != NULL, FALSE);
03681   _dbus_return_val_if_fail (method != NULL, FALSE);
03682   /* don't check that interface/method are valid since it would be
03683    * expensive, and not catch many common errors
03684    */
03685 
03686   return _dbus_message_has_type_interface_member (message,
03687                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03688                                                   iface, method);
03689 }
03690 
03702 dbus_bool_t
03703 dbus_message_is_signal (DBusMessage *message,
03704                         const char  *iface,
03705                         const char  *signal_name)
03706 {
03707   _dbus_return_val_if_fail (message != NULL, FALSE);
03708   _dbus_return_val_if_fail (iface != NULL, FALSE);
03709   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03710   /* don't check that interface/name are valid since it would be
03711    * expensive, and not catch many common errors
03712    */
03713 
03714   return _dbus_message_has_type_interface_member (message,
03715                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03716                                                   iface, signal_name);
03717 }
03718 
03729 dbus_bool_t
03730 dbus_message_is_error (DBusMessage *message,
03731                        const char  *error_name)
03732 {
03733   const char *n;
03734 
03735   _dbus_return_val_if_fail (message != NULL, FALSE);
03736   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03737   /* don't check that error_name is valid since it would be expensive,
03738    * and not catch many common errors
03739    */
03740 
03741   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03742     return FALSE;
03743 
03744   n = dbus_message_get_error_name (message);
03745 
03746   if (n && strcmp (n, error_name) == 0)
03747     return TRUE;
03748   else
03749     return FALSE;
03750 }
03751 
03762 dbus_bool_t
03763 dbus_message_has_destination (DBusMessage  *message,
03764                               const char   *name)
03765 {
03766   const char *s;
03767 
03768   _dbus_return_val_if_fail (message != NULL, FALSE);
03769   _dbus_return_val_if_fail (name != NULL, FALSE);
03770   /* don't check that name is valid since it would be expensive, and
03771    * not catch many common errors
03772    */
03773 
03774   s = dbus_message_get_destination (message);
03775 
03776   if (s && strcmp (s, name) == 0)
03777     return TRUE;
03778   else
03779     return FALSE;
03780 }
03781 
03797 dbus_bool_t
03798 dbus_message_has_sender (DBusMessage  *message,
03799                          const char   *name)
03800 {
03801   const char *s;
03802 
03803   _dbus_return_val_if_fail (message != NULL, FALSE);
03804   _dbus_return_val_if_fail (name != NULL, FALSE);
03805   /* don't check that name is valid since it would be expensive, and
03806    * not catch many common errors
03807    */
03808 
03809   s = dbus_message_get_sender (message);
03810 
03811   if (s && strcmp (s, name) == 0)
03812     return TRUE;
03813   else
03814     return FALSE;
03815 }
03816 
03826 dbus_bool_t
03827 dbus_message_has_signature (DBusMessage   *message,
03828                             const char    *signature)
03829 {
03830   const char *s;
03831 
03832   _dbus_return_val_if_fail (message != NULL, FALSE);
03833   _dbus_return_val_if_fail (signature != NULL, FALSE);
03834   /* don't check that signature is valid since it would be expensive,
03835    * and not catch many common errors
03836    */
03837 
03838   s = dbus_message_get_signature (message);
03839 
03840   if (s && strcmp (s, signature) == 0)
03841     return TRUE;
03842   else
03843     return FALSE;
03844 }
03845 
03868 dbus_bool_t
03869 dbus_set_error_from_message (DBusError   *error,
03870                              DBusMessage *message)
03871 {
03872   const char *str;
03873 
03874   _dbus_return_val_if_fail (message != NULL, FALSE);
03875   _dbus_return_val_if_error_is_set (error, FALSE);
03876 
03877   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03878     return FALSE;
03879 
03880   str = NULL;
03881   dbus_message_get_args (message, NULL,
03882                          DBUS_TYPE_STRING, &str,
03883                          DBUS_TYPE_INVALID);
03884 
03885   dbus_set_error (error, dbus_message_get_error_name (message),
03886                   str ? "%s" : NULL, str);
03887 
03888   return TRUE;
03889 }
03890 
03897 dbus_bool_t
03898 dbus_message_contains_unix_fds(DBusMessage *message)
03899 {
03900 #ifdef HAVE_UNIX_FD_PASSING
03901   _dbus_assert(message);
03902 
03903   return message->n_unix_fds > 0;
03904 #else
03905   return FALSE;
03906 #endif
03907 }
03908 
03927 #define INITIAL_LOADER_DATA_LEN 32
03928 
03935 DBusMessageLoader*
03936 _dbus_message_loader_new (void)
03937 {
03938   DBusMessageLoader *loader;
03939 
03940   loader = dbus_new0 (DBusMessageLoader, 1);
03941   if (loader == NULL)
03942     return NULL;
03943   
03944   loader->refcount = 1;
03945 
03946   loader->corrupted = FALSE;
03947   loader->corruption_reason = DBUS_VALID;
03948 
03949   /* this can be configured by the app, but defaults to the protocol max */
03950   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03951 
03952   /* We set a very relatively conservative default here since due to how
03953   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03954   number of unix fds we want to receive in advance. A
03955   try-and-reallocate loop is not possible. */
03956   loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
03957 
03958   if (!_dbus_string_init (&loader->data))
03959     {
03960       dbus_free (loader);
03961       return NULL;
03962     }
03963 
03964   /* preallocate the buffer for speed, ignore failure */
03965   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03966   _dbus_string_set_length (&loader->data, 0);
03967 
03968 #ifdef HAVE_UNIX_FD_PASSING
03969   loader->unix_fds = NULL;
03970   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03971   loader->unix_fds_outstanding = FALSE;
03972 #endif
03973 
03974   return loader;
03975 }
03976 
03983 DBusMessageLoader *
03984 _dbus_message_loader_ref (DBusMessageLoader *loader)
03985 {
03986   loader->refcount += 1;
03987 
03988   return loader;
03989 }
03990 
03997 void
03998 _dbus_message_loader_unref (DBusMessageLoader *loader)
03999 {
04000   loader->refcount -= 1;
04001   if (loader->refcount == 0)
04002     {
04003 #ifdef HAVE_UNIX_FD_PASSING
04004       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
04005       dbus_free(loader->unix_fds);
04006 #endif
04007       _dbus_list_foreach (&loader->messages,
04008                           (DBusForeachFunction) dbus_message_unref,
04009                           NULL);
04010       _dbus_list_clear (&loader->messages);
04011       _dbus_string_free (&loader->data);
04012       dbus_free (loader);
04013     }
04014 }
04015 
04034 void
04035 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
04036                                  DBusString        **buffer)
04037 {
04038   _dbus_assert (!loader->buffer_outstanding);
04039 
04040   *buffer = &loader->data;
04041 
04042   loader->buffer_outstanding = TRUE;
04043 }
04044 
04054 void
04055 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
04056                                     DBusString         *buffer)
04057 {
04058   _dbus_assert (loader->buffer_outstanding);
04059   _dbus_assert (buffer == &loader->data);
04060 
04061   loader->buffer_outstanding = FALSE;
04062 }
04063 
04074 dbus_bool_t
04075 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
04076                                   int               **fds,
04077                                   unsigned           *max_n_fds)
04078 {
04079 #ifdef HAVE_UNIX_FD_PASSING
04080   _dbus_assert (!loader->unix_fds_outstanding);
04081 
04082   /* Allocate space where we can put the fds we read. We allocate
04083      space for max_message_unix_fds since this is an
04084      upper limit how many fds can be received within a single
04085      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
04086      we are allocating the maximum possible array size right from the
04087      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
04088      there is no better way. */
04089 
04090   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
04091     {
04092       int *a = dbus_realloc(loader->unix_fds,
04093                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
04094 
04095       if (!a)
04096         return FALSE;
04097 
04098       loader->unix_fds = a;
04099       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
04100     }
04101 
04102   *fds = loader->unix_fds + loader->n_unix_fds;
04103   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
04104 
04105   loader->unix_fds_outstanding = TRUE;
04106   return TRUE;
04107 #else
04108   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
04109   return FALSE;
04110 #endif
04111 }
04112 
04123 void
04124 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
04125                                      int                *fds,
04126                                      unsigned            n_fds)
04127 {
04128 #ifdef HAVE_UNIX_FD_PASSING
04129   _dbus_assert(loader->unix_fds_outstanding);
04130   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
04131   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
04132 
04133   loader->n_unix_fds += n_fds;
04134   loader->unix_fds_outstanding = FALSE;
04135 
04136   if (n_fds && loader->unix_fds_change)
04137     loader->unix_fds_change (loader->unix_fds_change_data);
04138 #else
04139   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
04140 #endif
04141 }
04142 
04143 /*
04144  * FIXME when we move the header out of the buffer, that memmoves all
04145  * buffered messages. Kind of crappy.
04146  *
04147  * Also we copy the header and body, which is kind of crappy.  To
04148  * avoid this, we have to allow header and body to be in a single
04149  * memory block, which is good for messages we read and bad for
04150  * messages we are creating. But we could move_len() the buffer into
04151  * this single memory block, and move_len() will just swap the buffers
04152  * if you're moving the entire buffer replacing the dest string.
04153  *
04154  * We could also have the message loader tell the transport how many
04155  * bytes to read; so it would first ask for some arbitrary number like
04156  * 256, then if the message was incomplete it would use the
04157  * header/body len to ask for exactly the size of the message (or
04158  * blocks the size of a typical kernel buffer for the socket). That
04159  * way we don't get trailing bytes in the buffer that have to be
04160  * memmoved. Though I suppose we also don't have a chance of reading a
04161  * bunch of small messages at once, so the optimization may be stupid.
04162  *
04163  * Another approach would be to keep a "start" index into
04164  * loader->data and only delete it occasionally, instead of after
04165  * each message is loaded.
04166  *
04167  * load_message() returns FALSE if not enough memory OR the loader was corrupted
04168  */
04169 static dbus_bool_t
04170 load_message (DBusMessageLoader *loader,
04171               DBusMessage       *message,
04172               int                byte_order,
04173               int                fields_array_len,
04174               int                header_len,
04175               int                body_len)
04176 {
04177   dbus_bool_t oom;
04178   DBusValidity validity;
04179   const DBusString *type_str;
04180   int type_pos;
04181   DBusValidationMode mode;
04182   dbus_uint32_t n_unix_fds = 0;
04183 
04184   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
04185   
04186   oom = FALSE;
04187 
04188 #if 0
04189   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
04190 #endif
04191 
04192   /* 1. VALIDATE AND COPY OVER HEADER */
04193   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
04194   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
04195 
04196   if (!_dbus_header_load (&message->header,
04197                           mode,
04198                           &validity,
04199                           byte_order,
04200                           fields_array_len,
04201                           header_len,
04202                           body_len,
04203                           &loader->data, 0,
04204                           _dbus_string_get_length (&loader->data)))
04205     {
04206       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
04207 
04208       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
04209          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
04210       _dbus_assert (validity != DBUS_VALID);
04211 
04212       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
04213         oom = TRUE;
04214       else
04215         {
04216           loader->corrupted = TRUE;
04217           loader->corruption_reason = validity;
04218         }
04219       goto failed;
04220     }
04221 
04222   _dbus_assert (validity == DBUS_VALID);
04223 
04224   /* 2. VALIDATE BODY */
04225   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04226     {
04227       get_const_signature (&message->header, &type_str, &type_pos);
04228       
04229       /* Because the bytes_remaining arg is NULL, this validates that the
04230        * body is the right length
04231        */
04232       validity = _dbus_validate_body_with_reason (type_str,
04233                                                   type_pos,
04234                                                   byte_order,
04235                                                   NULL,
04236                                                   &loader->data,
04237                                                   header_len,
04238                                                   body_len);
04239       if (validity != DBUS_VALID)
04240         {
04241           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04242 
04243           loader->corrupted = TRUE;
04244           loader->corruption_reason = validity;
04245           
04246           goto failed;
04247         }
04248     }
04249 
04250   /* 3. COPY OVER UNIX FDS */
04251   _dbus_header_get_field_basic(&message->header,
04252                                DBUS_HEADER_FIELD_UNIX_FDS,
04253                                DBUS_TYPE_UINT32,
04254                                &n_unix_fds);
04255 
04256 #ifdef HAVE_UNIX_FD_PASSING
04257 
04258   if (n_unix_fds > loader->n_unix_fds)
04259     {
04260       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04261                     n_unix_fds, loader->n_unix_fds);
04262 
04263       loader->corrupted = TRUE;
04264       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04265       goto failed;
04266     }
04267 
04268   /* If this was a recycled message there might still be
04269      some memory allocated for the fds */
04270   dbus_free(message->unix_fds);
04271 
04272   if (n_unix_fds > 0)
04273     {
04274       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04275       if (message->unix_fds == NULL)
04276         {
04277           _dbus_verbose ("Failed to allocate file descriptor array\n");
04278           oom = TRUE;
04279           goto failed;
04280         }
04281 
04282       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04283       loader->n_unix_fds -= n_unix_fds;
04284       memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
04285 
04286       if (loader->unix_fds_change)
04287         loader->unix_fds_change (loader->unix_fds_change_data);
04288     }
04289   else
04290     message->unix_fds = NULL;
04291 
04292 #else
04293 
04294   if (n_unix_fds > 0)
04295     {
04296       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04297                      "but that's not supported on our platform, disconnecting.\n");
04298 
04299       loader->corrupted = TRUE;
04300       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04301       goto failed;
04302     }
04303 
04304 #endif
04305 
04306   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04307 
04308   if (!_dbus_list_append (&loader->messages, message))
04309     {
04310       _dbus_verbose ("Failed to append new message to loader queue\n");
04311       oom = TRUE;
04312       goto failed;
04313     }
04314 
04315   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04316   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04317                 (header_len + body_len));
04318 
04319   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04320     {
04321       _dbus_verbose ("Failed to move body into new message\n");
04322       oom = TRUE;
04323       goto failed;
04324     }
04325 
04326   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04327 
04328   /* don't waste more than 2k of memory */
04329   _dbus_string_compact (&loader->data, 2048);
04330 
04331   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04332   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04333 
04334   _dbus_verbose ("Loaded message %p\n", message);
04335 
04336   _dbus_assert (!oom);
04337   _dbus_assert (!loader->corrupted);
04338   _dbus_assert (loader->messages != NULL);
04339   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04340 
04341   return TRUE;
04342 
04343  failed:
04344 
04345   /* Clean up */
04346 
04347   /* does nothing if the message isn't in the list */
04348   _dbus_list_remove_last (&loader->messages, message);
04349   
04350   if (oom)
04351     _dbus_assert (!loader->corrupted);
04352   else
04353     _dbus_assert (loader->corrupted);
04354 
04355   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04356 
04357   return FALSE;
04358 }
04359 
04374 dbus_bool_t
04375 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04376 {
04377   while (!loader->corrupted &&
04378          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04379     {
04380       DBusValidity validity;
04381       int byte_order, fields_array_len, header_len, body_len;
04382 
04383       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04384                                                &validity,
04385                                                &byte_order,
04386                                                &fields_array_len,
04387                                                &header_len,
04388                                                &body_len,
04389                                                &loader->data, 0,
04390                                                _dbus_string_get_length (&loader->data)))
04391         {
04392           DBusMessage *message;
04393 
04394           _dbus_assert (validity == DBUS_VALID);
04395 
04396           message = dbus_message_new_empty_header ();
04397           if (message == NULL)
04398             return FALSE;
04399 
04400           if (!load_message (loader, message,
04401                              byte_order, fields_array_len,
04402                              header_len, body_len))
04403             {
04404               dbus_message_unref (message);
04405               /* load_message() returns false if corrupted or OOM; if
04406                * corrupted then return TRUE for not OOM
04407                */
04408               return loader->corrupted;
04409             }
04410 
04411           _dbus_assert (loader->messages != NULL);
04412           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04413         }
04414       else
04415         {
04416           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04417                          validity);
04418           if (validity != DBUS_VALID)
04419             {
04420               loader->corrupted = TRUE;
04421               loader->corruption_reason = validity;
04422             }
04423           return TRUE;
04424         }
04425     }
04426 
04427   return TRUE;
04428 }
04429 
04437 DBusMessage*
04438 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04439 {
04440   if (loader->messages)
04441     return loader->messages->data;
04442   else
04443     return NULL;
04444 }
04445 
04454 DBusMessage*
04455 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04456 {
04457   return _dbus_list_pop_first (&loader->messages);
04458 }
04459 
04468 DBusList*
04469 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04470 {
04471   return _dbus_list_pop_first_link (&loader->messages);
04472 }
04473 
04480 void
04481 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04482                                            DBusList           *link)
04483 {
04484   _dbus_list_prepend_link (&loader->messages, link);
04485 }
04486 
04496 dbus_bool_t
04497 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04498 {
04499   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04500                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04501   return loader->corrupted;
04502 }
04503 
04510 DBusValidity
04511 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04512 {
04513   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04514                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04515 
04516   return loader->corruption_reason;
04517 }
04518 
04525 void
04526 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04527                                            long                size)
04528 {
04529   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04530     {
04531       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04532                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04533       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04534     }
04535   loader->max_message_size = size;
04536 }
04537 
04544 long
04545 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04546 {
04547   return loader->max_message_size;
04548 }
04549 
04556 void
04557 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04558                                                long                n)
04559 {
04560   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04561     {
04562       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04563                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04564       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04565     }
04566   loader->max_message_unix_fds = n;
04567 }
04568 
04575 long
04576 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04577 {
04578   return loader->max_message_unix_fds;
04579 }
04580 
04586 int
04587 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
04588 {
04589 #ifdef HAVE_UNIX_FD_PASSING
04590   return loader->n_unix_fds;
04591 #else
04592   return 0;
04593 #endif
04594 }
04595 
04604 void
04605 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
04606                                                void (* callback) (void *),
04607                                                void *data)
04608 {
04609 #ifdef HAVE_UNIX_FD_PASSING
04610   loader->unix_fds_change = callback;
04611   loader->unix_fds_change_data = data;
04612 #endif
04613 }
04614 
04615 static DBusDataSlotAllocator slot_allocator =
04616   _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
04617 
04632 dbus_bool_t
04633 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04634 {
04635   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04636                                           slot_p);
04637 }
04638 
04650 void
04651 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04652 {
04653   _dbus_return_if_fail (*slot_p >= 0);
04654 
04655   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04656 }
04657 
04671 dbus_bool_t
04672 dbus_message_set_data (DBusMessage     *message,
04673                        dbus_int32_t     slot,
04674                        void            *data,
04675                        DBusFreeFunction free_data_func)
04676 {
04677   DBusFreeFunction old_free_func;
04678   void *old_data;
04679   dbus_bool_t retval;
04680 
04681   _dbus_return_val_if_fail (message != NULL, FALSE);
04682   _dbus_return_val_if_fail (slot >= 0, FALSE);
04683 
04684   retval = _dbus_data_slot_list_set (&slot_allocator,
04685                                      &message->slot_list,
04686                                      slot, data, free_data_func,
04687                                      &old_free_func, &old_data);
04688 
04689   if (retval)
04690     {
04691       /* Do the actual free outside the message lock */
04692       if (old_free_func)
04693         (* old_free_func) (old_data);
04694     }
04695 
04696   return retval;
04697 }
04698 
04707 void*
04708 dbus_message_get_data (DBusMessage   *message,
04709                        dbus_int32_t   slot)
04710 {
04711   void *res;
04712 
04713   _dbus_return_val_if_fail (message != NULL, NULL);
04714 
04715   res = _dbus_data_slot_list_get (&slot_allocator,
04716                                   &message->slot_list,
04717                                   slot);
04718 
04719   return res;
04720 }
04721 
04735 int
04736 dbus_message_type_from_string (const char *type_str)
04737 {
04738   if (strcmp (type_str, "method_call") == 0)
04739     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04740   if (strcmp (type_str, "method_return") == 0)
04741     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04742   else if (strcmp (type_str, "signal") == 0)
04743     return DBUS_MESSAGE_TYPE_SIGNAL;
04744   else if (strcmp (type_str, "error") == 0)
04745     return DBUS_MESSAGE_TYPE_ERROR;
04746   else
04747     return DBUS_MESSAGE_TYPE_INVALID;
04748 }
04749 
04763 const char *
04764 dbus_message_type_to_string (int type)
04765 {
04766   switch (type)
04767     {
04768     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04769       return "method_call";
04770     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04771       return "method_return";
04772     case DBUS_MESSAGE_TYPE_SIGNAL:
04773       return "signal";
04774     case DBUS_MESSAGE_TYPE_ERROR:
04775       return "error";
04776     default:
04777       return "invalid";
04778     }
04779 }
04780 
04793 dbus_bool_t
04794 dbus_message_marshal (DBusMessage  *msg,
04795                       char        **marshalled_data_p,
04796                       int          *len_p)
04797 {
04798   DBusString tmp;
04799   dbus_bool_t was_locked;
04800 
04801   _dbus_return_val_if_fail (msg != NULL, FALSE);
04802   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04803   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04804   
04805   if (!_dbus_string_init (&tmp))
04806     return FALSE;
04807 
04808   /* Ensure the message is locked, to ensure the length header is filled in. */
04809   was_locked = msg->locked;
04810 
04811   if (!was_locked)
04812     dbus_message_lock (msg);
04813 
04814   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04815     goto fail;
04816 
04817   *len_p = _dbus_string_get_length (&tmp);
04818 
04819   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04820     goto fail;
04821 
04822   *len_p = _dbus_string_get_length (&tmp);
04823 
04824   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04825     goto fail;
04826 
04827   _dbus_string_free (&tmp);
04828 
04829   if (!was_locked)
04830     msg->locked = FALSE;
04831 
04832   return TRUE;
04833 
04834  fail:
04835   _dbus_string_free (&tmp);
04836 
04837   if (!was_locked)
04838     msg->locked = FALSE;
04839 
04840   return FALSE;
04841 }
04842 
04855 DBusMessage *
04856 dbus_message_demarshal (const char *str,
04857                         int         len,
04858                         DBusError  *error)
04859 {
04860   DBusMessageLoader *loader;
04861   DBusString *buffer;
04862   DBusMessage *msg;
04863 
04864   _dbus_return_val_if_fail (str != NULL, NULL);
04865 
04866   loader = _dbus_message_loader_new ();
04867 
04868   if (loader == NULL)
04869     return NULL;
04870 
04871   _dbus_message_loader_get_buffer (loader, &buffer);
04872 
04873   if (!_dbus_string_append_len (buffer, str, len))
04874     goto fail_oom;
04875 
04876   _dbus_message_loader_return_buffer (loader, buffer);
04877 
04878   if (!_dbus_message_loader_queue_messages (loader))
04879     goto fail_oom;
04880 
04881   if (_dbus_message_loader_get_is_corrupted (loader))
04882     goto fail_corrupt;
04883 
04884   msg = _dbus_message_loader_pop_message (loader);
04885 
04886   if (!msg)
04887     goto fail_oom;
04888 
04889   _dbus_message_loader_unref (loader);
04890   return msg;
04891 
04892  fail_corrupt:
04893   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04894                   _dbus_validity_to_error_message (loader->corruption_reason));
04895   _dbus_message_loader_unref (loader);
04896   return NULL;
04897 
04898  fail_oom:
04899   _DBUS_SET_OOM (error);
04900   _dbus_message_loader_unref (loader);
04901   return NULL;
04902 }
04903 
04916 int 
04917 dbus_message_demarshal_bytes_needed(const char *buf, 
04918                                     int         len)
04919 {
04920   DBusString str;
04921   int byte_order, fields_array_len, header_len, body_len;
04922   DBusValidity validity = DBUS_VALID;
04923   int have_message;
04924 
04925   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04926     return 0;
04927 
04928   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04929     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04930   _dbus_string_init_const_len (&str, buf, len);
04931   
04932   validity = DBUS_VALID;
04933   have_message
04934     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04935                                           &validity, &byte_order,
04936                                           &fields_array_len,
04937                                           &header_len,
04938                                           &body_len,
04939                                           &str, 0,
04940                                           len);
04941   _dbus_string_free (&str);
04942 
04943   if (validity == DBUS_VALID)
04944     {
04945       _dbus_assert (have_message || (header_len + body_len) > len);
04946       (void) have_message; /* unused unless asserting */
04947       return header_len + body_len;
04948     }
04949   else
04950     {
04951       return -1; /* broken! */
04952     }
04953 }
04954 
04976 void
04977 dbus_message_set_allow_interactive_authorization (DBusMessage *message,
04978                                                   dbus_bool_t  allow)
04979 {
04980   _dbus_return_if_fail (message != NULL);
04981   _dbus_return_if_fail (!message->locked);
04982 
04983   _dbus_header_toggle_flag (&message->header,
04984                             DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION,
04985                             allow);
04986 }
04987 
04994 dbus_bool_t
04995 dbus_message_get_allow_interactive_authorization (DBusMessage *message)
04996 {
04997   _dbus_return_val_if_fail (message != NULL, FALSE);
04998 
04999   return _dbus_header_get_flag (&message->header,
05000                                 DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION);
05001 }
05002 
05005 /* tests in dbus-message-util.c */

Generated on 13 Sep 2016 for D-Bus by  doxygen 1.4.7