D-Bus  1.8.20
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 
00139 static void
00140 get_const_signature (DBusHeader        *header,
00141                      const DBusString **type_str_p,
00142                      int               *type_pos_p)
00143 {
00144   if (_dbus_header_get_field_raw (header,
00145                                   DBUS_HEADER_FIELD_SIGNATURE,
00146                                   type_str_p,
00147                                   type_pos_p))
00148     {
00149       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00150     }
00151   else
00152     {
00153       *type_str_p = &_dbus_empty_signature_str;
00154       *type_pos_p = 0;
00155     }
00156 }
00157 
00163 static void
00164 _dbus_message_byteswap (DBusMessage *message)
00165 {
00166   const DBusString *type_str;
00167   int type_pos;
00168   char byte_order;
00169 
00170   byte_order = _dbus_header_get_byte_order (&message->header);
00171 
00172   if (byte_order == DBUS_COMPILER_BYTE_ORDER)
00173     return;
00174 
00175   _dbus_verbose ("Swapping message into compiler byte order\n");
00176   
00177   get_const_signature (&message->header, &type_str, &type_pos);
00178   
00179   _dbus_marshal_byteswap (type_str, type_pos,
00180                           byte_order,
00181                           DBUS_COMPILER_BYTE_ORDER,
00182                           &message->body, 0);
00183 
00184   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00185   _dbus_assert (_dbus_header_get_byte_order (&message->header) ==
00186                 DBUS_COMPILER_BYTE_ORDER);
00187 }
00188 
00195 #define ensure_byte_order(message) _dbus_message_byteswap (message)
00196 
00207 void
00208 _dbus_message_get_network_data (DBusMessage          *message,
00209                                 const DBusString    **header,
00210                                 const DBusString    **body)
00211 {
00212   _dbus_assert (message->locked);
00213 
00214   *header = &message->header.data;
00215   *body = &message->body;
00216 }
00217 
00227 void _dbus_message_get_unix_fds(DBusMessage *message,
00228                                 const int  **fds,
00229                                 unsigned    *n_fds)
00230 {
00231   _dbus_assert (message->locked);
00232 
00233 #ifdef HAVE_UNIX_FD_PASSING
00234   *fds = message->unix_fds;
00235   *n_fds = message->n_unix_fds;
00236 #else
00237   *fds = NULL;
00238   *n_fds = 0;
00239 #endif
00240 }
00241 
00253 void 
00254 dbus_message_set_serial (DBusMessage   *message,
00255                          dbus_uint32_t  serial)
00256 {
00257   _dbus_return_if_fail (message != NULL);
00258   _dbus_return_if_fail (!message->locked);
00259 
00260   _dbus_header_set_serial (&message->header, serial);
00261 }
00262 
00279 void
00280 _dbus_message_add_counter_link (DBusMessage  *message,
00281                                 DBusList     *link)
00282 {
00283   /* right now we don't recompute the delta when message
00284    * size changes, and that's OK for current purposes
00285    * I think, but could be important to change later.
00286    * Do recompute it whenever there are no outstanding counters,
00287    * since it's basically free.
00288    */
00289   if (message->counters == NULL)
00290     {
00291       message->size_counter_delta =
00292         _dbus_string_get_length (&message->header.data) +
00293         _dbus_string_get_length (&message->body);
00294 
00295 #ifdef HAVE_UNIX_FD_PASSING
00296       message->unix_fd_counter_delta = message->n_unix_fds;
00297 #endif
00298 
00299 #if 0
00300       _dbus_verbose ("message has size %ld\n",
00301                      message->size_counter_delta);
00302 #endif
00303     }
00304 
00305   _dbus_list_append_link (&message->counters, link);
00306 
00307   _dbus_counter_adjust_size (link->data, message->size_counter_delta);
00308 
00309 #ifdef HAVE_UNIX_FD_PASSING
00310   _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
00311 #endif
00312 }
00313 
00328 dbus_bool_t
00329 _dbus_message_add_counter (DBusMessage *message,
00330                            DBusCounter *counter)
00331 {
00332   DBusList *link;
00333 
00334   link = _dbus_list_alloc_link (counter);
00335   if (link == NULL)
00336     return FALSE;
00337 
00338   _dbus_counter_ref (counter);
00339   _dbus_message_add_counter_link (message, link);
00340 
00341   return TRUE;
00342 }
00343 
00351 void
00352 _dbus_message_remove_counter (DBusMessage  *message,
00353                               DBusCounter  *counter)
00354 {
00355   DBusList *link;
00356 
00357   link = _dbus_list_find_last (&message->counters,
00358                                counter);
00359   _dbus_assert (link != NULL);
00360 
00361   _dbus_list_remove_link (&message->counters, link);
00362 
00363   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00364 
00365 #ifdef HAVE_UNIX_FD_PASSING
00366   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00367 #endif
00368 
00369   _dbus_counter_notify (counter);
00370   _dbus_counter_unref (counter);
00371 }
00372 
00383 void
00384 dbus_message_lock (DBusMessage  *message)
00385 {
00386   if (!message->locked)
00387     {
00388       _dbus_header_update_lengths (&message->header,
00389                                    _dbus_string_get_length (&message->body));
00390 
00391       /* must have a signature if you have a body */
00392       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00393                     dbus_message_get_signature (message) != NULL);
00394 
00395       message->locked = TRUE;
00396     }
00397 }
00398 
00399 static dbus_bool_t
00400 set_or_delete_string_field (DBusMessage *message,
00401                             int          field,
00402                             int          typecode,
00403                             const char  *value)
00404 {
00405   if (value == NULL)
00406     return _dbus_header_delete_field (&message->header, field);
00407   else
00408     return _dbus_header_set_field_basic (&message->header,
00409                                          field,
00410                                          typecode,
00411                                          &value);
00412 }
00413 
00414 #if 0
00415 /* Probably we don't need to use this */
00439 static dbus_bool_t
00440 _dbus_message_set_signature (DBusMessage *message,
00441                              const char  *signature)
00442 {
00443   _dbus_return_val_if_fail (message != NULL, FALSE);
00444   _dbus_return_val_if_fail (!message->locked, FALSE);
00445   _dbus_return_val_if_fail (signature == NULL ||
00446                             _dbus_check_is_valid_signature (signature));
00447   /* can't delete the signature if you have a message body */
00448   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00449                             signature != NULL);
00450 
00451   return set_or_delete_string_field (message,
00452                                      DBUS_HEADER_FIELD_SIGNATURE,
00453                                      DBUS_TYPE_SIGNATURE,
00454                                      signature);
00455 }
00456 #endif
00457 
00458 /* Message Cache
00459  *
00460  * We cache some DBusMessage to reduce the overhead of allocating
00461  * them.  In my profiling this consistently made about an 8%
00462  * difference.  It avoids the malloc for the message, the malloc for
00463  * the slot list, the malloc for the header string and body string,
00464  * and the associated free() calls. It does introduce another global
00465  * lock which could be a performance issue in certain cases.
00466  *
00467  * For the echo client/server the round trip time goes from around
00468  * .000077 to .000069 with the message cache on my laptop. The sysprof
00469  * change is as follows (numbers are cumulative percentage):
00470  *
00471  *  with message cache implemented as array as it is now (0.000069 per):
00472  *    new_empty_header           1.46
00473  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00474  *      mutex_unlock             0.25
00475  *      self                     0.41
00476  *    unref                      2.24
00477  *      self                     0.68
00478  *      list_clear               0.43
00479  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00480  *      mutex_unlock             0.25
00481  *
00482  *  with message cache implemented as list (0.000070 per roundtrip):
00483  *    new_empty_header           2.72
00484  *      list_pop_first           1.88
00485  *    unref                      3.3
00486  *      list_prepend             1.63
00487  *
00488  * without cache (0.000077 per roundtrip):
00489  *    new_empty_header           6.7
00490  *      string_init_preallocated 3.43
00491  *        dbus_malloc            2.43
00492  *      dbus_malloc0             2.59
00493  *
00494  *    unref                      4.02
00495  *      string_free              1.82
00496  *        dbus_free              1.63
00497  *      dbus_free                0.71
00498  *
00499  * If you implement the message_cache with a list, the primary reason
00500  * it's slower is that you add another thread lock (on the DBusList
00501  * mempool).
00502  */
00503 
00505 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00506 
00508 #define MAX_MESSAGE_CACHE_SIZE    5
00509 
00510 /* Protected by _DBUS_LOCK (message_cache) */
00511 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00512 static int message_cache_count = 0;
00513 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00514 
00515 static void
00516 dbus_message_cache_shutdown (void *data)
00517 {
00518   int i;
00519 
00520   if (!_DBUS_LOCK (message_cache))
00521     _dbus_assert_not_reached ("we would have initialized global locks "
00522         "before registering a shutdown function");
00523 
00524   i = 0;
00525   while (i < MAX_MESSAGE_CACHE_SIZE)
00526     {
00527       if (message_cache[i])
00528         dbus_message_finalize (message_cache[i]);
00529 
00530       ++i;
00531     }
00532 
00533   message_cache_count = 0;
00534   message_cache_shutdown_registered = FALSE;
00535 
00536   _DBUS_UNLOCK (message_cache);
00537 }
00538 
00546 static DBusMessage*
00547 dbus_message_get_cached (void)
00548 {
00549   DBusMessage *message;
00550   int i;
00551 
00552   message = NULL;
00553 
00554   if (!_DBUS_LOCK (message_cache))
00555     {
00556       /* we'd have initialized global locks before caching anything,
00557        * so there can't be anything in the cache */
00558       return NULL;
00559     }
00560 
00561   _dbus_assert (message_cache_count >= 0);
00562 
00563   if (message_cache_count == 0)
00564     {
00565       _DBUS_UNLOCK (message_cache);
00566       return NULL;
00567     }
00568 
00569   /* This is not necessarily true unless count > 0, and
00570    * message_cache is uninitialized until the shutdown is
00571    * registered
00572    */
00573   _dbus_assert (message_cache_shutdown_registered);
00574 
00575   i = 0;
00576   while (i < MAX_MESSAGE_CACHE_SIZE)
00577     {
00578       if (message_cache[i])
00579         {
00580           message = message_cache[i];
00581           message_cache[i] = NULL;
00582           message_cache_count -= 1;
00583           break;
00584         }
00585       ++i;
00586     }
00587   _dbus_assert (message_cache_count >= 0);
00588   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00589   _dbus_assert (message != NULL);
00590 
00591   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00592 
00593   _dbus_assert (message->counters == NULL);
00594   
00595   _DBUS_UNLOCK (message_cache);
00596 
00597   return message;
00598 }
00599 
00600 #ifdef HAVE_UNIX_FD_PASSING
00601 static void
00602 close_unix_fds(int *fds, unsigned *n_fds)
00603 {
00604   DBusError e;
00605   int i;
00606 
00607   if (*n_fds <= 0)
00608     return;
00609 
00610   dbus_error_init(&e);
00611 
00612   for (i = 0; i < *n_fds; i++)
00613     {
00614       if (!_dbus_close(fds[i], &e))
00615         {
00616           _dbus_warn("Failed to close file descriptor: %s\n", e.message);
00617           dbus_error_free(&e);
00618         }
00619     }
00620 
00621   *n_fds = 0;
00622 
00623   /* We don't free the array here, in case we can recycle it later */
00624 }
00625 #endif
00626 
00627 static void
00628 free_counter (void *element,
00629               void *data)
00630 {
00631   DBusCounter *counter = element;
00632   DBusMessage *message = data;
00633 
00634   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00635 #ifdef HAVE_UNIX_FD_PASSING
00636   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00637 #endif
00638 
00639   _dbus_counter_notify (counter);
00640   _dbus_counter_unref (counter);
00641 }
00642 
00648 static void
00649 dbus_message_cache_or_finalize (DBusMessage *message)
00650 {
00651   dbus_bool_t was_cached;
00652   int i;
00653 
00654   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00655 
00656   /* This calls application code and has to be done first thing
00657    * without holding the lock
00658    */
00659   _dbus_data_slot_list_clear (&message->slot_list);
00660 
00661   _dbus_list_foreach (&message->counters,
00662                       free_counter, message);
00663   _dbus_list_clear (&message->counters);
00664 
00665 #ifdef HAVE_UNIX_FD_PASSING
00666   close_unix_fds(message->unix_fds, &message->n_unix_fds);
00667 #endif
00668 
00669   was_cached = FALSE;
00670 
00671   if (!_DBUS_LOCK (message_cache))
00672     {
00673       /* The only way to get a non-null message goes through
00674        * dbus_message_get_cached() which takes the lock. */
00675       _dbus_assert_not_reached ("we would have initialized global locks "
00676           "the first time we constructed a message");
00677     }
00678 
00679   if (!message_cache_shutdown_registered)
00680     {
00681       _dbus_assert (message_cache_count == 0);
00682 
00683       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00684         goto out;
00685 
00686       i = 0;
00687       while (i < MAX_MESSAGE_CACHE_SIZE)
00688         {
00689           message_cache[i] = NULL;
00690           ++i;
00691         }
00692 
00693       message_cache_shutdown_registered = TRUE;
00694     }
00695 
00696   _dbus_assert (message_cache_count >= 0);
00697 
00698   if (!_dbus_enable_message_cache ())
00699     goto out;
00700 
00701   if ((_dbus_string_get_length (&message->header.data) +
00702        _dbus_string_get_length (&message->body)) >
00703       MAX_MESSAGE_SIZE_TO_CACHE)
00704     goto out;
00705 
00706   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00707     goto out;
00708 
00709   /* Find empty slot */
00710   i = 0;
00711   while (message_cache[i] != NULL)
00712     ++i;
00713 
00714   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00715 
00716   _dbus_assert (message_cache[i] == NULL);
00717   message_cache[i] = message;
00718   message_cache_count += 1;
00719   was_cached = TRUE;
00720 #ifndef DBUS_DISABLE_CHECKS
00721   message->in_cache = TRUE;
00722 #endif
00723 
00724  out:
00725   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00726 
00727   _DBUS_UNLOCK (message_cache);
00728   
00729   if (!was_cached)
00730     dbus_message_finalize (message);
00731 }
00732 
00733 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
00734 static dbus_bool_t
00735 _dbus_message_iter_check (DBusMessageRealIter *iter)
00736 {
00737   char byte_order;
00738 
00739   if (iter == NULL)
00740     {
00741       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00742       return FALSE;
00743     }
00744 
00745   byte_order = _dbus_header_get_byte_order (&iter->message->header);
00746 
00747   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00748     {
00749       if (iter->u.reader.byte_order != byte_order)
00750         {
00751           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00752           return FALSE;
00753         }
00754       /* because we swap the message into compiler order when you init an iter */
00755       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00756     }
00757   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00758     {
00759       if (iter->u.writer.byte_order != byte_order)
00760         {
00761           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00762           return FALSE;
00763         }
00764       /* because we swap the message into compiler order when you init an iter */
00765       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00766     }
00767   else
00768     {
00769       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00770       return FALSE;
00771     }
00772 
00773   if (iter->changed_stamp != iter->message->changed_stamp)
00774     {
00775       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00776       return FALSE;
00777     }
00778 
00779   return TRUE;
00780 }
00781 #endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
00782 
00795 dbus_bool_t
00796 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00797                                     DBusError       *error,
00798                                     int              first_arg_type,
00799                                     va_list          var_args)
00800 {
00801   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00802   int spec_type, msg_type, i, j;
00803   dbus_bool_t retval;
00804   va_list copy_args;
00805 
00806   _dbus_assert (_dbus_message_iter_check (real));
00807 
00808   retval = FALSE;
00809 
00810   spec_type = first_arg_type;
00811   i = 0;
00812 
00813   /* copy var_args first, then we can do another iteration over it to
00814    * free memory and close unix fds if parse failed at some point.
00815    */
00816   DBUS_VA_COPY (copy_args, var_args);
00817 
00818   while (spec_type != DBUS_TYPE_INVALID)
00819     {
00820       msg_type = dbus_message_iter_get_arg_type (iter);
00821 
00822       if (msg_type != spec_type)
00823         {
00824           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00825                           "Argument %d is specified to be of type \"%s\", but "
00826                           "is actually of type \"%s\"\n", i,
00827                           _dbus_type_to_string (spec_type),
00828                           _dbus_type_to_string (msg_type));
00829 
00830           goto out;
00831         }
00832 
00833       if (spec_type == DBUS_TYPE_UNIX_FD)
00834         {
00835 #ifdef HAVE_UNIX_FD_PASSING
00836           DBusBasicValue idx;
00837           int *pfd, nfd;
00838 
00839           pfd = va_arg (var_args, int*);
00840           _dbus_assert(pfd);
00841 
00842           _dbus_type_reader_read_basic(&real->u.reader, &idx);
00843 
00844           if (idx.u32 >= real->message->n_unix_fds)
00845             {
00846               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
00847                               "Message refers to file descriptor at index %i,"
00848                               "but has only %i descriptors attached.\n",
00849                               idx.u32,
00850                               real->message->n_unix_fds);
00851               goto out;
00852             }
00853 
00854           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
00855             goto out;
00856 
00857           *pfd = nfd;
00858 #else
00859           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00860                           "Platform does not support file desciptor passing.\n");
00861           goto out;
00862 #endif
00863         }
00864       else if (dbus_type_is_basic (spec_type))
00865         {
00866           DBusBasicValue *ptr;
00867 
00868           ptr = va_arg (var_args, DBusBasicValue*);
00869 
00870           _dbus_assert (ptr != NULL);
00871 
00872           _dbus_type_reader_read_basic (&real->u.reader,
00873                                         ptr);
00874         }
00875       else if (spec_type == DBUS_TYPE_ARRAY)
00876         {
00877           int element_type;
00878           int spec_element_type;
00879           const DBusBasicValue **ptr;
00880           int *n_elements_p;
00881           DBusTypeReader array;
00882 
00883           spec_element_type = va_arg (var_args, int);
00884           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00885 
00886           if (spec_element_type != element_type)
00887             {
00888               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00889                               "Argument %d is specified to be an array of \"%s\", but "
00890                               "is actually an array of \"%s\"\n",
00891                               i,
00892                               _dbus_type_to_string (spec_element_type),
00893                               _dbus_type_to_string (element_type));
00894 
00895               goto out;
00896             }
00897 
00898           if (dbus_type_is_fixed (spec_element_type) &&
00899               element_type != DBUS_TYPE_UNIX_FD)
00900             {
00901               ptr = va_arg (var_args, const DBusBasicValue**);
00902               n_elements_p = va_arg (var_args, int*);
00903 
00904               _dbus_assert (ptr != NULL);
00905               _dbus_assert (n_elements_p != NULL);
00906 
00907               _dbus_type_reader_recurse (&real->u.reader, &array);
00908 
00909               _dbus_type_reader_read_fixed_multi (&array,
00910                                                   (void *) ptr, n_elements_p);
00911             }
00912           else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
00913             {
00914               char ***str_array_p;
00915               int n_elements;
00916               char **str_array;
00917 
00918               str_array_p = va_arg (var_args, char***);
00919               n_elements_p = va_arg (var_args, int*);
00920 
00921               _dbus_assert (str_array_p != NULL);
00922               _dbus_assert (n_elements_p != NULL);
00923 
00924               /* Count elements in the array */
00925               _dbus_type_reader_recurse (&real->u.reader, &array);
00926 
00927               n_elements = 0;
00928               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00929                 {
00930                   ++n_elements;
00931                   _dbus_type_reader_next (&array);
00932                 }
00933 
00934               str_array = dbus_new0 (char*, n_elements + 1);
00935               if (str_array == NULL)
00936                 {
00937                   _DBUS_SET_OOM (error);
00938                   goto out;
00939                 }
00940 
00941               /* Now go through and dup each string */
00942               _dbus_type_reader_recurse (&real->u.reader, &array);
00943 
00944               j = 0;
00945               while (j < n_elements)
00946                 {
00947                   const char *s;
00948                   _dbus_type_reader_read_basic (&array,
00949                                                 (void *) &s);
00950                   
00951                   str_array[j] = _dbus_strdup (s);
00952                   if (str_array[j] == NULL)
00953                     {
00954                       dbus_free_string_array (str_array);
00955                       _DBUS_SET_OOM (error);
00956                       goto out;
00957                     }
00958                   
00959                   ++j;
00960                   
00961                   if (!_dbus_type_reader_next (&array))
00962                     _dbus_assert (j == n_elements);
00963                 }
00964 
00965               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00966               _dbus_assert (j == n_elements);
00967               _dbus_assert (str_array[j] == NULL);
00968 
00969               *str_array_p = str_array;
00970               *n_elements_p = n_elements;
00971             }
00972 #ifndef DBUS_DISABLE_CHECKS
00973           else
00974             {
00975               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00976                           _DBUS_FUNCTION_NAME);
00977               goto out;
00978             }
00979 #endif
00980         }
00981 #ifndef DBUS_DISABLE_CHECKS
00982       else
00983         {
00984           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00985                       _DBUS_FUNCTION_NAME);
00986           goto out;
00987         }
00988 #endif
00989 
00990       /* how many arguments already handled */
00991       i++;
00992 
00993       spec_type = va_arg (var_args, int);
00994       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00995         {
00996           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00997                           "Message has only %d arguments, but more were expected", i);
00998           goto out;
00999         }
01000     }
01001 
01002   retval = TRUE;
01003 
01004  out:
01005   /* there may memory or unix fd leak in the above iteration if parse failed.
01006    * so we have another iteration over copy_args to free memory and close
01007    * unix fds.
01008    */
01009   if (!retval)
01010     {
01011       spec_type = first_arg_type;
01012       j = 0;
01013 
01014       while (j < i)
01015         {
01016           if (spec_type == DBUS_TYPE_UNIX_FD)
01017             {
01018 #ifdef HAVE_UNIX_FD_PASSING
01019               int *pfd;
01020 
01021               pfd = va_arg (copy_args, int *);
01022               _dbus_assert(pfd);
01023               if (*pfd >= 0)
01024                 {
01025                   _dbus_close (*pfd, NULL);
01026                   *pfd = -1;
01027                 }
01028 #endif
01029             }
01030           else if (dbus_type_is_basic (spec_type))
01031             {
01032               /* move the index forward */
01033               va_arg (copy_args, DBusBasicValue *);
01034             }
01035           else if (spec_type == DBUS_TYPE_ARRAY)
01036             {
01037               int spec_element_type;
01038 
01039               spec_element_type = va_arg (copy_args, int);
01040               if (dbus_type_is_fixed (spec_element_type))
01041                 {
01042                   /* move the index forward */
01043                   va_arg (copy_args, const DBusBasicValue **);
01044                   va_arg (copy_args, int *);
01045                 }
01046               else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
01047                 {
01048                   char ***str_array_p;
01049 
01050                   str_array_p = va_arg (copy_args, char ***);
01051                   /* move the index forward */
01052                   va_arg (copy_args, int *);
01053                   _dbus_assert (str_array_p != NULL);
01054                   dbus_free_string_array (*str_array_p);
01055                   *str_array_p = NULL;
01056                 }
01057             }
01058 
01059           spec_type = va_arg (copy_args, int);
01060           j++;
01061         }
01062     }
01063 
01064   va_end (copy_args);
01065   return retval;
01066 }
01067 
01126 dbus_uint32_t
01127 dbus_message_get_serial (DBusMessage *message)
01128 {
01129   _dbus_return_val_if_fail (message != NULL, 0);
01130 
01131   return _dbus_header_get_serial (&message->header);
01132 }
01133 
01142 dbus_bool_t
01143 dbus_message_set_reply_serial (DBusMessage   *message,
01144                                dbus_uint32_t  reply_serial)
01145 {
01146   _dbus_return_val_if_fail (message != NULL, FALSE);
01147   _dbus_return_val_if_fail (!message->locked, FALSE);
01148   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01149 
01150   return _dbus_header_set_field_basic (&message->header,
01151                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01152                                        DBUS_TYPE_UINT32,
01153                                        &reply_serial);
01154 }
01155 
01162 dbus_uint32_t
01163 dbus_message_get_reply_serial  (DBusMessage *message)
01164 {
01165   dbus_uint32_t v_UINT32;
01166 
01167   _dbus_return_val_if_fail (message != NULL, 0);
01168 
01169   if (_dbus_header_get_field_basic (&message->header,
01170                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01171                                     DBUS_TYPE_UINT32,
01172                                     &v_UINT32))
01173     return v_UINT32;
01174   else
01175     return 0;
01176 }
01177 
01178 static void
01179 dbus_message_finalize (DBusMessage *message)
01180 {
01181   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01182 
01183   /* This calls application callbacks! */
01184   _dbus_data_slot_list_free (&message->slot_list);
01185 
01186   _dbus_list_foreach (&message->counters,
01187                       free_counter, message);
01188   _dbus_list_clear (&message->counters);
01189 
01190   _dbus_header_free (&message->header);
01191   _dbus_string_free (&message->body);
01192 
01193 #ifdef HAVE_UNIX_FD_PASSING
01194   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01195   dbus_free(message->unix_fds);
01196 #endif
01197 
01198   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01199 
01200   dbus_free (message);
01201 }
01202 
01203 static DBusMessage*
01204 dbus_message_new_empty_header (void)
01205 {
01206   DBusMessage *message;
01207   dbus_bool_t from_cache;
01208 
01209   message = dbus_message_get_cached ();
01210 
01211   if (message != NULL)
01212     {
01213       from_cache = TRUE;
01214     }
01215   else
01216     {
01217       from_cache = FALSE;
01218       message = dbus_new0 (DBusMessage, 1);
01219       if (message == NULL)
01220         return NULL;
01221 #ifndef DBUS_DISABLE_CHECKS
01222       message->generation = _dbus_current_generation;
01223 #endif
01224 
01225 #ifdef HAVE_UNIX_FD_PASSING
01226       message->unix_fds = NULL;
01227       message->n_unix_fds_allocated = 0;
01228 #endif
01229     }
01230 
01231   _dbus_atomic_inc (&message->refcount);
01232 
01233   _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
01234 
01235   message->locked = FALSE;
01236 #ifndef DBUS_DISABLE_CHECKS
01237   message->in_cache = FALSE;
01238 #endif
01239   message->counters = NULL;
01240   message->size_counter_delta = 0;
01241   message->changed_stamp = 0;
01242 
01243 #ifdef HAVE_UNIX_FD_PASSING
01244   message->n_unix_fds = 0;
01245   message->n_unix_fds_allocated = 0;
01246   message->unix_fd_counter_delta = 0;
01247 #endif
01248 
01249   if (!from_cache)
01250     _dbus_data_slot_list_init (&message->slot_list);
01251 
01252   if (from_cache)
01253     {
01254       _dbus_header_reinit (&message->header);
01255       _dbus_string_set_length (&message->body, 0);
01256     }
01257   else
01258     {
01259       if (!_dbus_header_init (&message->header))
01260         {
01261           dbus_free (message);
01262           return NULL;
01263         }
01264 
01265       if (!_dbus_string_init_preallocated (&message->body, 32))
01266         {
01267           _dbus_header_free (&message->header);
01268           dbus_free (message);
01269           return NULL;
01270         }
01271     }
01272 
01273   return message;
01274 }
01275 
01288 DBusMessage*
01289 dbus_message_new (int message_type)
01290 {
01291   DBusMessage *message;
01292 
01293   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01294 
01295   message = dbus_message_new_empty_header ();
01296   if (message == NULL)
01297     return NULL;
01298 
01299   if (!_dbus_header_create (&message->header,
01300                             DBUS_COMPILER_BYTE_ORDER,
01301                             message_type,
01302                             NULL, NULL, NULL, NULL, NULL))
01303     {
01304       dbus_message_unref (message);
01305       return NULL;
01306     }
01307 
01308   return message;
01309 }
01310 
01332 DBusMessage*
01333 dbus_message_new_method_call (const char *destination,
01334                               const char *path,
01335                               const char *iface,
01336                               const char *method)
01337 {
01338   DBusMessage *message;
01339 
01340   _dbus_return_val_if_fail (path != NULL, NULL);
01341   _dbus_return_val_if_fail (method != NULL, NULL);
01342   _dbus_return_val_if_fail (destination == NULL ||
01343                             _dbus_check_is_valid_bus_name (destination), NULL);
01344   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01345   _dbus_return_val_if_fail (iface == NULL ||
01346                             _dbus_check_is_valid_interface (iface), NULL);
01347   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01348 
01349   message = dbus_message_new_empty_header ();
01350   if (message == NULL)
01351     return NULL;
01352 
01353   if (!_dbus_header_create (&message->header,
01354                             DBUS_COMPILER_BYTE_ORDER,
01355                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01356                             destination, path, iface, method, NULL))
01357     {
01358       dbus_message_unref (message);
01359       return NULL;
01360     }
01361 
01362   return message;
01363 }
01364 
01372 DBusMessage*
01373 dbus_message_new_method_return (DBusMessage *method_call)
01374 {
01375   DBusMessage *message;
01376   const char *sender;
01377 
01378   _dbus_return_val_if_fail (method_call != NULL, NULL);
01379 
01380   sender = dbus_message_get_sender (method_call);
01381 
01382   /* sender is allowed to be null here in peer-to-peer case */
01383 
01384   message = dbus_message_new_empty_header ();
01385   if (message == NULL)
01386     return NULL;
01387 
01388   if (!_dbus_header_create (&message->header,
01389                             DBUS_COMPILER_BYTE_ORDER,
01390                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01391                             sender, NULL, NULL, NULL, NULL))
01392     {
01393       dbus_message_unref (message);
01394       return NULL;
01395     }
01396 
01397   dbus_message_set_no_reply (message, TRUE);
01398 
01399   if (!dbus_message_set_reply_serial (message,
01400                                       dbus_message_get_serial (method_call)))
01401     {
01402       dbus_message_unref (message);
01403       return NULL;
01404     }
01405 
01406   return message;
01407 }
01408 
01423 DBusMessage*
01424 dbus_message_new_signal (const char *path,
01425                          const char *iface,
01426                          const char *name)
01427 {
01428   DBusMessage *message;
01429 
01430   _dbus_return_val_if_fail (path != NULL, NULL);
01431   _dbus_return_val_if_fail (iface != NULL, NULL);
01432   _dbus_return_val_if_fail (name != NULL, NULL);
01433   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01434   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
01435   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01436 
01437   message = dbus_message_new_empty_header ();
01438   if (message == NULL)
01439     return NULL;
01440 
01441   if (!_dbus_header_create (&message->header,
01442                             DBUS_COMPILER_BYTE_ORDER,
01443                             DBUS_MESSAGE_TYPE_SIGNAL,
01444                             NULL, path, iface, name, NULL))
01445     {
01446       dbus_message_unref (message);
01447       return NULL;
01448     }
01449 
01450   dbus_message_set_no_reply (message, TRUE);
01451 
01452   return message;
01453 }
01454 
01469 DBusMessage*
01470 dbus_message_new_error (DBusMessage *reply_to,
01471                         const char  *error_name,
01472                         const char  *error_message)
01473 {
01474   DBusMessage *message;
01475   const char *sender;
01476   DBusMessageIter iter;
01477 
01478   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01479   _dbus_return_val_if_fail (error_name != NULL, NULL);
01480   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01481 
01482   sender = dbus_message_get_sender (reply_to);
01483 
01484   /* sender may be NULL for non-message-bus case or
01485    * when the message bus is dealing with an unregistered
01486    * connection.
01487    */
01488   message = dbus_message_new_empty_header ();
01489   if (message == NULL)
01490     return NULL;
01491 
01492   if (!_dbus_header_create (&message->header,
01493                             DBUS_COMPILER_BYTE_ORDER,
01494                             DBUS_MESSAGE_TYPE_ERROR,
01495                             sender, NULL, NULL, NULL, error_name))
01496     {
01497       dbus_message_unref (message);
01498       return NULL;
01499     }
01500 
01501   dbus_message_set_no_reply (message, TRUE);
01502 
01503   if (!dbus_message_set_reply_serial (message,
01504                                       dbus_message_get_serial (reply_to)))
01505     {
01506       dbus_message_unref (message);
01507       return NULL;
01508     }
01509 
01510   if (error_message != NULL)
01511     {
01512       dbus_message_iter_init_append (message, &iter);
01513       if (!dbus_message_iter_append_basic (&iter,
01514                                            DBUS_TYPE_STRING,
01515                                            &error_message))
01516         {
01517           dbus_message_unref (message);
01518           return NULL;
01519         }
01520     }
01521 
01522   return message;
01523 }
01524 
01541 DBusMessage*
01542 dbus_message_new_error_printf (DBusMessage *reply_to,
01543                                const char  *error_name,
01544                                const char  *error_format,
01545                                ...)
01546 {
01547   va_list args;
01548   DBusString str;
01549   DBusMessage *message;
01550 
01551   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01552   _dbus_return_val_if_fail (error_name != NULL, NULL);
01553   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01554 
01555   if (!_dbus_string_init (&str))
01556     return NULL;
01557 
01558   va_start (args, error_format);
01559 
01560   if (_dbus_string_append_printf_valist (&str, error_format, args))
01561     message = dbus_message_new_error (reply_to, error_name,
01562                                       _dbus_string_get_const_data (&str));
01563   else
01564     message = NULL;
01565 
01566   _dbus_string_free (&str);
01567 
01568   va_end (args);
01569 
01570   return message;
01571 }
01572 
01573 
01586 DBusMessage *
01587 dbus_message_copy (const DBusMessage *message)
01588 {
01589   DBusMessage *retval;
01590 
01591   _dbus_return_val_if_fail (message != NULL, NULL);
01592 
01593   retval = dbus_new0 (DBusMessage, 1);
01594   if (retval == NULL)
01595     return NULL;
01596 
01597   _dbus_atomic_inc (&retval->refcount);
01598 
01599   retval->locked = FALSE;
01600 #ifndef DBUS_DISABLE_CHECKS
01601   retval->generation = message->generation;
01602 #endif
01603 
01604   if (!_dbus_header_copy (&message->header, &retval->header))
01605     {
01606       dbus_free (retval);
01607       return NULL;
01608     }
01609 
01610   if (!_dbus_string_init_preallocated (&retval->body,
01611                                        _dbus_string_get_length (&message->body)))
01612     {
01613       _dbus_header_free (&retval->header);
01614       dbus_free (retval);
01615       return NULL;
01616     }
01617 
01618   if (!_dbus_string_copy (&message->body, 0,
01619                           &retval->body, 0))
01620     goto failed_copy;
01621 
01622 #ifdef HAVE_UNIX_FD_PASSING
01623   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01624   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01625     goto failed_copy;
01626 
01627   retval->n_unix_fds_allocated = message->n_unix_fds;
01628 
01629   for (retval->n_unix_fds = 0;
01630        retval->n_unix_fds < message->n_unix_fds;
01631        retval->n_unix_fds++)
01632     {
01633       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01634 
01635       if (retval->unix_fds[retval->n_unix_fds] < 0)
01636         goto failed_copy;
01637     }
01638 
01639 #endif
01640 
01641   _dbus_message_trace_ref (retval, 0, 1, "copy");
01642   return retval;
01643 
01644  failed_copy:
01645   _dbus_header_free (&retval->header);
01646   _dbus_string_free (&retval->body);
01647 
01648 #ifdef HAVE_UNIX_FD_PASSING
01649   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01650   dbus_free(retval->unix_fds);
01651 #endif
01652 
01653   dbus_free (retval);
01654 
01655   return NULL;
01656 }
01657 
01658 
01666 DBusMessage *
01667 dbus_message_ref (DBusMessage *message)
01668 {
01669   dbus_int32_t old_refcount;
01670 
01671   _dbus_return_val_if_fail (message != NULL, NULL);
01672   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01673   _dbus_return_val_if_fail (!message->in_cache, NULL);
01674 
01675   old_refcount = _dbus_atomic_inc (&message->refcount);
01676   _dbus_assert (old_refcount >= 1);
01677   _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
01678 
01679   return message;
01680 }
01681 
01689 void
01690 dbus_message_unref (DBusMessage *message)
01691 {
01692  dbus_int32_t old_refcount;
01693 
01694   _dbus_return_if_fail (message != NULL);
01695   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01696   _dbus_return_if_fail (!message->in_cache);
01697 
01698   old_refcount = _dbus_atomic_dec (&message->refcount);
01699 
01700   _dbus_assert (old_refcount >= 1);
01701 
01702   _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
01703 
01704   if (old_refcount == 1)
01705     {
01706       /* Calls application callbacks! */
01707       dbus_message_cache_or_finalize (message);
01708     }
01709 }
01710 
01721 int
01722 dbus_message_get_type (DBusMessage *message)
01723 {
01724   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01725 
01726   return _dbus_header_get_message_type (&message->header);
01727 }
01728 
01791 dbus_bool_t
01792 dbus_message_append_args (DBusMessage *message,
01793                           int          first_arg_type,
01794                           ...)
01795 {
01796   dbus_bool_t retval;
01797   va_list var_args;
01798 
01799   _dbus_return_val_if_fail (message != NULL, FALSE);
01800 
01801   va_start (var_args, first_arg_type);
01802   retval = dbus_message_append_args_valist (message,
01803                                             first_arg_type,
01804                                             var_args);
01805   va_end (var_args);
01806 
01807   return retval;
01808 }
01809 
01823 dbus_bool_t
01824 dbus_message_append_args_valist (DBusMessage *message,
01825                                  int          first_arg_type,
01826                                  va_list      var_args)
01827 {
01828   int type;
01829   DBusMessageIter iter;
01830 
01831   _dbus_return_val_if_fail (message != NULL, FALSE);
01832 
01833   type = first_arg_type;
01834 
01835   dbus_message_iter_init_append (message, &iter);
01836 
01837   while (type != DBUS_TYPE_INVALID)
01838     {
01839       if (dbus_type_is_basic (type))
01840         {
01841           const DBusBasicValue *value;
01842           value = va_arg (var_args, const DBusBasicValue*);
01843 
01844           if (!dbus_message_iter_append_basic (&iter,
01845                                                type,
01846                                                value))
01847             goto failed;
01848         }
01849       else if (type == DBUS_TYPE_ARRAY)
01850         {
01851           int element_type;
01852           DBusMessageIter array;
01853           char buf[2];
01854 
01855           element_type = va_arg (var_args, int);
01856               
01857           buf[0] = element_type;
01858           buf[1] = '\0';
01859           if (!dbus_message_iter_open_container (&iter,
01860                                                  DBUS_TYPE_ARRAY,
01861                                                  buf,
01862                                                  &array))
01863             goto failed;
01864 
01865           if (dbus_type_is_fixed (element_type) &&
01866               element_type != DBUS_TYPE_UNIX_FD)
01867             {
01868               const DBusBasicValue **value;
01869               int n_elements;
01870 
01871               value = va_arg (var_args, const DBusBasicValue**);
01872               n_elements = va_arg (var_args, int);
01873               
01874               if (!dbus_message_iter_append_fixed_array (&array,
01875                                                          element_type,
01876                                                          value,
01877                                                          n_elements)) {
01878                 dbus_message_iter_abandon_container (&iter, &array);
01879                 goto failed;
01880               }
01881             }
01882           else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
01883             {
01884               const char ***value_p;
01885               const char **value;
01886               int n_elements;
01887               int i;
01888               
01889               value_p = va_arg (var_args, const char***);
01890               n_elements = va_arg (var_args, int);
01891 
01892               value = *value_p;
01893               
01894               i = 0;
01895               while (i < n_elements)
01896                 {
01897                   if (!dbus_message_iter_append_basic (&array,
01898                                                        element_type,
01899                                                        &value[i])) {
01900                     dbus_message_iter_abandon_container (&iter, &array);
01901                     goto failed;
01902                   }
01903                   ++i;
01904                 }
01905             }
01906           else
01907             {
01908               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01909                           _dbus_type_to_string (element_type),
01910                           _DBUS_FUNCTION_NAME);
01911               goto failed;
01912             }
01913 
01914           if (!dbus_message_iter_close_container (&iter, &array))
01915             goto failed;
01916         }
01917 #ifndef DBUS_DISABLE_CHECKS
01918       else
01919         {
01920           _dbus_warn ("type %s isn't supported yet in %s\n",
01921                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01922           goto failed;
01923         }
01924 #endif
01925 
01926       type = va_arg (var_args, int);
01927     }
01928 
01929   return TRUE;
01930 
01931  failed:
01932   return FALSE;
01933 }
01934 
01979 dbus_bool_t
01980 dbus_message_get_args (DBusMessage     *message,
01981                        DBusError       *error,
01982                        int              first_arg_type,
01983                        ...)
01984 {
01985   dbus_bool_t retval;
01986   va_list var_args;
01987 
01988   _dbus_return_val_if_fail (message != NULL, FALSE);
01989   _dbus_return_val_if_error_is_set (error, FALSE);
01990 
01991   va_start (var_args, first_arg_type);
01992   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01993   va_end (var_args);
01994 
01995   return retval;
01996 }
01997 
02008 dbus_bool_t
02009 dbus_message_get_args_valist (DBusMessage     *message,
02010                               DBusError       *error,
02011                               int              first_arg_type,
02012                               va_list          var_args)
02013 {
02014   DBusMessageIter iter;
02015 
02016   _dbus_return_val_if_fail (message != NULL, FALSE);
02017   _dbus_return_val_if_error_is_set (error, FALSE);
02018 
02019   dbus_message_iter_init (message, &iter);
02020   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
02021 }
02022 
02023 static void
02024 _dbus_message_iter_init_common (DBusMessage         *message,
02025                                 DBusMessageRealIter *real,
02026                                 int                  iter_type)
02027 {
02028   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
02029 
02030   /* Since the iterator will read or write who-knows-what from the
02031    * message, we need to get in the right byte order
02032    */
02033   ensure_byte_order (message);
02034   
02035   real->message = message;
02036   real->changed_stamp = message->changed_stamp;
02037   real->iter_type = iter_type;
02038   real->sig_refcount = 0;
02039 }
02040 
02063 dbus_bool_t
02064 dbus_message_iter_init (DBusMessage     *message,
02065                         DBusMessageIter *iter)
02066 {
02067   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02068   const DBusString *type_str;
02069   int type_pos;
02070 
02071   _dbus_return_val_if_fail (message != NULL, FALSE);
02072   _dbus_return_val_if_fail (iter != NULL, FALSE);
02073 
02074   get_const_signature (&message->header, &type_str, &type_pos);
02075 
02076   _dbus_message_iter_init_common (message, real,
02077                                   DBUS_MESSAGE_ITER_TYPE_READER);
02078 
02079   _dbus_type_reader_init (&real->u.reader,
02080                           _dbus_header_get_byte_order (&message->header),
02081                           type_str, type_pos,
02082                           &message->body,
02083                           0);
02084 
02085   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
02086 }
02087 
02094 dbus_bool_t
02095 dbus_message_iter_has_next (DBusMessageIter *iter)
02096 {
02097   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02098 
02099   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02100   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02101 
02102   return _dbus_type_reader_has_next (&real->u.reader);
02103 }
02104 
02113 dbus_bool_t
02114 dbus_message_iter_next (DBusMessageIter *iter)
02115 {
02116   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02117 
02118   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02119   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02120 
02121   return _dbus_type_reader_next (&real->u.reader);
02122 }
02123 
02138 int
02139 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02140 {
02141   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02142 
02143   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02144   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02145 
02146   return _dbus_type_reader_get_current_type (&real->u.reader);
02147 }
02148 
02157 int
02158 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02159 {
02160   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02161 
02162   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02163   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02164   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02165 
02166   return _dbus_type_reader_get_element_type (&real->u.reader);
02167 }
02168 
02194 void
02195 dbus_message_iter_recurse (DBusMessageIter  *iter,
02196                            DBusMessageIter  *sub)
02197 {
02198   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02199   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02200 
02201   _dbus_return_if_fail (_dbus_message_iter_check (real));
02202   _dbus_return_if_fail (sub != NULL);
02203 
02204   *real_sub = *real;
02205   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02206 }
02207 
02219 char *
02220 dbus_message_iter_get_signature (DBusMessageIter *iter)
02221 {
02222   const DBusString *sig;
02223   DBusString retstr;
02224   char *ret;
02225   int start, len;
02226   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02227 
02228   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02229 
02230   if (!_dbus_string_init (&retstr))
02231     return NULL;
02232 
02233   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02234                                    &start, &len);
02235   if (!_dbus_string_append_len (&retstr,
02236                                 _dbus_string_get_const_data (sig) + start,
02237                                 len))
02238     return NULL;
02239   if (!_dbus_string_steal_data (&retstr, &ret))
02240     return NULL;
02241   _dbus_string_free (&retstr);
02242   return ret;
02243 }
02244 
02292 void
02293 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02294                              void             *value)
02295 {
02296   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02297 
02298   _dbus_return_if_fail (_dbus_message_iter_check (real));
02299   _dbus_return_if_fail (value != NULL);
02300 
02301   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02302     {
02303 #ifdef HAVE_UNIX_FD_PASSING
02304       DBusBasicValue idx;
02305 
02306       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02307 
02308       if (idx.u32 >= real->message->n_unix_fds) {
02309         /* Hmm, we cannot really signal an error here, so let's make
02310            sure to return an invalid fd. */
02311         *((int*) value) = -1;
02312         return;
02313       }
02314 
02315       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02316 #else
02317       *((int*) value) = -1;
02318 #endif
02319     }
02320   else
02321     {
02322       _dbus_type_reader_read_basic (&real->u.reader,
02323                                     value);
02324     }
02325 }
02326 
02345 int
02346 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02347 {
02348   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02349 
02350   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02351 
02352   return _dbus_type_reader_get_array_length (&real->u.reader);
02353 }
02354 
02390 void
02391 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02392                                    void             *value,
02393                                    int              *n_elements)
02394 {
02395   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02396 #ifndef DBUS_DISABLE_CHECKS
02397   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02398 
02399   _dbus_return_if_fail (_dbus_message_iter_check (real));
02400   _dbus_return_if_fail (value != NULL);
02401   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02402                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02403 #endif
02404 
02405   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02406                                       value, n_elements);
02407 }
02408 
02420 void
02421 dbus_message_iter_init_append (DBusMessage     *message,
02422                                DBusMessageIter *iter)
02423 {
02424   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02425 
02426   _dbus_return_if_fail (message != NULL);
02427   _dbus_return_if_fail (iter != NULL);
02428 
02429   _dbus_message_iter_init_common (message, real,
02430                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02431 
02432   /* We create the signature string and point iterators at it "on demand"
02433    * when a value is actually appended. That means that init() never fails
02434    * due to OOM.
02435    */
02436   _dbus_type_writer_init_types_delayed (&real->u.writer,
02437                                         _dbus_header_get_byte_order (&message->header),
02438                                         &message->body,
02439                                         _dbus_string_get_length (&message->body));
02440 }
02441 
02450 static dbus_bool_t
02451 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02452 {
02453   DBusString *str;
02454   const DBusString *current_sig;
02455   int current_sig_pos;
02456 
02457   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02458 
02459   if (real->u.writer.type_str != NULL)
02460     {
02461       _dbus_assert (real->sig_refcount > 0);
02462       real->sig_refcount += 1;
02463       return TRUE;
02464     }
02465 
02466   str = dbus_new (DBusString, 1);
02467   if (str == NULL)
02468     return FALSE;
02469 
02470   if (!_dbus_header_get_field_raw (&real->message->header,
02471                                    DBUS_HEADER_FIELD_SIGNATURE,
02472                                    &current_sig, &current_sig_pos))
02473     current_sig = NULL;
02474 
02475   if (current_sig)
02476     {
02477       int current_len;
02478 
02479       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02480       current_sig_pos += 1; /* move on to sig data */
02481 
02482       if (!_dbus_string_init_preallocated (str, current_len + 4))
02483         {
02484           dbus_free (str);
02485           return FALSE;
02486         }
02487 
02488       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02489                                   str, 0))
02490         {
02491           _dbus_string_free (str);
02492           dbus_free (str);
02493           return FALSE;
02494         }
02495     }
02496   else
02497     {
02498       if (!_dbus_string_init_preallocated (str, 4))
02499         {
02500           dbus_free (str);
02501           return FALSE;
02502         }
02503     }
02504 
02505   real->sig_refcount = 1;
02506 
02507   _dbus_type_writer_add_types (&real->u.writer,
02508                                str, _dbus_string_get_length (str));
02509   return TRUE;
02510 }
02511 
02521 static dbus_bool_t
02522 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02523 {
02524   DBusString *str;
02525   const char *v_STRING;
02526   dbus_bool_t retval;
02527 
02528   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02529   _dbus_assert (real->u.writer.type_str != NULL);
02530   _dbus_assert (real->sig_refcount > 0);
02531 
02532   real->sig_refcount -= 1;
02533 
02534   if (real->sig_refcount > 0)
02535     return TRUE;
02536   _dbus_assert (real->sig_refcount == 0);
02537 
02538   retval = TRUE;
02539 
02540   str = real->u.writer.type_str;
02541 
02542   v_STRING = _dbus_string_get_const_data (str);
02543   if (!_dbus_header_set_field_basic (&real->message->header,
02544                                      DBUS_HEADER_FIELD_SIGNATURE,
02545                                      DBUS_TYPE_SIGNATURE,
02546                                      &v_STRING))
02547     retval = FALSE;
02548 
02549   _dbus_type_writer_remove_types (&real->u.writer);
02550   _dbus_string_free (str);
02551   dbus_free (str);
02552 
02553   return retval;
02554 }
02555 
02563 static void
02564 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02565 {
02566   DBusString *str;
02567 
02568   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02569   _dbus_assert (real->u.writer.type_str != NULL);
02570   _dbus_assert (real->sig_refcount > 0);
02571 
02572   real->sig_refcount -= 1;
02573 
02574   if (real->sig_refcount > 0)
02575     return;
02576   _dbus_assert (real->sig_refcount == 0);
02577 
02578   str = real->u.writer.type_str;
02579 
02580   _dbus_type_writer_remove_types (&real->u.writer);
02581   _dbus_string_free (str);
02582   dbus_free (str);
02583 }
02584 
02585 #ifndef DBUS_DISABLE_CHECKS
02586 static dbus_bool_t
02587 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02588 {
02589   if (!_dbus_message_iter_check (iter))
02590     return FALSE;
02591 
02592   if (iter->message->locked)
02593     {
02594       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02595       return FALSE;
02596     }
02597 
02598   return TRUE;
02599 }
02600 #endif /* DBUS_DISABLE_CHECKS */
02601 
02602 #ifdef HAVE_UNIX_FD_PASSING
02603 static int *
02604 expand_fd_array(DBusMessage *m,
02605                 unsigned     n)
02606 {
02607   _dbus_assert(m);
02608 
02609   /* This makes space for adding n new fds to the array and returns a
02610      pointer to the place were the first fd should be put. */
02611 
02612   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02613     {
02614       unsigned k;
02615       int *p;
02616 
02617       /* Make twice as much space as necessary */
02618       k = (m->n_unix_fds + n) * 2;
02619 
02620       /* Allocate at least four */
02621       if (k < 4)
02622         k = 4;
02623 
02624       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02625       if (p == NULL)
02626         return NULL;
02627 
02628       m->unix_fds = p;
02629       m->n_unix_fds_allocated = k;
02630     }
02631 
02632   return m->unix_fds + m->n_unix_fds;
02633 }
02634 #endif
02635 
02655 dbus_bool_t
02656 dbus_message_iter_append_basic (DBusMessageIter *iter,
02657                                 int              type,
02658                                 const void      *value)
02659 {
02660   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02661   dbus_bool_t ret;
02662 
02663   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02664   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02665   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02666   _dbus_return_val_if_fail (value != NULL, FALSE);
02667 
02668 #ifndef DBUS_DISABLE_CHECKS
02669   switch (type)
02670     {
02671       const char * const *string_p;
02672       const dbus_bool_t *bool_p;
02673 
02674       case DBUS_TYPE_STRING:
02675         string_p = value;
02676         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02677         break;
02678 
02679       case DBUS_TYPE_OBJECT_PATH:
02680         string_p = value;
02681         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02682         break;
02683 
02684       case DBUS_TYPE_SIGNATURE:
02685         string_p = value;
02686         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02687         break;
02688 
02689       case DBUS_TYPE_BOOLEAN:
02690         bool_p = value;
02691         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02692         break;
02693 
02694       default:
02695           {
02696             /* nothing to check, all possible values are allowed */
02697           }
02698     }
02699 #endif
02700 
02701   if (!_dbus_message_iter_open_signature (real))
02702     return FALSE;
02703 
02704   if (type == DBUS_TYPE_UNIX_FD)
02705     {
02706 #ifdef HAVE_UNIX_FD_PASSING
02707       int *fds;
02708       dbus_uint32_t u;
02709 
02710       /* First step, include the fd in the fd list of this message */
02711       if (!(fds = expand_fd_array(real->message, 1)))
02712         return FALSE;
02713 
02714       *fds = _dbus_dup(*(int*) value, NULL);
02715       if (*fds < 0)
02716         return FALSE;
02717 
02718       u = real->message->n_unix_fds;
02719 
02720       /* Second step, write the index to the fd */
02721       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02722         _dbus_close(*fds, NULL);
02723         return FALSE;
02724       }
02725 
02726       real->message->n_unix_fds += 1;
02727       u += 1;
02728 
02729       /* Final step, update the header accordingly */
02730       ret = _dbus_header_set_field_basic (&real->message->header,
02731                                           DBUS_HEADER_FIELD_UNIX_FDS,
02732                                           DBUS_TYPE_UINT32,
02733                                           &u);
02734 
02735       /* If any of these operations fail the message is
02736          hosed. However, no memory or fds should be leaked since what
02737          has been added to message has been added to the message, and
02738          can hence be accounted for when the message is being
02739          freed. */
02740 #else
02741       ret = FALSE;
02742 #endif
02743     }
02744   else
02745     {
02746       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02747     }
02748 
02749   if (!_dbus_message_iter_close_signature (real))
02750     ret = FALSE;
02751 
02752   return ret;
02753 }
02754 
02790 dbus_bool_t
02791 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02792                                       int              element_type,
02793                                       const void      *value,
02794                                       int              n_elements)
02795 {
02796   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02797   dbus_bool_t ret;
02798 
02799   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02800   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02801   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02802   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02803   _dbus_return_val_if_fail (value != NULL, FALSE);
02804   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02805   _dbus_return_val_if_fail (n_elements <=
02806                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02807                             FALSE);
02808 
02809 #ifndef DBUS_DISABLE_CHECKS
02810   if (element_type == DBUS_TYPE_BOOLEAN)
02811     {
02812       const dbus_bool_t * const *bools = value;
02813       int i;
02814 
02815       for (i = 0; i < n_elements; i++)
02816         {
02817           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02818         }
02819     }
02820 #endif
02821 
02822   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02823 
02824   return ret;
02825 }
02826 
02848 dbus_bool_t
02849 dbus_message_iter_open_container (DBusMessageIter *iter,
02850                                   int              type,
02851                                   const char      *contained_signature,
02852                                   DBusMessageIter *sub)
02853 {
02854   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02855   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02856   DBusString contained_str;
02857 
02858   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02859   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02860   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02861   _dbus_return_val_if_fail (sub != NULL, FALSE);
02862   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02863                              contained_signature == NULL) ||
02864                             (type == DBUS_TYPE_DICT_ENTRY &&
02865                              contained_signature == NULL) ||
02866                             (type == DBUS_TYPE_VARIANT &&
02867                              contained_signature != NULL) ||
02868                             (type == DBUS_TYPE_ARRAY &&
02869                              contained_signature != NULL), FALSE);
02870   
02871   /* this would fail if the contained_signature is a dict entry, since
02872    * dict entries are invalid signatures standalone (they must be in
02873    * an array)
02874    */
02875   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02876                             (contained_signature == NULL ||
02877                              _dbus_check_is_valid_signature (contained_signature)),
02878                             FALSE);
02879 
02880   if (!_dbus_message_iter_open_signature (real))
02881     return FALSE;
02882 
02883   *real_sub = *real;
02884 
02885   if (contained_signature != NULL)
02886     {
02887       _dbus_string_init_const (&contained_str, contained_signature);
02888 
02889       return _dbus_type_writer_recurse (&real->u.writer,
02890                                         type,
02891                                         &contained_str, 0,
02892                                         &real_sub->u.writer);
02893     }
02894   else
02895     {
02896       return _dbus_type_writer_recurse (&real->u.writer,
02897                                         type,
02898                                         NULL, 0,
02899                                         &real_sub->u.writer);
02900     } 
02901 }
02902 
02903 
02917 dbus_bool_t
02918 dbus_message_iter_close_container (DBusMessageIter *iter,
02919                                    DBusMessageIter *sub)
02920 {
02921   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02922   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02923   dbus_bool_t ret;
02924 
02925   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02926   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02927   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02928   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02929 
02930   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02931                                      &real_sub->u.writer);
02932 
02933   if (!_dbus_message_iter_close_signature (real))
02934     ret = FALSE;
02935 
02936   return ret;
02937 }
02938 
02950 void
02951 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02952                                      DBusMessageIter *sub)
02953 {
02954   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02955 #ifndef DBUS_DISABLE_CHECKS
02956   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02957 
02958   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02959   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02960   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02961   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02962 #endif
02963 
02964   _dbus_message_iter_abandon_signature (real);
02965 }
02966 
02983 void
02984 dbus_message_set_no_reply (DBusMessage *message,
02985                            dbus_bool_t  no_reply)
02986 {
02987   _dbus_return_if_fail (message != NULL);
02988   _dbus_return_if_fail (!message->locked);
02989 
02990   _dbus_header_toggle_flag (&message->header,
02991                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02992                             no_reply);
02993 }
02994 
03002 dbus_bool_t
03003 dbus_message_get_no_reply (DBusMessage *message)
03004 {
03005   _dbus_return_val_if_fail (message != NULL, FALSE);
03006 
03007   return _dbus_header_get_flag (&message->header,
03008                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
03009 }
03010 
03025 void
03026 dbus_message_set_auto_start (DBusMessage *message,
03027                              dbus_bool_t  auto_start)
03028 {
03029   _dbus_return_if_fail (message != NULL);
03030   _dbus_return_if_fail (!message->locked);
03031 
03032   _dbus_header_toggle_flag (&message->header,
03033                             DBUS_HEADER_FLAG_NO_AUTO_START,
03034                             !auto_start);
03035 }
03036 
03044 dbus_bool_t
03045 dbus_message_get_auto_start (DBusMessage *message)
03046 {
03047   _dbus_return_val_if_fail (message != NULL, FALSE);
03048 
03049   return !_dbus_header_get_flag (&message->header,
03050                                  DBUS_HEADER_FLAG_NO_AUTO_START);
03051 }
03052 
03053 
03066 dbus_bool_t
03067 dbus_message_set_path (DBusMessage   *message,
03068                        const char    *object_path)
03069 {
03070   _dbus_return_val_if_fail (message != NULL, FALSE);
03071   _dbus_return_val_if_fail (!message->locked, FALSE);
03072   _dbus_return_val_if_fail (object_path == NULL ||
03073                             _dbus_check_is_valid_path (object_path),
03074                             FALSE);
03075 
03076   return set_or_delete_string_field (message,
03077                                      DBUS_HEADER_FIELD_PATH,
03078                                      DBUS_TYPE_OBJECT_PATH,
03079                                      object_path);
03080 }
03081 
03095 const char*
03096 dbus_message_get_path (DBusMessage   *message)
03097 {
03098   const char *v;
03099 
03100   _dbus_return_val_if_fail (message != NULL, NULL);
03101 
03102   v = NULL; /* in case field doesn't exist */
03103   _dbus_header_get_field_basic (&message->header,
03104                                 DBUS_HEADER_FIELD_PATH,
03105                                 DBUS_TYPE_OBJECT_PATH,
03106                                 (void *) &v);
03107   return v;
03108 }
03109 
03119 dbus_bool_t
03120 dbus_message_has_path (DBusMessage   *message,
03121                        const char    *path)
03122 {
03123   const char *msg_path;
03124   msg_path = dbus_message_get_path (message);
03125   
03126   if (msg_path == NULL)
03127     {
03128       if (path == NULL)
03129         return TRUE;
03130       else
03131         return FALSE;
03132     }
03133 
03134   if (path == NULL)
03135     return FALSE;
03136    
03137   if (strcmp (msg_path, path) == 0)
03138     return TRUE;
03139 
03140   return FALSE;
03141 }
03142 
03163 dbus_bool_t
03164 dbus_message_get_path_decomposed (DBusMessage   *message,
03165                                   char        ***path)
03166 {
03167   const char *v;
03168 
03169   _dbus_return_val_if_fail (message != NULL, FALSE);
03170   _dbus_return_val_if_fail (path != NULL, FALSE);
03171 
03172   *path = NULL;
03173 
03174   v = dbus_message_get_path (message);
03175   if (v != NULL)
03176     {
03177       if (!_dbus_decompose_path (v, strlen (v),
03178                                  path, NULL))
03179         return FALSE;
03180     }
03181   return TRUE;
03182 }
03183 
03197 dbus_bool_t
03198 dbus_message_set_interface (DBusMessage  *message,
03199                             const char   *iface)
03200 {
03201   _dbus_return_val_if_fail (message != NULL, FALSE);
03202   _dbus_return_val_if_fail (!message->locked, FALSE);
03203   _dbus_return_val_if_fail (iface == NULL ||
03204                             _dbus_check_is_valid_interface (iface),
03205                             FALSE);
03206 
03207   return set_or_delete_string_field (message,
03208                                      DBUS_HEADER_FIELD_INTERFACE,
03209                                      DBUS_TYPE_STRING,
03210                                      iface);
03211 }
03212 
03226 const char*
03227 dbus_message_get_interface (DBusMessage *message)
03228 {
03229   const char *v;
03230 
03231   _dbus_return_val_if_fail (message != NULL, NULL);
03232 
03233   v = NULL; /* in case field doesn't exist */
03234   _dbus_header_get_field_basic (&message->header,
03235                                 DBUS_HEADER_FIELD_INTERFACE,
03236                                 DBUS_TYPE_STRING,
03237                                 (void *) &v);
03238   return v;
03239 }
03240 
03248 dbus_bool_t
03249 dbus_message_has_interface (DBusMessage   *message,
03250                             const char    *iface)
03251 {
03252   const char *msg_interface;
03253   msg_interface = dbus_message_get_interface (message);
03254    
03255   if (msg_interface == NULL)
03256     {
03257       if (iface == NULL)
03258         return TRUE;
03259       else
03260         return FALSE;
03261     }
03262 
03263   if (iface == NULL)
03264     return FALSE;
03265      
03266   if (strcmp (msg_interface, iface) == 0)
03267     return TRUE;
03268 
03269   return FALSE;
03270 
03271 }
03272 
03285 dbus_bool_t
03286 dbus_message_set_member (DBusMessage  *message,
03287                          const char   *member)
03288 {
03289   _dbus_return_val_if_fail (message != NULL, FALSE);
03290   _dbus_return_val_if_fail (!message->locked, FALSE);
03291   _dbus_return_val_if_fail (member == NULL ||
03292                             _dbus_check_is_valid_member (member),
03293                             FALSE);
03294 
03295   return set_or_delete_string_field (message,
03296                                      DBUS_HEADER_FIELD_MEMBER,
03297                                      DBUS_TYPE_STRING,
03298                                      member);
03299 }
03300 
03312 const char*
03313 dbus_message_get_member (DBusMessage *message)
03314 {
03315   const char *v;
03316 
03317   _dbus_return_val_if_fail (message != NULL, NULL);
03318 
03319   v = NULL; /* in case field doesn't exist */
03320   _dbus_header_get_field_basic (&message->header,
03321                                 DBUS_HEADER_FIELD_MEMBER,
03322                                 DBUS_TYPE_STRING,
03323                                 (void *) &v);
03324   return v;
03325 }
03326 
03334 dbus_bool_t
03335 dbus_message_has_member (DBusMessage   *message,
03336                          const char    *member)
03337 {
03338   const char *msg_member;
03339   msg_member = dbus_message_get_member (message);
03340  
03341   if (msg_member == NULL)
03342     {
03343       if (member == NULL)
03344         return TRUE;
03345       else
03346         return FALSE;
03347     }
03348 
03349   if (member == NULL)
03350     return FALSE;
03351     
03352   if (strcmp (msg_member, member) == 0)
03353     return TRUE;
03354 
03355   return FALSE;
03356 
03357 }
03358 
03370 dbus_bool_t
03371 dbus_message_set_error_name (DBusMessage  *message,
03372                              const char   *error_name)
03373 {
03374   _dbus_return_val_if_fail (message != NULL, FALSE);
03375   _dbus_return_val_if_fail (!message->locked, FALSE);
03376   _dbus_return_val_if_fail (error_name == NULL ||
03377                             _dbus_check_is_valid_error_name (error_name),
03378                             FALSE);
03379 
03380   return set_or_delete_string_field (message,
03381                                      DBUS_HEADER_FIELD_ERROR_NAME,
03382                                      DBUS_TYPE_STRING,
03383                                      error_name);
03384 }
03385 
03396 const char*
03397 dbus_message_get_error_name (DBusMessage *message)
03398 {
03399   const char *v;
03400 
03401   _dbus_return_val_if_fail (message != NULL, NULL);
03402 
03403   v = NULL; /* in case field doesn't exist */
03404   _dbus_header_get_field_basic (&message->header,
03405                                 DBUS_HEADER_FIELD_ERROR_NAME,
03406                                 DBUS_TYPE_STRING,
03407                                 (void *) &v);
03408   return v;
03409 }
03410 
03424 dbus_bool_t
03425 dbus_message_set_destination (DBusMessage  *message,
03426                               const char   *destination)
03427 {
03428   _dbus_return_val_if_fail (message != NULL, FALSE);
03429   _dbus_return_val_if_fail (!message->locked, FALSE);
03430   _dbus_return_val_if_fail (destination == NULL ||
03431                             _dbus_check_is_valid_bus_name (destination),
03432                             FALSE);
03433 
03434   return set_or_delete_string_field (message,
03435                                      DBUS_HEADER_FIELD_DESTINATION,
03436                                      DBUS_TYPE_STRING,
03437                                      destination);
03438 }
03439 
03449 const char*
03450 dbus_message_get_destination (DBusMessage *message)
03451 {
03452   const char *v;
03453 
03454   _dbus_return_val_if_fail (message != NULL, NULL);
03455 
03456   v = NULL; /* in case field doesn't exist */
03457   _dbus_header_get_field_basic (&message->header,
03458                                 DBUS_HEADER_FIELD_DESTINATION,
03459                                 DBUS_TYPE_STRING,
03460                                 (void *) &v);
03461   return v;
03462 }
03463 
03478 dbus_bool_t
03479 dbus_message_set_sender (DBusMessage  *message,
03480                          const char   *sender)
03481 {
03482   _dbus_return_val_if_fail (message != NULL, FALSE);
03483   _dbus_return_val_if_fail (!message->locked, FALSE);
03484   _dbus_return_val_if_fail (sender == NULL ||
03485                             _dbus_check_is_valid_bus_name (sender),
03486                             FALSE);
03487 
03488   return set_or_delete_string_field (message,
03489                                      DBUS_HEADER_FIELD_SENDER,
03490                                      DBUS_TYPE_STRING,
03491                                      sender);
03492 }
03493 
03509 const char*
03510 dbus_message_get_sender (DBusMessage *message)
03511 {
03512   const char *v;
03513 
03514   _dbus_return_val_if_fail (message != NULL, NULL);
03515 
03516   v = NULL; /* in case field doesn't exist */
03517   _dbus_header_get_field_basic (&message->header,
03518                                 DBUS_HEADER_FIELD_SENDER,
03519                                 DBUS_TYPE_STRING,
03520                                 (void *) &v);
03521   return v;
03522 }
03523 
03542 const char*
03543 dbus_message_get_signature (DBusMessage *message)
03544 {
03545   const DBusString *type_str;
03546   int type_pos;
03547 
03548   _dbus_return_val_if_fail (message != NULL, NULL);
03549 
03550   get_const_signature (&message->header, &type_str, &type_pos);
03551 
03552   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03553 }
03554 
03555 static dbus_bool_t
03556 _dbus_message_has_type_interface_member (DBusMessage *message,
03557                                          int          type,
03558                                          const char  *iface,
03559                                          const char  *member)
03560 {
03561   const char *n;
03562 
03563   _dbus_assert (message != NULL);
03564   _dbus_assert (iface != NULL);
03565   _dbus_assert (member != NULL);
03566 
03567   if (dbus_message_get_type (message) != type)
03568     return FALSE;
03569 
03570   /* Optimize by checking the short member name first
03571    * instead of the longer interface name
03572    */
03573 
03574   n = dbus_message_get_member (message);
03575 
03576   if (n && strcmp (n, member) == 0)
03577     {
03578       n = dbus_message_get_interface (message);
03579 
03580       if (n == NULL || strcmp (n, iface) == 0)
03581         return TRUE;
03582     }
03583 
03584   return FALSE;
03585 }
03586 
03601 dbus_bool_t
03602 dbus_message_is_method_call (DBusMessage *message,
03603                              const char  *iface,
03604                              const char  *method)
03605 {
03606   _dbus_return_val_if_fail (message != NULL, FALSE);
03607   _dbus_return_val_if_fail (iface != NULL, FALSE);
03608   _dbus_return_val_if_fail (method != NULL, FALSE);
03609   /* don't check that interface/method are valid since it would be
03610    * expensive, and not catch many common errors
03611    */
03612 
03613   return _dbus_message_has_type_interface_member (message,
03614                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03615                                                   iface, method);
03616 }
03617 
03629 dbus_bool_t
03630 dbus_message_is_signal (DBusMessage *message,
03631                         const char  *iface,
03632                         const char  *signal_name)
03633 {
03634   _dbus_return_val_if_fail (message != NULL, FALSE);
03635   _dbus_return_val_if_fail (iface != NULL, FALSE);
03636   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03637   /* don't check that interface/name are valid since it would be
03638    * expensive, and not catch many common errors
03639    */
03640 
03641   return _dbus_message_has_type_interface_member (message,
03642                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03643                                                   iface, signal_name);
03644 }
03645 
03656 dbus_bool_t
03657 dbus_message_is_error (DBusMessage *message,
03658                        const char  *error_name)
03659 {
03660   const char *n;
03661 
03662   _dbus_return_val_if_fail (message != NULL, FALSE);
03663   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03664   /* don't check that error_name is valid since it would be expensive,
03665    * and not catch many common errors
03666    */
03667 
03668   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03669     return FALSE;
03670 
03671   n = dbus_message_get_error_name (message);
03672 
03673   if (n && strcmp (n, error_name) == 0)
03674     return TRUE;
03675   else
03676     return FALSE;
03677 }
03678 
03689 dbus_bool_t
03690 dbus_message_has_destination (DBusMessage  *message,
03691                               const char   *name)
03692 {
03693   const char *s;
03694 
03695   _dbus_return_val_if_fail (message != NULL, FALSE);
03696   _dbus_return_val_if_fail (name != NULL, FALSE);
03697   /* don't check that name is valid since it would be expensive, and
03698    * not catch many common errors
03699    */
03700 
03701   s = dbus_message_get_destination (message);
03702 
03703   if (s && strcmp (s, name) == 0)
03704     return TRUE;
03705   else
03706     return FALSE;
03707 }
03708 
03724 dbus_bool_t
03725 dbus_message_has_sender (DBusMessage  *message,
03726                          const char   *name)
03727 {
03728   const char *s;
03729 
03730   _dbus_return_val_if_fail (message != NULL, FALSE);
03731   _dbus_return_val_if_fail (name != NULL, FALSE);
03732   /* don't check that name is valid since it would be expensive, and
03733    * not catch many common errors
03734    */
03735 
03736   s = dbus_message_get_sender (message);
03737 
03738   if (s && strcmp (s, name) == 0)
03739     return TRUE;
03740   else
03741     return FALSE;
03742 }
03743 
03753 dbus_bool_t
03754 dbus_message_has_signature (DBusMessage   *message,
03755                             const char    *signature)
03756 {
03757   const char *s;
03758 
03759   _dbus_return_val_if_fail (message != NULL, FALSE);
03760   _dbus_return_val_if_fail (signature != NULL, FALSE);
03761   /* don't check that signature is valid since it would be expensive,
03762    * and not catch many common errors
03763    */
03764 
03765   s = dbus_message_get_signature (message);
03766 
03767   if (s && strcmp (s, signature) == 0)
03768     return TRUE;
03769   else
03770     return FALSE;
03771 }
03772 
03795 dbus_bool_t
03796 dbus_set_error_from_message (DBusError   *error,
03797                              DBusMessage *message)
03798 {
03799   const char *str;
03800 
03801   _dbus_return_val_if_fail (message != NULL, FALSE);
03802   _dbus_return_val_if_error_is_set (error, FALSE);
03803 
03804   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03805     return FALSE;
03806 
03807   str = NULL;
03808   dbus_message_get_args (message, NULL,
03809                          DBUS_TYPE_STRING, &str,
03810                          DBUS_TYPE_INVALID);
03811 
03812   dbus_set_error (error, dbus_message_get_error_name (message),
03813                   str ? "%s" : NULL, str);
03814 
03815   return TRUE;
03816 }
03817 
03824 dbus_bool_t
03825 dbus_message_contains_unix_fds(DBusMessage *message)
03826 {
03827 #ifdef HAVE_UNIX_FD_PASSING
03828   _dbus_assert(message);
03829 
03830   return message->n_unix_fds > 0;
03831 #else
03832   return FALSE;
03833 #endif
03834 }
03835 
03854 #define INITIAL_LOADER_DATA_LEN 32
03855 
03862 DBusMessageLoader*
03863 _dbus_message_loader_new (void)
03864 {
03865   DBusMessageLoader *loader;
03866 
03867   loader = dbus_new0 (DBusMessageLoader, 1);
03868   if (loader == NULL)
03869     return NULL;
03870   
03871   loader->refcount = 1;
03872 
03873   loader->corrupted = FALSE;
03874   loader->corruption_reason = DBUS_VALID;
03875 
03876   /* this can be configured by the app, but defaults to the protocol max */
03877   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03878 
03879   /* We set a very relatively conservative default here since due to how
03880   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03881   number of unix fds we want to receive in advance. A
03882   try-and-reallocate loop is not possible. */
03883   loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
03884 
03885   if (!_dbus_string_init (&loader->data))
03886     {
03887       dbus_free (loader);
03888       return NULL;
03889     }
03890 
03891   /* preallocate the buffer for speed, ignore failure */
03892   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03893   _dbus_string_set_length (&loader->data, 0);
03894 
03895 #ifdef HAVE_UNIX_FD_PASSING
03896   loader->unix_fds = NULL;
03897   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03898   loader->unix_fds_outstanding = FALSE;
03899 #endif
03900 
03901   return loader;
03902 }
03903 
03910 DBusMessageLoader *
03911 _dbus_message_loader_ref (DBusMessageLoader *loader)
03912 {
03913   loader->refcount += 1;
03914 
03915   return loader;
03916 }
03917 
03924 void
03925 _dbus_message_loader_unref (DBusMessageLoader *loader)
03926 {
03927   loader->refcount -= 1;
03928   if (loader->refcount == 0)
03929     {
03930 #ifdef HAVE_UNIX_FD_PASSING
03931       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
03932       dbus_free(loader->unix_fds);
03933 #endif
03934       _dbus_list_foreach (&loader->messages,
03935                           (DBusForeachFunction) dbus_message_unref,
03936                           NULL);
03937       _dbus_list_clear (&loader->messages);
03938       _dbus_string_free (&loader->data);
03939       dbus_free (loader);
03940     }
03941 }
03942 
03961 void
03962 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03963                                  DBusString        **buffer)
03964 {
03965   _dbus_assert (!loader->buffer_outstanding);
03966 
03967   *buffer = &loader->data;
03968 
03969   loader->buffer_outstanding = TRUE;
03970 }
03971 
03981 void
03982 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03983                                     DBusString         *buffer)
03984 {
03985   _dbus_assert (loader->buffer_outstanding);
03986   _dbus_assert (buffer == &loader->data);
03987 
03988   loader->buffer_outstanding = FALSE;
03989 }
03990 
04001 dbus_bool_t
04002 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
04003                                   int               **fds,
04004                                   unsigned           *max_n_fds)
04005 {
04006 #ifdef HAVE_UNIX_FD_PASSING
04007   _dbus_assert (!loader->unix_fds_outstanding);
04008 
04009   /* Allocate space where we can put the fds we read. We allocate
04010      space for max_message_unix_fds since this is an
04011      upper limit how many fds can be received within a single
04012      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
04013      we are allocating the maximum possible array size right from the
04014      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
04015      there is no better way. */
04016 
04017   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
04018     {
04019       int *a = dbus_realloc(loader->unix_fds,
04020                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
04021 
04022       if (!a)
04023         return FALSE;
04024 
04025       loader->unix_fds = a;
04026       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
04027     }
04028 
04029   *fds = loader->unix_fds + loader->n_unix_fds;
04030   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
04031 
04032   loader->unix_fds_outstanding = TRUE;
04033   return TRUE;
04034 #else
04035   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
04036   return FALSE;
04037 #endif
04038 }
04039 
04050 void
04051 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
04052                                      int                *fds,
04053                                      unsigned            n_fds)
04054 {
04055 #ifdef HAVE_UNIX_FD_PASSING
04056   _dbus_assert(loader->unix_fds_outstanding);
04057   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
04058   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
04059 
04060   loader->n_unix_fds += n_fds;
04061   loader->unix_fds_outstanding = FALSE;
04062 
04063   if (n_fds && loader->unix_fds_change)
04064     loader->unix_fds_change (loader->unix_fds_change_data);
04065 #else
04066   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
04067 #endif
04068 }
04069 
04070 /*
04071  * FIXME when we move the header out of the buffer, that memmoves all
04072  * buffered messages. Kind of crappy.
04073  *
04074  * Also we copy the header and body, which is kind of crappy.  To
04075  * avoid this, we have to allow header and body to be in a single
04076  * memory block, which is good for messages we read and bad for
04077  * messages we are creating. But we could move_len() the buffer into
04078  * this single memory block, and move_len() will just swap the buffers
04079  * if you're moving the entire buffer replacing the dest string.
04080  *
04081  * We could also have the message loader tell the transport how many
04082  * bytes to read; so it would first ask for some arbitrary number like
04083  * 256, then if the message was incomplete it would use the
04084  * header/body len to ask for exactly the size of the message (or
04085  * blocks the size of a typical kernel buffer for the socket). That
04086  * way we don't get trailing bytes in the buffer that have to be
04087  * memmoved. Though I suppose we also don't have a chance of reading a
04088  * bunch of small messages at once, so the optimization may be stupid.
04089  *
04090  * Another approach would be to keep a "start" index into
04091  * loader->data and only delete it occasionally, instead of after
04092  * each message is loaded.
04093  *
04094  * load_message() returns FALSE if not enough memory OR the loader was corrupted
04095  */
04096 static dbus_bool_t
04097 load_message (DBusMessageLoader *loader,
04098               DBusMessage       *message,
04099               int                byte_order,
04100               int                fields_array_len,
04101               int                header_len,
04102               int                body_len)
04103 {
04104   dbus_bool_t oom;
04105   DBusValidity validity;
04106   const DBusString *type_str;
04107   int type_pos;
04108   DBusValidationMode mode;
04109   dbus_uint32_t n_unix_fds = 0;
04110 
04111   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
04112   
04113   oom = FALSE;
04114 
04115 #if 0
04116   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
04117 #endif
04118 
04119   /* 1. VALIDATE AND COPY OVER HEADER */
04120   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
04121   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
04122 
04123   if (!_dbus_header_load (&message->header,
04124                           mode,
04125                           &validity,
04126                           byte_order,
04127                           fields_array_len,
04128                           header_len,
04129                           body_len,
04130                           &loader->data, 0,
04131                           _dbus_string_get_length (&loader->data)))
04132     {
04133       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
04134 
04135       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
04136          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
04137       _dbus_assert (validity != DBUS_VALID);
04138 
04139       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
04140         oom = TRUE;
04141       else
04142         {
04143           loader->corrupted = TRUE;
04144           loader->corruption_reason = validity;
04145         }
04146       goto failed;
04147     }
04148 
04149   _dbus_assert (validity == DBUS_VALID);
04150 
04151   /* 2. VALIDATE BODY */
04152   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04153     {
04154       get_const_signature (&message->header, &type_str, &type_pos);
04155       
04156       /* Because the bytes_remaining arg is NULL, this validates that the
04157        * body is the right length
04158        */
04159       validity = _dbus_validate_body_with_reason (type_str,
04160                                                   type_pos,
04161                                                   byte_order,
04162                                                   NULL,
04163                                                   &loader->data,
04164                                                   header_len,
04165                                                   body_len);
04166       if (validity != DBUS_VALID)
04167         {
04168           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04169 
04170           loader->corrupted = TRUE;
04171           loader->corruption_reason = validity;
04172           
04173           goto failed;
04174         }
04175     }
04176 
04177   /* 3. COPY OVER UNIX FDS */
04178   _dbus_header_get_field_basic(&message->header,
04179                                DBUS_HEADER_FIELD_UNIX_FDS,
04180                                DBUS_TYPE_UINT32,
04181                                &n_unix_fds);
04182 
04183 #ifdef HAVE_UNIX_FD_PASSING
04184 
04185   if (n_unix_fds > loader->n_unix_fds)
04186     {
04187       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04188                     n_unix_fds, loader->n_unix_fds);
04189 
04190       loader->corrupted = TRUE;
04191       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04192       goto failed;
04193     }
04194 
04195   /* If this was a recycled message there might still be
04196      some memory allocated for the fds */
04197   dbus_free(message->unix_fds);
04198 
04199   if (n_unix_fds > 0)
04200     {
04201       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04202       if (message->unix_fds == NULL)
04203         {
04204           _dbus_verbose ("Failed to allocate file descriptor array\n");
04205           oom = TRUE;
04206           goto failed;
04207         }
04208 
04209       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04210       loader->n_unix_fds -= n_unix_fds;
04211       memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
04212 
04213       if (loader->unix_fds_change)
04214         loader->unix_fds_change (loader->unix_fds_change_data);
04215     }
04216   else
04217     message->unix_fds = NULL;
04218 
04219 #else
04220 
04221   if (n_unix_fds > 0)
04222     {
04223       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04224                      "but that's not supported on our platform, disconnecting.\n");
04225 
04226       loader->corrupted = TRUE;
04227       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04228       goto failed;
04229     }
04230 
04231 #endif
04232 
04233   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04234 
04235   if (!_dbus_list_append (&loader->messages, message))
04236     {
04237       _dbus_verbose ("Failed to append new message to loader queue\n");
04238       oom = TRUE;
04239       goto failed;
04240     }
04241 
04242   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04243   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04244                 (header_len + body_len));
04245 
04246   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04247     {
04248       _dbus_verbose ("Failed to move body into new message\n");
04249       oom = TRUE;
04250       goto failed;
04251     }
04252 
04253   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04254 
04255   /* don't waste more than 2k of memory */
04256   _dbus_string_compact (&loader->data, 2048);
04257 
04258   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04259   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04260 
04261   _dbus_verbose ("Loaded message %p\n", message);
04262 
04263   _dbus_assert (!oom);
04264   _dbus_assert (!loader->corrupted);
04265   _dbus_assert (loader->messages != NULL);
04266   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04267 
04268   return TRUE;
04269 
04270  failed:
04271 
04272   /* Clean up */
04273 
04274   /* does nothing if the message isn't in the list */
04275   _dbus_list_remove_last (&loader->messages, message);
04276   
04277   if (oom)
04278     _dbus_assert (!loader->corrupted);
04279   else
04280     _dbus_assert (loader->corrupted);
04281 
04282   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04283 
04284   return FALSE;
04285 }
04286 
04301 dbus_bool_t
04302 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04303 {
04304   while (!loader->corrupted &&
04305          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04306     {
04307       DBusValidity validity;
04308       int byte_order, fields_array_len, header_len, body_len;
04309 
04310       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04311                                                &validity,
04312                                                &byte_order,
04313                                                &fields_array_len,
04314                                                &header_len,
04315                                                &body_len,
04316                                                &loader->data, 0,
04317                                                _dbus_string_get_length (&loader->data)))
04318         {
04319           DBusMessage *message;
04320 
04321           _dbus_assert (validity == DBUS_VALID);
04322 
04323           message = dbus_message_new_empty_header ();
04324           if (message == NULL)
04325             return FALSE;
04326 
04327           if (!load_message (loader, message,
04328                              byte_order, fields_array_len,
04329                              header_len, body_len))
04330             {
04331               dbus_message_unref (message);
04332               /* load_message() returns false if corrupted or OOM; if
04333                * corrupted then return TRUE for not OOM
04334                */
04335               return loader->corrupted;
04336             }
04337 
04338           _dbus_assert (loader->messages != NULL);
04339           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04340         }
04341       else
04342         {
04343           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04344                          validity);
04345           if (validity != DBUS_VALID)
04346             {
04347               loader->corrupted = TRUE;
04348               loader->corruption_reason = validity;
04349             }
04350           return TRUE;
04351         }
04352     }
04353 
04354   return TRUE;
04355 }
04356 
04364 DBusMessage*
04365 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04366 {
04367   if (loader->messages)
04368     return loader->messages->data;
04369   else
04370     return NULL;
04371 }
04372 
04381 DBusMessage*
04382 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04383 {
04384   return _dbus_list_pop_first (&loader->messages);
04385 }
04386 
04395 DBusList*
04396 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04397 {
04398   return _dbus_list_pop_first_link (&loader->messages);
04399 }
04400 
04407 void
04408 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04409                                            DBusList           *link)
04410 {
04411   _dbus_list_prepend_link (&loader->messages, link);
04412 }
04413 
04423 dbus_bool_t
04424 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04425 {
04426   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04427                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04428   return loader->corrupted;
04429 }
04430 
04437 DBusValidity
04438 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04439 {
04440   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04441                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04442 
04443   return loader->corruption_reason;
04444 }
04445 
04452 void
04453 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04454                                            long                size)
04455 {
04456   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04457     {
04458       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04459                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04460       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04461     }
04462   loader->max_message_size = size;
04463 }
04464 
04471 long
04472 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04473 {
04474   return loader->max_message_size;
04475 }
04476 
04483 void
04484 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04485                                                long                n)
04486 {
04487   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04488     {
04489       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04490                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04491       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04492     }
04493   loader->max_message_unix_fds = n;
04494 }
04495 
04502 long
04503 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04504 {
04505   return loader->max_message_unix_fds;
04506 }
04507 
04513 int
04514 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
04515 {
04516 #ifdef HAVE_UNIX_FD_PASSING
04517   return loader->n_unix_fds;
04518 #else
04519   return 0;
04520 #endif
04521 }
04522 
04531 void
04532 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
04533                                                void (* callback) (void *),
04534                                                void *data)
04535 {
04536 #ifdef HAVE_UNIX_FD_PASSING
04537   loader->unix_fds_change = callback;
04538   loader->unix_fds_change_data = data;
04539 #endif
04540 }
04541 
04542 static DBusDataSlotAllocator slot_allocator =
04543   _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
04544 
04559 dbus_bool_t
04560 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04561 {
04562   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04563                                           slot_p);
04564 }
04565 
04577 void
04578 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04579 {
04580   _dbus_return_if_fail (*slot_p >= 0);
04581 
04582   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04583 }
04584 
04598 dbus_bool_t
04599 dbus_message_set_data (DBusMessage     *message,
04600                        dbus_int32_t     slot,
04601                        void            *data,
04602                        DBusFreeFunction free_data_func)
04603 {
04604   DBusFreeFunction old_free_func;
04605   void *old_data;
04606   dbus_bool_t retval;
04607 
04608   _dbus_return_val_if_fail (message != NULL, FALSE);
04609   _dbus_return_val_if_fail (slot >= 0, FALSE);
04610 
04611   retval = _dbus_data_slot_list_set (&slot_allocator,
04612                                      &message->slot_list,
04613                                      slot, data, free_data_func,
04614                                      &old_free_func, &old_data);
04615 
04616   if (retval)
04617     {
04618       /* Do the actual free outside the message lock */
04619       if (old_free_func)
04620         (* old_free_func) (old_data);
04621     }
04622 
04623   return retval;
04624 }
04625 
04634 void*
04635 dbus_message_get_data (DBusMessage   *message,
04636                        dbus_int32_t   slot)
04637 {
04638   void *res;
04639 
04640   _dbus_return_val_if_fail (message != NULL, NULL);
04641 
04642   res = _dbus_data_slot_list_get (&slot_allocator,
04643                                   &message->slot_list,
04644                                   slot);
04645 
04646   return res;
04647 }
04648 
04662 int
04663 dbus_message_type_from_string (const char *type_str)
04664 {
04665   if (strcmp (type_str, "method_call") == 0)
04666     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04667   if (strcmp (type_str, "method_return") == 0)
04668     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04669   else if (strcmp (type_str, "signal") == 0)
04670     return DBUS_MESSAGE_TYPE_SIGNAL;
04671   else if (strcmp (type_str, "error") == 0)
04672     return DBUS_MESSAGE_TYPE_ERROR;
04673   else
04674     return DBUS_MESSAGE_TYPE_INVALID;
04675 }
04676 
04690 const char *
04691 dbus_message_type_to_string (int type)
04692 {
04693   switch (type)
04694     {
04695     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04696       return "method_call";
04697     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04698       return "method_return";
04699     case DBUS_MESSAGE_TYPE_SIGNAL:
04700       return "signal";
04701     case DBUS_MESSAGE_TYPE_ERROR:
04702       return "error";
04703     default:
04704       return "invalid";
04705     }
04706 }
04707 
04720 dbus_bool_t
04721 dbus_message_marshal (DBusMessage  *msg,
04722                       char        **marshalled_data_p,
04723                       int          *len_p)
04724 {
04725   DBusString tmp;
04726   dbus_bool_t was_locked;
04727 
04728   _dbus_return_val_if_fail (msg != NULL, FALSE);
04729   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04730   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04731   
04732   if (!_dbus_string_init (&tmp))
04733     return FALSE;
04734 
04735   /* Ensure the message is locked, to ensure the length header is filled in. */
04736   was_locked = msg->locked;
04737 
04738   if (!was_locked)
04739     dbus_message_lock (msg);
04740 
04741   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04742     goto fail;
04743 
04744   *len_p = _dbus_string_get_length (&tmp);
04745 
04746   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04747     goto fail;
04748 
04749   *len_p = _dbus_string_get_length (&tmp);
04750 
04751   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04752     goto fail;
04753 
04754   _dbus_string_free (&tmp);
04755 
04756   if (!was_locked)
04757     msg->locked = FALSE;
04758 
04759   return TRUE;
04760 
04761  fail:
04762   _dbus_string_free (&tmp);
04763 
04764   if (!was_locked)
04765     msg->locked = FALSE;
04766 
04767   return FALSE;
04768 }
04769 
04782 DBusMessage *
04783 dbus_message_demarshal (const char *str,
04784                         int         len,
04785                         DBusError  *error)
04786 {
04787   DBusMessageLoader *loader;
04788   DBusString *buffer;
04789   DBusMessage *msg;
04790 
04791   _dbus_return_val_if_fail (str != NULL, NULL);
04792 
04793   loader = _dbus_message_loader_new ();
04794 
04795   if (loader == NULL)
04796     return NULL;
04797 
04798   _dbus_message_loader_get_buffer (loader, &buffer);
04799 
04800   if (!_dbus_string_append_len (buffer, str, len))
04801     goto fail_oom;
04802 
04803   _dbus_message_loader_return_buffer (loader, buffer);
04804 
04805   if (!_dbus_message_loader_queue_messages (loader))
04806     goto fail_oom;
04807 
04808   if (_dbus_message_loader_get_is_corrupted (loader))
04809     goto fail_corrupt;
04810 
04811   msg = _dbus_message_loader_pop_message (loader);
04812 
04813   if (!msg)
04814     goto fail_oom;
04815 
04816   _dbus_message_loader_unref (loader);
04817   return msg;
04818 
04819  fail_corrupt:
04820   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04821                   _dbus_validity_to_error_message (loader->corruption_reason));
04822   _dbus_message_loader_unref (loader);
04823   return NULL;
04824 
04825  fail_oom:
04826   _DBUS_SET_OOM (error);
04827   _dbus_message_loader_unref (loader);
04828   return NULL;
04829 }
04830 
04843 int 
04844 dbus_message_demarshal_bytes_needed(const char *buf, 
04845                                     int         len)
04846 {
04847   DBusString str;
04848   int byte_order, fields_array_len, header_len, body_len;
04849   DBusValidity validity = DBUS_VALID;
04850   int have_message;
04851 
04852   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04853     return 0;
04854 
04855   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04856     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04857   _dbus_string_init_const_len (&str, buf, len);
04858   
04859   validity = DBUS_VALID;
04860   have_message
04861     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04862                                           &validity, &byte_order,
04863                                           &fields_array_len,
04864                                           &header_len,
04865                                           &body_len,
04866                                           &str, 0,
04867                                           len);
04868   _dbus_string_free (&str);
04869 
04870   if (validity == DBUS_VALID)
04871     {
04872       _dbus_assert (have_message || (header_len + body_len) > len);
04873       (void) have_message; /* unused unless asserting */
04874       return header_len + body_len;
04875     }
04876   else
04877     {
04878       return -1; /* broken! */
04879     }
04880 }
04881 
04884 /* tests in dbus-message-util.c */