D-Bus  1.4.10
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-unix.h"
00039 #endif
00040 
00041 #include <string.h>
00042 
00043 static void dbus_message_finalize (DBusMessage *message);
00044 
00055 /* Not thread locked, but strictly const/read-only so should be OK
00056  */
00058 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
00059 
00060 /* these have wacky values to help trap uninitialized iterators;
00061  * but has to fit in 3 bits
00062  */
00063 enum {
00064   DBUS_MESSAGE_ITER_TYPE_READER = 3,
00065   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
00066 };
00067 
00069 typedef struct DBusMessageRealIter DBusMessageRealIter;
00070 
00076 struct DBusMessageRealIter
00077 {
00078   DBusMessage *message; 
00079   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 
00080   dbus_uint32_t iter_type : 3;      
00081   dbus_uint32_t sig_refcount : 8;   
00082   union
00083   {
00084     DBusTypeWriter writer; 
00085     DBusTypeReader reader; 
00086   } u; 
00087 };
00088 
00089 static void
00090 get_const_signature (DBusHeader        *header,
00091                      const DBusString **type_str_p,
00092                      int               *type_pos_p)
00093 {
00094   if (_dbus_header_get_field_raw (header,
00095                                   DBUS_HEADER_FIELD_SIGNATURE,
00096                                   type_str_p,
00097                                   type_pos_p))
00098     {
00099       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00100     }
00101   else
00102     {
00103       *type_str_p = &_dbus_empty_signature_str;
00104       *type_pos_p = 0;
00105     }
00106 }
00107 
00113 static void
00114 _dbus_message_byteswap (DBusMessage *message)
00115 {
00116   const DBusString *type_str;
00117   int type_pos;
00118   
00119   if (message->byte_order == DBUS_COMPILER_BYTE_ORDER)
00120     return;
00121 
00122   _dbus_verbose ("Swapping message into compiler byte order\n");
00123   
00124   get_const_signature (&message->header, &type_str, &type_pos);
00125   
00126   _dbus_marshal_byteswap (type_str, type_pos,
00127                           message->byte_order,
00128                           DBUS_COMPILER_BYTE_ORDER,
00129                           &message->body, 0);
00130 
00131   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00132   
00133   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00134 }
00135 
00142 #define ensure_byte_order(message)                      \
00143  if (message->byte_order != DBUS_COMPILER_BYTE_ORDER)   \
00144    _dbus_message_byteswap (message)
00145 
00156 void
00157 _dbus_message_get_network_data (DBusMessage          *message,
00158                                 const DBusString    **header,
00159                                 const DBusString    **body)
00160 {
00161   _dbus_assert (message->locked);
00162 
00163   *header = &message->header.data;
00164   *body = &message->body;
00165 }
00166 
00176 void _dbus_message_get_unix_fds(DBusMessage *message,
00177                                 const int  **fds,
00178                                 unsigned    *n_fds)
00179 {
00180   _dbus_assert (message->locked);
00181 
00182 #ifdef HAVE_UNIX_FD_PASSING
00183   *fds = message->unix_fds;
00184   *n_fds = message->n_unix_fds;
00185 #else
00186   *fds = NULL;
00187   *n_fds = 0;
00188 #endif
00189 }
00190 
00202 void 
00203 dbus_message_set_serial (DBusMessage   *message,
00204                          dbus_uint32_t  serial)
00205 {
00206   _dbus_return_if_fail (message != NULL);
00207   _dbus_return_if_fail (!message->locked);
00208 
00209   _dbus_header_set_serial (&message->header, serial);
00210 }
00211 
00223 void
00224 _dbus_message_add_counter_link (DBusMessage  *message,
00225                                 DBusList     *link)
00226 {
00227   /* right now we don't recompute the delta when message
00228    * size changes, and that's OK for current purposes
00229    * I think, but could be important to change later.
00230    * Do recompute it whenever there are no outstanding counters,
00231    * since it's basically free.
00232    */
00233   if (message->counters == NULL)
00234     {
00235       message->size_counter_delta =
00236         _dbus_string_get_length (&message->header.data) +
00237         _dbus_string_get_length (&message->body);
00238 
00239 #ifdef HAVE_UNIX_FD_PASSING
00240       message->unix_fd_counter_delta = message->n_unix_fds;
00241 #endif
00242 
00243 #if 0
00244       _dbus_verbose ("message has size %ld\n",
00245                      message->size_counter_delta);
00246 #endif
00247     }
00248 
00249   _dbus_list_append_link (&message->counters, link);
00250 
00251   _dbus_counter_adjust_size (link->data, message->size_counter_delta);
00252 
00253 #ifdef HAVE_UNIX_FD_PASSING
00254   _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
00255 #endif
00256 }
00257 
00267 dbus_bool_t
00268 _dbus_message_add_counter (DBusMessage *message,
00269                            DBusCounter *counter)
00270 {
00271   DBusList *link;
00272 
00273   link = _dbus_list_alloc_link (counter);
00274   if (link == NULL)
00275     return FALSE;
00276 
00277   _dbus_counter_ref (counter);
00278   _dbus_message_add_counter_link (message, link);
00279 
00280   return TRUE;
00281 }
00282 
00291 void
00292 _dbus_message_remove_counter (DBusMessage  *message,
00293                               DBusCounter  *counter,
00294                               DBusList    **link_return)
00295 {
00296   DBusList *link;
00297 
00298   link = _dbus_list_find_last (&message->counters,
00299                                counter);
00300   _dbus_assert (link != NULL);
00301 
00302   _dbus_list_unlink (&message->counters,
00303                      link);
00304   if (link_return)
00305     *link_return = link;
00306   else
00307     _dbus_list_free_link (link);
00308 
00309   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00310 
00311 #ifdef HAVE_UNIX_FD_PASSING
00312   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00313 #endif
00314 
00315   _dbus_counter_unref (counter);
00316 }
00317 
00328 void
00329 dbus_message_lock (DBusMessage  *message)
00330 {
00331   if (!message->locked)
00332     {
00333       _dbus_header_update_lengths (&message->header,
00334                                    _dbus_string_get_length (&message->body));
00335 
00336       /* must have a signature if you have a body */
00337       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00338                     dbus_message_get_signature (message) != NULL);
00339 
00340       message->locked = TRUE;
00341     }
00342 }
00343 
00344 static dbus_bool_t
00345 set_or_delete_string_field (DBusMessage *message,
00346                             int          field,
00347                             int          typecode,
00348                             const char  *value)
00349 {
00350   if (value == NULL)
00351     return _dbus_header_delete_field (&message->header, field);
00352   else
00353     return _dbus_header_set_field_basic (&message->header,
00354                                          field,
00355                                          typecode,
00356                                          &value);
00357 }
00358 
00359 #if 0
00360 /* Probably we don't need to use this */
00384 static dbus_bool_t
00385 _dbus_message_set_signature (DBusMessage *message,
00386                              const char  *signature)
00387 {
00388   _dbus_return_val_if_fail (message != NULL, FALSE);
00389   _dbus_return_val_if_fail (!message->locked, FALSE);
00390   _dbus_return_val_if_fail (signature == NULL ||
00391                             _dbus_check_is_valid_signature (signature));
00392   /* can't delete the signature if you have a message body */
00393   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00394                             signature != NULL);
00395 
00396   return set_or_delete_string_field (message,
00397                                      DBUS_HEADER_FIELD_SIGNATURE,
00398                                      DBUS_TYPE_SIGNATURE,
00399                                      signature);
00400 }
00401 #endif
00402 
00403 /* Message Cache
00404  *
00405  * We cache some DBusMessage to reduce the overhead of allocating
00406  * them.  In my profiling this consistently made about an 8%
00407  * difference.  It avoids the malloc for the message, the malloc for
00408  * the slot list, the malloc for the header string and body string,
00409  * and the associated free() calls. It does introduce another global
00410  * lock which could be a performance issue in certain cases.
00411  *
00412  * For the echo client/server the round trip time goes from around
00413  * .000077 to .000069 with the message cache on my laptop. The sysprof
00414  * change is as follows (numbers are cumulative percentage):
00415  *
00416  *  with message cache implemented as array as it is now (0.000069 per):
00417  *    new_empty_header           1.46
00418  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00419  *      mutex_unlock             0.25
00420  *      self                     0.41
00421  *    unref                      2.24
00422  *      self                     0.68
00423  *      list_clear               0.43
00424  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00425  *      mutex_unlock             0.25
00426  *
00427  *  with message cache implemented as list (0.000070 per roundtrip):
00428  *    new_empty_header           2.72
00429  *      list_pop_first           1.88
00430  *    unref                      3.3
00431  *      list_prepend             1.63
00432  *
00433  * without cache (0.000077 per roundtrip):
00434  *    new_empty_header           6.7
00435  *      string_init_preallocated 3.43
00436  *        dbus_malloc            2.43
00437  *      dbus_malloc0             2.59
00438  *
00439  *    unref                      4.02
00440  *      string_free              1.82
00441  *        dbus_free              1.63
00442  *      dbus_free                0.71
00443  *
00444  * If you implement the message_cache with a list, the primary reason
00445  * it's slower is that you add another thread lock (on the DBusList
00446  * mempool).
00447  */
00448 
00450 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00451 
00453 #define MAX_MESSAGE_CACHE_SIZE    5
00454 
00455 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00456 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00457 static int message_cache_count = 0;
00458 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00459 
00460 static void
00461 dbus_message_cache_shutdown (void *data)
00462 {
00463   int i;
00464 
00465   _DBUS_LOCK (message_cache);
00466 
00467   i = 0;
00468   while (i < MAX_MESSAGE_CACHE_SIZE)
00469     {
00470       if (message_cache[i])
00471         dbus_message_finalize (message_cache[i]);
00472 
00473       ++i;
00474     }
00475 
00476   message_cache_count = 0;
00477   message_cache_shutdown_registered = FALSE;
00478 
00479   _DBUS_UNLOCK (message_cache);
00480 }
00481 
00489 static DBusMessage*
00490 dbus_message_get_cached (void)
00491 {
00492   DBusMessage *message;
00493   int i;
00494 
00495   message = NULL;
00496 
00497   _DBUS_LOCK (message_cache);
00498 
00499   _dbus_assert (message_cache_count >= 0);
00500 
00501   if (message_cache_count == 0)
00502     {
00503       _DBUS_UNLOCK (message_cache);
00504       return NULL;
00505     }
00506 
00507   /* This is not necessarily true unless count > 0, and
00508    * message_cache is uninitialized until the shutdown is
00509    * registered
00510    */
00511   _dbus_assert (message_cache_shutdown_registered);
00512 
00513   i = 0;
00514   while (i < MAX_MESSAGE_CACHE_SIZE)
00515     {
00516       if (message_cache[i])
00517         {
00518           message = message_cache[i];
00519           message_cache[i] = NULL;
00520           message_cache_count -= 1;
00521           break;
00522         }
00523       ++i;
00524     }
00525   _dbus_assert (message_cache_count >= 0);
00526   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00527   _dbus_assert (message != NULL);
00528 
00529   _dbus_assert (message->refcount.value == 0);
00530   _dbus_assert (message->counters == NULL);
00531   
00532   _DBUS_UNLOCK (message_cache);
00533 
00534   return message;
00535 }
00536 
00537 #ifdef HAVE_UNIX_FD_PASSING
00538 static void
00539 close_unix_fds(int *fds, unsigned *n_fds)
00540 {
00541   DBusError e;
00542   int i;
00543 
00544   if (*n_fds <= 0)
00545     return;
00546 
00547   dbus_error_init(&e);
00548 
00549   for (i = 0; i < *n_fds; i++)
00550     {
00551       if (!_dbus_close(fds[i], &e))
00552         {
00553           _dbus_warn("Failed to close file descriptor: %s\n", e.message);
00554           dbus_error_free(&e);
00555         }
00556     }
00557 
00558   *n_fds = 0;
00559 
00560   /* We don't free the array here, in case we can recycle it later */
00561 }
00562 #endif
00563 
00564 static void
00565 free_counter (void *element,
00566               void *data)
00567 {
00568   DBusCounter *counter = element;
00569   DBusMessage *message = data;
00570 
00571   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00572 #ifdef HAVE_UNIX_FD_PASSING
00573   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00574 #endif
00575 
00576   _dbus_counter_unref (counter);
00577 }
00578 
00584 static void
00585 dbus_message_cache_or_finalize (DBusMessage *message)
00586 {
00587   dbus_bool_t was_cached;
00588   int i;
00589   
00590   _dbus_assert (message->refcount.value == 0);
00591 
00592   /* This calls application code and has to be done first thing
00593    * without holding the lock
00594    */
00595   _dbus_data_slot_list_clear (&message->slot_list);
00596 
00597   _dbus_list_foreach (&message->counters,
00598                       free_counter, message);
00599   _dbus_list_clear (&message->counters);
00600 
00601 #ifdef HAVE_UNIX_FD_PASSING
00602   close_unix_fds(message->unix_fds, &message->n_unix_fds);
00603 #endif
00604 
00605   was_cached = FALSE;
00606 
00607   _DBUS_LOCK (message_cache);
00608 
00609   if (!message_cache_shutdown_registered)
00610     {
00611       _dbus_assert (message_cache_count == 0);
00612 
00613       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00614         goto out;
00615 
00616       i = 0;
00617       while (i < MAX_MESSAGE_CACHE_SIZE)
00618         {
00619           message_cache[i] = NULL;
00620           ++i;
00621         }
00622 
00623       message_cache_shutdown_registered = TRUE;
00624     }
00625 
00626   _dbus_assert (message_cache_count >= 0);
00627 
00628   if ((_dbus_string_get_length (&message->header.data) +
00629        _dbus_string_get_length (&message->body)) >
00630       MAX_MESSAGE_SIZE_TO_CACHE)
00631     goto out;
00632 
00633   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00634     goto out;
00635 
00636   /* Find empty slot */
00637   i = 0;
00638   while (message_cache[i] != NULL)
00639     ++i;
00640 
00641   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00642 
00643   _dbus_assert (message_cache[i] == NULL);
00644   message_cache[i] = message;
00645   message_cache_count += 1;
00646   was_cached = TRUE;
00647 #ifndef DBUS_DISABLE_CHECKS
00648   message->in_cache = TRUE;
00649 #endif
00650 
00651  out:
00652   _dbus_assert (message->refcount.value == 0);
00653   
00654   _DBUS_UNLOCK (message_cache);
00655   
00656   if (!was_cached)
00657     dbus_message_finalize (message);
00658 }
00659 
00660 #ifndef DBUS_DISABLE_CHECKS
00661 static dbus_bool_t
00662 _dbus_message_iter_check (DBusMessageRealIter *iter)
00663 {
00664   if (iter == NULL)
00665     {
00666       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00667       return FALSE;
00668     }
00669 
00670   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00671     {
00672       if (iter->u.reader.byte_order != iter->message->byte_order)
00673         {
00674           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00675           return FALSE;
00676         }
00677       /* because we swap the message into compiler order when you init an iter */
00678       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00679     }
00680   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00681     {
00682       if (iter->u.writer.byte_order != iter->message->byte_order)
00683         {
00684           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00685           return FALSE;
00686         }
00687       /* because we swap the message into compiler order when you init an iter */
00688       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00689     }
00690   else
00691     {
00692       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00693       return FALSE;
00694     }
00695 
00696   if (iter->changed_stamp != iter->message->changed_stamp)
00697     {
00698       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00699       return FALSE;
00700     }
00701 
00702   return TRUE;
00703 }
00704 #endif /* DBUS_DISABLE_CHECKS */
00705 
00720 dbus_bool_t
00721 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00722                                     DBusError       *error,
00723                                     int              first_arg_type,
00724                                     va_list          var_args)
00725 {
00726   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00727   int spec_type, msg_type, i;
00728   dbus_bool_t retval;
00729 
00730   _dbus_assert (_dbus_message_iter_check (real));
00731 
00732   retval = FALSE;
00733 
00734   spec_type = first_arg_type;
00735   i = 0;
00736 
00737   while (spec_type != DBUS_TYPE_INVALID)
00738     {
00739       msg_type = dbus_message_iter_get_arg_type (iter);
00740 
00741       if (msg_type != spec_type)
00742         {
00743           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00744                           "Argument %d is specified to be of type \"%s\", but "
00745                           "is actually of type \"%s\"\n", i,
00746                           _dbus_type_to_string (spec_type),
00747                           _dbus_type_to_string (msg_type));
00748 
00749           goto out;
00750         }
00751 
00752       if (spec_type == DBUS_TYPE_UNIX_FD)
00753         {
00754 #ifdef HAVE_UNIX_FD_PASSING
00755           DBusBasicValue idx;
00756           int *pfd, nfd;
00757 
00758           pfd = va_arg (var_args, int*);
00759           _dbus_assert(pfd);
00760 
00761           _dbus_type_reader_read_basic(&real->u.reader, &idx);
00762 
00763           if (idx.u32 >= real->message->n_unix_fds)
00764             {
00765               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
00766                               "Message refers to file descriptor at index %i,"
00767                               "but has only %i descriptors attached.\n",
00768                               idx.u32,
00769                               real->message->n_unix_fds);
00770               goto out;
00771             }
00772 
00773           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
00774             goto out;
00775 
00776           *pfd = nfd;
00777 #else
00778           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00779                           "Platform does not support file desciptor passing.\n");
00780           goto out;
00781 #endif
00782         }
00783       else if (dbus_type_is_basic (spec_type))
00784         {
00785           DBusBasicValue *ptr;
00786 
00787           ptr = va_arg (var_args, DBusBasicValue*);
00788 
00789           _dbus_assert (ptr != NULL);
00790 
00791           _dbus_type_reader_read_basic (&real->u.reader,
00792                                         ptr);
00793         }
00794       else if (spec_type == DBUS_TYPE_ARRAY)
00795         {
00796           int element_type;
00797           int spec_element_type;
00798           const DBusBasicValue **ptr;
00799           int *n_elements_p;
00800           DBusTypeReader array;
00801 
00802           spec_element_type = va_arg (var_args, int);
00803           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00804 
00805           if (spec_element_type != element_type)
00806             {
00807               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00808                               "Argument %d is specified to be an array of \"%s\", but "
00809                               "is actually an array of \"%s\"\n",
00810                               i,
00811                               _dbus_type_to_string (spec_element_type),
00812                               _dbus_type_to_string (element_type));
00813 
00814               goto out;
00815             }
00816 
00817           if (dbus_type_is_fixed (spec_element_type) &&
00818               element_type != DBUS_TYPE_UNIX_FD)
00819             {
00820               ptr = va_arg (var_args, const DBusBasicValue**);
00821               n_elements_p = va_arg (var_args, int*);
00822 
00823               _dbus_assert (ptr != NULL);
00824               _dbus_assert (n_elements_p != NULL);
00825 
00826               _dbus_type_reader_recurse (&real->u.reader, &array);
00827 
00828               _dbus_type_reader_read_fixed_multi (&array,
00829                                                   (void *) ptr, n_elements_p);
00830             }
00831           else if (spec_element_type == DBUS_TYPE_STRING ||
00832                    spec_element_type == DBUS_TYPE_SIGNATURE ||
00833                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
00834             {
00835               char ***str_array_p;
00836               int n_elements;
00837               char **str_array;
00838 
00839               str_array_p = va_arg (var_args, char***);
00840               n_elements_p = va_arg (var_args, int*);
00841 
00842               _dbus_assert (str_array_p != NULL);
00843               _dbus_assert (n_elements_p != NULL);
00844 
00845               /* Count elements in the array */
00846               _dbus_type_reader_recurse (&real->u.reader, &array);
00847 
00848               n_elements = 0;
00849               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00850                 {
00851                   ++n_elements;
00852                   _dbus_type_reader_next (&array);
00853                 }
00854 
00855               str_array = dbus_new0 (char*, n_elements + 1);
00856               if (str_array == NULL)
00857                 {
00858                   _DBUS_SET_OOM (error);
00859                   goto out;
00860                 }
00861 
00862               /* Now go through and dup each string */
00863               _dbus_type_reader_recurse (&real->u.reader, &array);
00864 
00865               i = 0;
00866               while (i < n_elements)
00867                 {
00868                   const char *s;
00869                   _dbus_type_reader_read_basic (&array,
00870                                                 (void *) &s);
00871                   
00872                   str_array[i] = _dbus_strdup (s);
00873                   if (str_array[i] == NULL)
00874                     {
00875                       dbus_free_string_array (str_array);
00876                       _DBUS_SET_OOM (error);
00877                       goto out;
00878                     }
00879                   
00880                   ++i;
00881                   
00882                   if (!_dbus_type_reader_next (&array))
00883                     _dbus_assert (i == n_elements);
00884                 }
00885 
00886               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00887               _dbus_assert (i == n_elements);
00888               _dbus_assert (str_array[i] == NULL);
00889 
00890               *str_array_p = str_array;
00891               *n_elements_p = n_elements;
00892             }
00893 #ifndef DBUS_DISABLE_CHECKS
00894           else
00895             {
00896               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00897                           _DBUS_FUNCTION_NAME);
00898               goto out;
00899             }
00900 #endif
00901         }
00902 #ifndef DBUS_DISABLE_CHECKS
00903       else
00904         {
00905           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00906                       _DBUS_FUNCTION_NAME);
00907           goto out;
00908         }
00909 #endif
00910 
00911       spec_type = va_arg (var_args, int);
00912       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00913         {
00914           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00915                           "Message has only %d arguments, but more were expected", i);
00916           goto out;
00917         }
00918 
00919       i++;
00920     }
00921 
00922   retval = TRUE;
00923 
00924  out:
00925 
00926   return retval;
00927 }
00928 
00987 dbus_uint32_t
00988 dbus_message_get_serial (DBusMessage *message)
00989 {
00990   _dbus_return_val_if_fail (message != NULL, 0);
00991 
00992   return _dbus_header_get_serial (&message->header);
00993 }
00994 
01003 dbus_bool_t
01004 dbus_message_set_reply_serial (DBusMessage   *message,
01005                                dbus_uint32_t  reply_serial)
01006 {
01007   _dbus_return_val_if_fail (message != NULL, FALSE);
01008   _dbus_return_val_if_fail (!message->locked, FALSE);
01009   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01010 
01011   return _dbus_header_set_field_basic (&message->header,
01012                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01013                                        DBUS_TYPE_UINT32,
01014                                        &reply_serial);
01015 }
01016 
01023 dbus_uint32_t
01024 dbus_message_get_reply_serial  (DBusMessage *message)
01025 {
01026   dbus_uint32_t v_UINT32;
01027 
01028   _dbus_return_val_if_fail (message != NULL, 0);
01029 
01030   if (_dbus_header_get_field_basic (&message->header,
01031                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01032                                     DBUS_TYPE_UINT32,
01033                                     &v_UINT32))
01034     return v_UINT32;
01035   else
01036     return 0;
01037 }
01038 
01039 static void
01040 dbus_message_finalize (DBusMessage *message)
01041 {
01042   _dbus_assert (message->refcount.value == 0);
01043 
01044   /* This calls application callbacks! */
01045   _dbus_data_slot_list_free (&message->slot_list);
01046 
01047   _dbus_list_foreach (&message->counters,
01048                       free_counter, message);
01049   _dbus_list_clear (&message->counters);
01050 
01051   _dbus_header_free (&message->header);
01052   _dbus_string_free (&message->body);
01053 
01054 #ifdef HAVE_UNIX_FD_PASSING
01055   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01056   dbus_free(message->unix_fds);
01057 #endif
01058 
01059   _dbus_assert (message->refcount.value == 0);
01060   
01061   dbus_free (message);
01062 }
01063 
01064 static DBusMessage*
01065 dbus_message_new_empty_header (void)
01066 {
01067   DBusMessage *message;
01068   dbus_bool_t from_cache;
01069 
01070   message = dbus_message_get_cached ();
01071 
01072   if (message != NULL)
01073     {
01074       from_cache = TRUE;
01075     }
01076   else
01077     {
01078       from_cache = FALSE;
01079       message = dbus_new (DBusMessage, 1);
01080       if (message == NULL)
01081         return NULL;
01082 #ifndef DBUS_DISABLE_CHECKS
01083       message->generation = _dbus_current_generation;
01084 #endif
01085 
01086 #ifdef HAVE_UNIX_FD_PASSING
01087       message->unix_fds = NULL;
01088       message->n_unix_fds_allocated = 0;
01089 #endif
01090     }
01091   
01092   message->refcount.value = 1;
01093   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
01094   message->locked = FALSE;
01095 #ifndef DBUS_DISABLE_CHECKS
01096   message->in_cache = FALSE;
01097 #endif
01098   message->counters = NULL;
01099   message->size_counter_delta = 0;
01100   message->changed_stamp = 0;
01101 
01102 #ifdef HAVE_UNIX_FD_PASSING
01103   message->n_unix_fds = 0;
01104   message->n_unix_fds_allocated = 0;
01105   message->unix_fd_counter_delta = 0;
01106 #endif
01107 
01108   if (!from_cache)
01109     _dbus_data_slot_list_init (&message->slot_list);
01110 
01111   if (from_cache)
01112     {
01113       _dbus_header_reinit (&message->header, message->byte_order);
01114       _dbus_string_set_length (&message->body, 0);
01115     }
01116   else
01117     {
01118       if (!_dbus_header_init (&message->header, message->byte_order))
01119         {
01120           dbus_free (message);
01121           return NULL;
01122         }
01123 
01124       if (!_dbus_string_init_preallocated (&message->body, 32))
01125         {
01126           _dbus_header_free (&message->header);
01127           dbus_free (message);
01128           return NULL;
01129         }
01130     }
01131 
01132   return message;
01133 }
01134 
01147 DBusMessage*
01148 dbus_message_new (int message_type)
01149 {
01150   DBusMessage *message;
01151 
01152   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01153 
01154   message = dbus_message_new_empty_header ();
01155   if (message == NULL)
01156     return NULL;
01157 
01158   if (!_dbus_header_create (&message->header,
01159                             message_type,
01160                             NULL, NULL, NULL, NULL, NULL))
01161     {
01162       dbus_message_unref (message);
01163       return NULL;
01164     }
01165 
01166   return message;
01167 }
01168 
01190 DBusMessage*
01191 dbus_message_new_method_call (const char *destination,
01192                               const char *path,
01193                               const char *interface,
01194                               const char *method)
01195 {
01196   DBusMessage *message;
01197 
01198   _dbus_return_val_if_fail (path != NULL, NULL);
01199   _dbus_return_val_if_fail (method != NULL, NULL);
01200   _dbus_return_val_if_fail (destination == NULL ||
01201                             _dbus_check_is_valid_bus_name (destination), NULL);
01202   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01203   _dbus_return_val_if_fail (interface == NULL ||
01204                             _dbus_check_is_valid_interface (interface), NULL);
01205   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01206 
01207   message = dbus_message_new_empty_header ();
01208   if (message == NULL)
01209     return NULL;
01210 
01211   if (!_dbus_header_create (&message->header,
01212                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01213                             destination, path, interface, method, NULL))
01214     {
01215       dbus_message_unref (message);
01216       return NULL;
01217     }
01218 
01219   return message;
01220 }
01221 
01229 DBusMessage*
01230 dbus_message_new_method_return (DBusMessage *method_call)
01231 {
01232   DBusMessage *message;
01233   const char *sender;
01234 
01235   _dbus_return_val_if_fail (method_call != NULL, NULL);
01236 
01237   sender = dbus_message_get_sender (method_call);
01238 
01239   /* sender is allowed to be null here in peer-to-peer case */
01240 
01241   message = dbus_message_new_empty_header ();
01242   if (message == NULL)
01243     return NULL;
01244 
01245   if (!_dbus_header_create (&message->header,
01246                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01247                             sender, NULL, NULL, NULL, NULL))
01248     {
01249       dbus_message_unref (message);
01250       return NULL;
01251     }
01252 
01253   dbus_message_set_no_reply (message, TRUE);
01254 
01255   if (!dbus_message_set_reply_serial (message,
01256                                       dbus_message_get_serial (method_call)))
01257     {
01258       dbus_message_unref (message);
01259       return NULL;
01260     }
01261 
01262   return message;
01263 }
01264 
01279 DBusMessage*
01280 dbus_message_new_signal (const char *path,
01281                          const char *interface,
01282                          const char *name)
01283 {
01284   DBusMessage *message;
01285 
01286   _dbus_return_val_if_fail (path != NULL, NULL);
01287   _dbus_return_val_if_fail (interface != NULL, NULL);
01288   _dbus_return_val_if_fail (name != NULL, NULL);
01289   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01290   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
01291   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01292 
01293   message = dbus_message_new_empty_header ();
01294   if (message == NULL)
01295     return NULL;
01296 
01297   if (!_dbus_header_create (&message->header,
01298                             DBUS_MESSAGE_TYPE_SIGNAL,
01299                             NULL, path, interface, name, NULL))
01300     {
01301       dbus_message_unref (message);
01302       return NULL;
01303     }
01304 
01305   dbus_message_set_no_reply (message, TRUE);
01306 
01307   return message;
01308 }
01309 
01324 DBusMessage*
01325 dbus_message_new_error (DBusMessage *reply_to,
01326                         const char  *error_name,
01327                         const char  *error_message)
01328 {
01329   DBusMessage *message;
01330   const char *sender;
01331   DBusMessageIter iter;
01332 
01333   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01334   _dbus_return_val_if_fail (error_name != NULL, NULL);
01335   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01336 
01337   sender = dbus_message_get_sender (reply_to);
01338 
01339   /* sender may be NULL for non-message-bus case or
01340    * when the message bus is dealing with an unregistered
01341    * connection.
01342    */
01343   message = dbus_message_new_empty_header ();
01344   if (message == NULL)
01345     return NULL;
01346 
01347   if (!_dbus_header_create (&message->header,
01348                             DBUS_MESSAGE_TYPE_ERROR,
01349                             sender, NULL, NULL, NULL, error_name))
01350     {
01351       dbus_message_unref (message);
01352       return NULL;
01353     }
01354 
01355   dbus_message_set_no_reply (message, TRUE);
01356 
01357   if (!dbus_message_set_reply_serial (message,
01358                                       dbus_message_get_serial (reply_to)))
01359     {
01360       dbus_message_unref (message);
01361       return NULL;
01362     }
01363 
01364   if (error_message != NULL)
01365     {
01366       dbus_message_iter_init_append (message, &iter);
01367       if (!dbus_message_iter_append_basic (&iter,
01368                                            DBUS_TYPE_STRING,
01369                                            &error_message))
01370         {
01371           dbus_message_unref (message);
01372           return NULL;
01373         }
01374     }
01375 
01376   return message;
01377 }
01378 
01395 DBusMessage*
01396 dbus_message_new_error_printf (DBusMessage *reply_to,
01397                                const char  *error_name,
01398                                const char  *error_format,
01399                                ...)
01400 {
01401   va_list args;
01402   DBusString str;
01403   DBusMessage *message;
01404 
01405   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01406   _dbus_return_val_if_fail (error_name != NULL, NULL);
01407   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01408 
01409   if (!_dbus_string_init (&str))
01410     return NULL;
01411 
01412   va_start (args, error_format);
01413 
01414   if (_dbus_string_append_printf_valist (&str, error_format, args))
01415     message = dbus_message_new_error (reply_to, error_name,
01416                                       _dbus_string_get_const_data (&str));
01417   else
01418     message = NULL;
01419 
01420   _dbus_string_free (&str);
01421 
01422   va_end (args);
01423 
01424   return message;
01425 }
01426 
01427 
01440 DBusMessage *
01441 dbus_message_copy (const DBusMessage *message)
01442 {
01443   DBusMessage *retval;
01444 
01445   _dbus_return_val_if_fail (message != NULL, NULL);
01446 
01447   retval = dbus_new0 (DBusMessage, 1);
01448   if (retval == NULL)
01449     return NULL;
01450 
01451   retval->refcount.value = 1;
01452   retval->byte_order = message->byte_order;
01453   retval->locked = FALSE;
01454 #ifndef DBUS_DISABLE_CHECKS
01455   retval->generation = message->generation;
01456 #endif
01457 
01458   if (!_dbus_header_copy (&message->header, &retval->header))
01459     {
01460       dbus_free (retval);
01461       return NULL;
01462     }
01463 
01464   if (!_dbus_string_init_preallocated (&retval->body,
01465                                        _dbus_string_get_length (&message->body)))
01466     {
01467       _dbus_header_free (&retval->header);
01468       dbus_free (retval);
01469       return NULL;
01470     }
01471 
01472   if (!_dbus_string_copy (&message->body, 0,
01473                           &retval->body, 0))
01474     goto failed_copy;
01475 
01476 #ifdef HAVE_UNIX_FD_PASSING
01477   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01478   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01479     goto failed_copy;
01480 
01481   retval->n_unix_fds_allocated = message->n_unix_fds;
01482 
01483   for (retval->n_unix_fds = 0;
01484        retval->n_unix_fds < message->n_unix_fds;
01485        retval->n_unix_fds++)
01486     {
01487       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01488 
01489       if (retval->unix_fds[retval->n_unix_fds] < 0)
01490         goto failed_copy;
01491     }
01492 
01493 #endif
01494 
01495   return retval;
01496 
01497  failed_copy:
01498   _dbus_header_free (&retval->header);
01499   _dbus_string_free (&retval->body);
01500 
01501 #ifdef HAVE_UNIX_FD_PASSING
01502   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01503   dbus_free(retval->unix_fds);
01504 #endif
01505 
01506   dbus_free (retval);
01507 
01508   return NULL;
01509 }
01510 
01511 
01519 DBusMessage *
01520 dbus_message_ref (DBusMessage *message)
01521 {
01522   dbus_int32_t old_refcount;
01523 
01524   _dbus_return_val_if_fail (message != NULL, NULL);
01525   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01526   _dbus_return_val_if_fail (!message->in_cache, NULL);
01527   
01528   old_refcount = _dbus_atomic_inc (&message->refcount);
01529   _dbus_assert (old_refcount >= 1);
01530 
01531   return message;
01532 }
01533 
01541 void
01542 dbus_message_unref (DBusMessage *message)
01543 {
01544  dbus_int32_t old_refcount;
01545 
01546   _dbus_return_if_fail (message != NULL);
01547   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01548   _dbus_return_if_fail (!message->in_cache);
01549 
01550   old_refcount = _dbus_atomic_dec (&message->refcount);
01551 
01552   _dbus_assert (old_refcount >= 0);
01553 
01554   if (old_refcount == 1)
01555     {
01556       /* Calls application callbacks! */
01557       dbus_message_cache_or_finalize (message);
01558     }
01559 }
01560 
01571 int
01572 dbus_message_get_type (DBusMessage *message)
01573 {
01574   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01575 
01576   return _dbus_header_get_message_type (&message->header);
01577 }
01578 
01641 dbus_bool_t
01642 dbus_message_append_args (DBusMessage *message,
01643                           int          first_arg_type,
01644                           ...)
01645 {
01646   dbus_bool_t retval;
01647   va_list var_args;
01648 
01649   _dbus_return_val_if_fail (message != NULL, FALSE);
01650 
01651   va_start (var_args, first_arg_type);
01652   retval = dbus_message_append_args_valist (message,
01653                                             first_arg_type,
01654                                             var_args);
01655   va_end (var_args);
01656 
01657   return retval;
01658 }
01659 
01673 dbus_bool_t
01674 dbus_message_append_args_valist (DBusMessage *message,
01675                                  int          first_arg_type,
01676                                  va_list      var_args)
01677 {
01678   int type;
01679   DBusMessageIter iter;
01680 
01681   _dbus_return_val_if_fail (message != NULL, FALSE);
01682 
01683   type = first_arg_type;
01684 
01685   dbus_message_iter_init_append (message, &iter);
01686 
01687   while (type != DBUS_TYPE_INVALID)
01688     {
01689       if (dbus_type_is_basic (type))
01690         {
01691           const DBusBasicValue *value;
01692           value = va_arg (var_args, const DBusBasicValue*);
01693 
01694           if (!dbus_message_iter_append_basic (&iter,
01695                                                type,
01696                                                value))
01697             goto failed;
01698         }
01699       else if (type == DBUS_TYPE_ARRAY)
01700         {
01701           int element_type;
01702           DBusMessageIter array;
01703           char buf[2];
01704 
01705           element_type = va_arg (var_args, int);
01706               
01707           buf[0] = element_type;
01708           buf[1] = '\0';
01709           if (!dbus_message_iter_open_container (&iter,
01710                                                  DBUS_TYPE_ARRAY,
01711                                                  buf,
01712                                                  &array))
01713             goto failed;
01714 
01715           if (dbus_type_is_fixed (element_type) &&
01716               element_type != DBUS_TYPE_UNIX_FD)
01717             {
01718               const DBusBasicValue **value;
01719               int n_elements;
01720 
01721               value = va_arg (var_args, const DBusBasicValue**);
01722               n_elements = va_arg (var_args, int);
01723               
01724               if (!dbus_message_iter_append_fixed_array (&array,
01725                                                          element_type,
01726                                                          value,
01727                                                          n_elements)) {
01728                 dbus_message_iter_abandon_container (&iter, &array);
01729                 goto failed;
01730               }
01731             }
01732           else if (element_type == DBUS_TYPE_STRING ||
01733                    element_type == DBUS_TYPE_SIGNATURE ||
01734                    element_type == DBUS_TYPE_OBJECT_PATH)
01735             {
01736               const char ***value_p;
01737               const char **value;
01738               int n_elements;
01739               int i;
01740               
01741               value_p = va_arg (var_args, const char***);
01742               n_elements = va_arg (var_args, int);
01743 
01744               value = *value_p;
01745               
01746               i = 0;
01747               while (i < n_elements)
01748                 {
01749                   if (!dbus_message_iter_append_basic (&array,
01750                                                        element_type,
01751                                                        &value[i])) {
01752                     dbus_message_iter_abandon_container (&iter, &array);
01753                     goto failed;
01754                   }
01755                   ++i;
01756                 }
01757             }
01758           else
01759             {
01760               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01761                           _dbus_type_to_string (element_type),
01762                           _DBUS_FUNCTION_NAME);
01763               goto failed;
01764             }
01765 
01766           if (!dbus_message_iter_close_container (&iter, &array))
01767             goto failed;
01768         }
01769 #ifndef DBUS_DISABLE_CHECKS
01770       else
01771         {
01772           _dbus_warn ("type %s isn't supported yet in %s\n",
01773                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01774           goto failed;
01775         }
01776 #endif
01777 
01778       type = va_arg (var_args, int);
01779     }
01780 
01781   return TRUE;
01782 
01783  failed:
01784   return FALSE;
01785 }
01786 
01831 dbus_bool_t
01832 dbus_message_get_args (DBusMessage     *message,
01833                        DBusError       *error,
01834                        int              first_arg_type,
01835                        ...)
01836 {
01837   dbus_bool_t retval;
01838   va_list var_args;
01839 
01840   _dbus_return_val_if_fail (message != NULL, FALSE);
01841   _dbus_return_val_if_error_is_set (error, FALSE);
01842 
01843   va_start (var_args, first_arg_type);
01844   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01845   va_end (var_args);
01846 
01847   return retval;
01848 }
01849 
01860 dbus_bool_t
01861 dbus_message_get_args_valist (DBusMessage     *message,
01862                               DBusError       *error,
01863                               int              first_arg_type,
01864                               va_list          var_args)
01865 {
01866   DBusMessageIter iter;
01867 
01868   _dbus_return_val_if_fail (message != NULL, FALSE);
01869   _dbus_return_val_if_error_is_set (error, FALSE);
01870 
01871   dbus_message_iter_init (message, &iter);
01872   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01873 }
01874 
01875 static void
01876 _dbus_message_iter_init_common (DBusMessage         *message,
01877                                 DBusMessageRealIter *real,
01878                                 int                  iter_type)
01879 {
01880   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01881 
01882   /* Since the iterator will read or write who-knows-what from the
01883    * message, we need to get in the right byte order
01884    */
01885   ensure_byte_order (message);
01886   
01887   real->message = message;
01888   real->changed_stamp = message->changed_stamp;
01889   real->iter_type = iter_type;
01890   real->sig_refcount = 0;
01891 }
01892 
01915 dbus_bool_t
01916 dbus_message_iter_init (DBusMessage     *message,
01917                         DBusMessageIter *iter)
01918 {
01919   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01920   const DBusString *type_str;
01921   int type_pos;
01922 
01923   _dbus_return_val_if_fail (message != NULL, FALSE);
01924   _dbus_return_val_if_fail (iter != NULL, FALSE);
01925 
01926   get_const_signature (&message->header, &type_str, &type_pos);
01927 
01928   _dbus_message_iter_init_common (message, real,
01929                                   DBUS_MESSAGE_ITER_TYPE_READER);
01930 
01931   _dbus_type_reader_init (&real->u.reader,
01932                           message->byte_order,
01933                           type_str, type_pos,
01934                           &message->body,
01935                           0);
01936 
01937   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
01938 }
01939 
01946 dbus_bool_t
01947 dbus_message_iter_has_next (DBusMessageIter *iter)
01948 {
01949   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01950 
01951   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01952   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01953 
01954   return _dbus_type_reader_has_next (&real->u.reader);
01955 }
01956 
01965 dbus_bool_t
01966 dbus_message_iter_next (DBusMessageIter *iter)
01967 {
01968   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01969 
01970   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01971   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01972 
01973   return _dbus_type_reader_next (&real->u.reader);
01974 }
01975 
01990 int
01991 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
01992 {
01993   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01994 
01995   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01996   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01997 
01998   return _dbus_type_reader_get_current_type (&real->u.reader);
01999 }
02000 
02009 int
02010 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02011 {
02012   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02013 
02014   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02015   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02016   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02017 
02018   return _dbus_type_reader_get_element_type (&real->u.reader);
02019 }
02020 
02046 void
02047 dbus_message_iter_recurse (DBusMessageIter  *iter,
02048                            DBusMessageIter  *sub)
02049 {
02050   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02051   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02052 
02053   _dbus_return_if_fail (_dbus_message_iter_check (real));
02054   _dbus_return_if_fail (sub != NULL);
02055 
02056   *real_sub = *real;
02057   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02058 }
02059 
02071 char *
02072 dbus_message_iter_get_signature (DBusMessageIter *iter)
02073 {
02074   const DBusString *sig;
02075   DBusString retstr;
02076   char *ret;
02077   int start, len;
02078   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02079 
02080   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02081 
02082   if (!_dbus_string_init (&retstr))
02083     return NULL;
02084 
02085   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02086                                    &start, &len);
02087   if (!_dbus_string_append_len (&retstr,
02088                                 _dbus_string_get_const_data (sig) + start,
02089                                 len))
02090     return NULL;
02091   if (!_dbus_string_steal_data (&retstr, &ret))
02092     return NULL;
02093   _dbus_string_free (&retstr);
02094   return ret;
02095 }
02096 
02144 void
02145 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02146                              void             *value)
02147 {
02148   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02149 
02150   _dbus_return_if_fail (_dbus_message_iter_check (real));
02151   _dbus_return_if_fail (value != NULL);
02152 
02153   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02154     {
02155 #ifdef HAVE_UNIX_FD_PASSING
02156       DBusBasicValue idx;
02157 
02158       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02159 
02160       if (idx.u32 >= real->message->n_unix_fds) {
02161         /* Hmm, we cannot really signal an error here, so let's make
02162            sure to return an invalid fd. */
02163         *((int*) value) = -1;
02164         return;
02165       }
02166 
02167       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02168 #else
02169       *((int*) value) = -1;
02170 #endif
02171     }
02172   else
02173     {
02174       _dbus_type_reader_read_basic (&real->u.reader,
02175                                     value);
02176     }
02177 }
02178 
02197 int
02198 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02199 {
02200   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02201 
02202   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02203 
02204   return _dbus_type_reader_get_array_length (&real->u.reader);
02205 }
02206 
02242 void
02243 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02244                                    void             *value,
02245                                    int              *n_elements)
02246 {
02247   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02248   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02249 
02250   _dbus_return_if_fail (_dbus_message_iter_check (real));
02251   _dbus_return_if_fail (value != NULL);
02252   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02253                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02254 
02255   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02256                                       value, n_elements);
02257 }
02258 
02270 void
02271 dbus_message_iter_init_append (DBusMessage     *message,
02272                                DBusMessageIter *iter)
02273 {
02274   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02275 
02276   _dbus_return_if_fail (message != NULL);
02277   _dbus_return_if_fail (iter != NULL);
02278 
02279   _dbus_message_iter_init_common (message, real,
02280                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02281 
02282   /* We create the signature string and point iterators at it "on demand"
02283    * when a value is actually appended. That means that init() never fails
02284    * due to OOM.
02285    */
02286   _dbus_type_writer_init_types_delayed (&real->u.writer,
02287                                         message->byte_order,
02288                                         &message->body,
02289                                         _dbus_string_get_length (&message->body));
02290 }
02291 
02300 static dbus_bool_t
02301 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02302 {
02303   DBusString *str;
02304   const DBusString *current_sig;
02305   int current_sig_pos;
02306 
02307   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02308 
02309   if (real->u.writer.type_str != NULL)
02310     {
02311       _dbus_assert (real->sig_refcount > 0);
02312       real->sig_refcount += 1;
02313       return TRUE;
02314     }
02315 
02316   str = dbus_new (DBusString, 1);
02317   if (str == NULL)
02318     return FALSE;
02319 
02320   if (!_dbus_header_get_field_raw (&real->message->header,
02321                                    DBUS_HEADER_FIELD_SIGNATURE,
02322                                    &current_sig, &current_sig_pos))
02323     current_sig = NULL;
02324 
02325   if (current_sig)
02326     {
02327       int current_len;
02328 
02329       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02330       current_sig_pos += 1; /* move on to sig data */
02331 
02332       if (!_dbus_string_init_preallocated (str, current_len + 4))
02333         {
02334           dbus_free (str);
02335           return FALSE;
02336         }
02337 
02338       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02339                                   str, 0))
02340         {
02341           _dbus_string_free (str);
02342           dbus_free (str);
02343           return FALSE;
02344         }
02345     }
02346   else
02347     {
02348       if (!_dbus_string_init_preallocated (str, 4))
02349         {
02350           dbus_free (str);
02351           return FALSE;
02352         }
02353     }
02354 
02355   real->sig_refcount = 1;
02356 
02357   _dbus_type_writer_add_types (&real->u.writer,
02358                                str, _dbus_string_get_length (str));
02359   return TRUE;
02360 }
02361 
02371 static dbus_bool_t
02372 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02373 {
02374   DBusString *str;
02375   const char *v_STRING;
02376   dbus_bool_t retval;
02377 
02378   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02379   _dbus_assert (real->u.writer.type_str != NULL);
02380   _dbus_assert (real->sig_refcount > 0);
02381 
02382   real->sig_refcount -= 1;
02383 
02384   if (real->sig_refcount > 0)
02385     return TRUE;
02386   _dbus_assert (real->sig_refcount == 0);
02387 
02388   retval = TRUE;
02389 
02390   str = real->u.writer.type_str;
02391 
02392   v_STRING = _dbus_string_get_const_data (str);
02393   if (!_dbus_header_set_field_basic (&real->message->header,
02394                                      DBUS_HEADER_FIELD_SIGNATURE,
02395                                      DBUS_TYPE_SIGNATURE,
02396                                      &v_STRING))
02397     retval = FALSE;
02398 
02399   _dbus_type_writer_remove_types (&real->u.writer);
02400   _dbus_string_free (str);
02401   dbus_free (str);
02402 
02403   return retval;
02404 }
02405 
02413 static void
02414 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02415 {
02416   DBusString *str;
02417 
02418   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02419   _dbus_assert (real->u.writer.type_str != NULL);
02420   _dbus_assert (real->sig_refcount > 0);
02421 
02422   real->sig_refcount -= 1;
02423 
02424   if (real->sig_refcount > 0)
02425     return;
02426   _dbus_assert (real->sig_refcount == 0);
02427 
02428   str = real->u.writer.type_str;
02429 
02430   _dbus_type_writer_remove_types (&real->u.writer);
02431   _dbus_string_free (str);
02432   dbus_free (str);
02433 }
02434 
02435 #ifndef DBUS_DISABLE_CHECKS
02436 static dbus_bool_t
02437 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02438 {
02439   if (!_dbus_message_iter_check (iter))
02440     return FALSE;
02441 
02442   if (iter->message->locked)
02443     {
02444       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02445       return FALSE;
02446     }
02447 
02448   return TRUE;
02449 }
02450 #endif /* DBUS_DISABLE_CHECKS */
02451 
02452 #ifdef HAVE_UNIX_FD_PASSING
02453 static int *
02454 expand_fd_array(DBusMessage *m,
02455                 unsigned     n)
02456 {
02457   _dbus_assert(m);
02458 
02459   /* This makes space for adding n new fds to the array and returns a
02460      pointer to the place were the first fd should be put. */
02461 
02462   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02463     {
02464       unsigned k;
02465       int *p;
02466 
02467       /* Make twice as much space as necessary */
02468       k = (m->n_unix_fds + n) * 2;
02469 
02470       /* Allocate at least four */
02471       if (k < 4)
02472         k = 4;
02473 
02474       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02475       if (p == NULL)
02476         return NULL;
02477 
02478       m->unix_fds = p;
02479       m->n_unix_fds_allocated = k;
02480     }
02481 
02482   return m->unix_fds + m->n_unix_fds;
02483 }
02484 #endif
02485 
02505 dbus_bool_t
02506 dbus_message_iter_append_basic (DBusMessageIter *iter,
02507                                 int              type,
02508                                 const void      *value)
02509 {
02510   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02511   dbus_bool_t ret;
02512 
02513   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02514   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02515   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02516   _dbus_return_val_if_fail (value != NULL, FALSE);
02517 
02518 #ifndef DBUS_DISABLE_CHECKS
02519   switch (type)
02520     {
02521       const char * const *string_p;
02522       const dbus_bool_t *bool_p;
02523 
02524       case DBUS_TYPE_STRING:
02525         string_p = value;
02526         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02527         break;
02528 
02529       case DBUS_TYPE_OBJECT_PATH:
02530         string_p = value;
02531         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02532         break;
02533 
02534       case DBUS_TYPE_SIGNATURE:
02535         string_p = value;
02536         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02537         break;
02538 
02539       case DBUS_TYPE_BOOLEAN:
02540         bool_p = value;
02541         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02542         break;
02543 
02544       default:
02545           {
02546             /* nothing to check, all possible values are allowed */
02547           }
02548     }
02549 #endif
02550 
02551   if (!_dbus_message_iter_open_signature (real))
02552     return FALSE;
02553 
02554   if (type == DBUS_TYPE_UNIX_FD)
02555     {
02556 #ifdef HAVE_UNIX_FD_PASSING
02557       int *fds;
02558       dbus_uint32_t u;
02559 
02560       /* First step, include the fd in the fd list of this message */
02561       if (!(fds = expand_fd_array(real->message, 1)))
02562         return FALSE;
02563 
02564       *fds = _dbus_dup(*(int*) value, NULL);
02565       if (*fds < 0)
02566         return FALSE;
02567 
02568       u = real->message->n_unix_fds;
02569 
02570       /* Second step, write the index to the fd */
02571       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02572         _dbus_close(*fds, NULL);
02573         return FALSE;
02574       }
02575 
02576       real->message->n_unix_fds += 1;
02577       u += 1;
02578 
02579       /* Final step, update the header accordingly */
02580       ret = _dbus_header_set_field_basic (&real->message->header,
02581                                           DBUS_HEADER_FIELD_UNIX_FDS,
02582                                           DBUS_TYPE_UINT32,
02583                                           &u);
02584 
02585       /* If any of these operations fail the message is
02586          hosed. However, no memory or fds should be leaked since what
02587          has been added to message has been added to the message, and
02588          can hence be accounted for when the message is being
02589          freed. */
02590 #else
02591       ret = FALSE;
02592 #endif
02593     }
02594   else
02595     {
02596       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02597     }
02598 
02599   if (!_dbus_message_iter_close_signature (real))
02600     ret = FALSE;
02601 
02602   return ret;
02603 }
02604 
02640 dbus_bool_t
02641 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02642                                       int              element_type,
02643                                       const void      *value,
02644                                       int              n_elements)
02645 {
02646   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02647   dbus_bool_t ret;
02648 
02649   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02650   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02651   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02652   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02653   _dbus_return_val_if_fail (value != NULL, FALSE);
02654   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02655   _dbus_return_val_if_fail (n_elements <=
02656                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02657                             FALSE);
02658 
02659 #ifndef DBUS_DISABLE_CHECKS
02660   if (element_type == DBUS_TYPE_BOOLEAN)
02661     {
02662       const dbus_bool_t * const *bools = value;
02663       int i;
02664 
02665       for (i = 0; i < n_elements; i++)
02666         {
02667           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02668         }
02669     }
02670 #endif
02671 
02672   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02673 
02674   return ret;
02675 }
02676 
02698 dbus_bool_t
02699 dbus_message_iter_open_container (DBusMessageIter *iter,
02700                                   int              type,
02701                                   const char      *contained_signature,
02702                                   DBusMessageIter *sub)
02703 {
02704   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02705   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02706   DBusString contained_str;
02707 
02708   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02709   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02710   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02711   _dbus_return_val_if_fail (sub != NULL, FALSE);
02712   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02713                              contained_signature == NULL) ||
02714                             (type == DBUS_TYPE_DICT_ENTRY &&
02715                              contained_signature == NULL) ||
02716                             (type == DBUS_TYPE_VARIANT &&
02717                              contained_signature != NULL) ||
02718                             (type == DBUS_TYPE_ARRAY &&
02719                              contained_signature != NULL), FALSE);
02720   
02721   /* this would fail if the contained_signature is a dict entry, since
02722    * dict entries are invalid signatures standalone (they must be in
02723    * an array)
02724    */
02725   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02726                             (contained_signature == NULL ||
02727                              _dbus_check_is_valid_signature (contained_signature)),
02728                             FALSE);
02729 
02730   if (!_dbus_message_iter_open_signature (real))
02731     return FALSE;
02732 
02733   *real_sub = *real;
02734 
02735   if (contained_signature != NULL)
02736     {
02737       _dbus_string_init_const (&contained_str, contained_signature);
02738 
02739       return _dbus_type_writer_recurse (&real->u.writer,
02740                                         type,
02741                                         &contained_str, 0,
02742                                         &real_sub->u.writer);
02743     }
02744   else
02745     {
02746       return _dbus_type_writer_recurse (&real->u.writer,
02747                                         type,
02748                                         NULL, 0,
02749                                         &real_sub->u.writer);
02750     } 
02751 }
02752 
02753 
02767 dbus_bool_t
02768 dbus_message_iter_close_container (DBusMessageIter *iter,
02769                                    DBusMessageIter *sub)
02770 {
02771   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02772   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02773   dbus_bool_t ret;
02774 
02775   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02776   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02777   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02778   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02779 
02780   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02781                                      &real_sub->u.writer);
02782 
02783   if (!_dbus_message_iter_close_signature (real))
02784     ret = FALSE;
02785 
02786   return ret;
02787 }
02788 
02800 void
02801 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02802                                      DBusMessageIter *sub)
02803 {
02804   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02805   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02806 
02807   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02808   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02809   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02810   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02811 
02812   _dbus_message_iter_abandon_signature (real);
02813 }
02814 
02831 void
02832 dbus_message_set_no_reply (DBusMessage *message,
02833                            dbus_bool_t  no_reply)
02834 {
02835   _dbus_return_if_fail (message != NULL);
02836   _dbus_return_if_fail (!message->locked);
02837 
02838   _dbus_header_toggle_flag (&message->header,
02839                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02840                             no_reply);
02841 }
02842 
02850 dbus_bool_t
02851 dbus_message_get_no_reply (DBusMessage *message)
02852 {
02853   _dbus_return_val_if_fail (message != NULL, FALSE);
02854 
02855   return _dbus_header_get_flag (&message->header,
02856                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02857 }
02858 
02873 void
02874 dbus_message_set_auto_start (DBusMessage *message,
02875                              dbus_bool_t  auto_start)
02876 {
02877   _dbus_return_if_fail (message != NULL);
02878   _dbus_return_if_fail (!message->locked);
02879 
02880   _dbus_header_toggle_flag (&message->header,
02881                             DBUS_HEADER_FLAG_NO_AUTO_START,
02882                             !auto_start);
02883 }
02884 
02892 dbus_bool_t
02893 dbus_message_get_auto_start (DBusMessage *message)
02894 {
02895   _dbus_return_val_if_fail (message != NULL, FALSE);
02896 
02897   return !_dbus_header_get_flag (&message->header,
02898                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02899 }
02900 
02901 
02914 dbus_bool_t
02915 dbus_message_set_path (DBusMessage   *message,
02916                        const char    *object_path)
02917 {
02918   _dbus_return_val_if_fail (message != NULL, FALSE);
02919   _dbus_return_val_if_fail (!message->locked, FALSE);
02920   _dbus_return_val_if_fail (object_path == NULL ||
02921                             _dbus_check_is_valid_path (object_path),
02922                             FALSE);
02923 
02924   return set_or_delete_string_field (message,
02925                                      DBUS_HEADER_FIELD_PATH,
02926                                      DBUS_TYPE_OBJECT_PATH,
02927                                      object_path);
02928 }
02929 
02943 const char*
02944 dbus_message_get_path (DBusMessage   *message)
02945 {
02946   const char *v;
02947 
02948   _dbus_return_val_if_fail (message != NULL, NULL);
02949 
02950   v = NULL; /* in case field doesn't exist */
02951   _dbus_header_get_field_basic (&message->header,
02952                                 DBUS_HEADER_FIELD_PATH,
02953                                 DBUS_TYPE_OBJECT_PATH,
02954                                 (void *) &v);
02955   return v;
02956 }
02957 
02967 dbus_bool_t
02968 dbus_message_has_path (DBusMessage   *message,
02969                        const char    *path)
02970 {
02971   const char *msg_path;
02972   msg_path = dbus_message_get_path (message);
02973   
02974   if (msg_path == NULL)
02975     {
02976       if (path == NULL)
02977         return TRUE;
02978       else
02979         return FALSE;
02980     }
02981 
02982   if (path == NULL)
02983     return FALSE;
02984    
02985   if (strcmp (msg_path, path) == 0)
02986     return TRUE;
02987 
02988   return FALSE;
02989 }
02990 
03011 dbus_bool_t
03012 dbus_message_get_path_decomposed (DBusMessage   *message,
03013                                   char        ***path)
03014 {
03015   const char *v;
03016 
03017   _dbus_return_val_if_fail (message != NULL, FALSE);
03018   _dbus_return_val_if_fail (path != NULL, FALSE);
03019 
03020   *path = NULL;
03021 
03022   v = dbus_message_get_path (message);
03023   if (v != NULL)
03024     {
03025       if (!_dbus_decompose_path (v, strlen (v),
03026                                  path, NULL))
03027         return FALSE;
03028     }
03029   return TRUE;
03030 }
03031 
03045 dbus_bool_t
03046 dbus_message_set_interface (DBusMessage  *message,
03047                             const char   *interface)
03048 {
03049   _dbus_return_val_if_fail (message != NULL, FALSE);
03050   _dbus_return_val_if_fail (!message->locked, FALSE);
03051   _dbus_return_val_if_fail (interface == NULL ||
03052                             _dbus_check_is_valid_interface (interface),
03053                             FALSE);
03054 
03055   return set_or_delete_string_field (message,
03056                                      DBUS_HEADER_FIELD_INTERFACE,
03057                                      DBUS_TYPE_STRING,
03058                                      interface);
03059 }
03060 
03074 const char*
03075 dbus_message_get_interface (DBusMessage *message)
03076 {
03077   const char *v;
03078 
03079   _dbus_return_val_if_fail (message != NULL, NULL);
03080 
03081   v = NULL; /* in case field doesn't exist */
03082   _dbus_header_get_field_basic (&message->header,
03083                                 DBUS_HEADER_FIELD_INTERFACE,
03084                                 DBUS_TYPE_STRING,
03085                                 (void *) &v);
03086   return v;
03087 }
03088 
03096 dbus_bool_t
03097 dbus_message_has_interface (DBusMessage   *message,
03098                             const char    *interface)
03099 {
03100   const char *msg_interface;
03101   msg_interface = dbus_message_get_interface (message);
03102    
03103   if (msg_interface == NULL)
03104     {
03105       if (interface == NULL)
03106         return TRUE;
03107       else
03108         return FALSE;
03109     }
03110 
03111   if (interface == NULL)
03112     return FALSE;
03113      
03114   if (strcmp (msg_interface, interface) == 0)
03115     return TRUE;
03116 
03117   return FALSE;
03118 
03119 }
03120 
03133 dbus_bool_t
03134 dbus_message_set_member (DBusMessage  *message,
03135                          const char   *member)
03136 {
03137   _dbus_return_val_if_fail (message != NULL, FALSE);
03138   _dbus_return_val_if_fail (!message->locked, FALSE);
03139   _dbus_return_val_if_fail (member == NULL ||
03140                             _dbus_check_is_valid_member (member),
03141                             FALSE);
03142 
03143   return set_or_delete_string_field (message,
03144                                      DBUS_HEADER_FIELD_MEMBER,
03145                                      DBUS_TYPE_STRING,
03146                                      member);
03147 }
03148 
03160 const char*
03161 dbus_message_get_member (DBusMessage *message)
03162 {
03163   const char *v;
03164 
03165   _dbus_return_val_if_fail (message != NULL, NULL);
03166 
03167   v = NULL; /* in case field doesn't exist */
03168   _dbus_header_get_field_basic (&message->header,
03169                                 DBUS_HEADER_FIELD_MEMBER,
03170                                 DBUS_TYPE_STRING,
03171                                 (void *) &v);
03172   return v;
03173 }
03174 
03182 dbus_bool_t
03183 dbus_message_has_member (DBusMessage   *message,
03184                          const char    *member)
03185 {
03186   const char *msg_member;
03187   msg_member = dbus_message_get_member (message);
03188  
03189   if (msg_member == NULL)
03190     {
03191       if (member == NULL)
03192         return TRUE;
03193       else
03194         return FALSE;
03195     }
03196 
03197   if (member == NULL)
03198     return FALSE;
03199     
03200   if (strcmp (msg_member, member) == 0)
03201     return TRUE;
03202 
03203   return FALSE;
03204 
03205 }
03206 
03218 dbus_bool_t
03219 dbus_message_set_error_name (DBusMessage  *message,
03220                              const char   *error_name)
03221 {
03222   _dbus_return_val_if_fail (message != NULL, FALSE);
03223   _dbus_return_val_if_fail (!message->locked, FALSE);
03224   _dbus_return_val_if_fail (error_name == NULL ||
03225                             _dbus_check_is_valid_error_name (error_name),
03226                             FALSE);
03227 
03228   return set_or_delete_string_field (message,
03229                                      DBUS_HEADER_FIELD_ERROR_NAME,
03230                                      DBUS_TYPE_STRING,
03231                                      error_name);
03232 }
03233 
03244 const char*
03245 dbus_message_get_error_name (DBusMessage *message)
03246 {
03247   const char *v;
03248 
03249   _dbus_return_val_if_fail (message != NULL, NULL);
03250 
03251   v = NULL; /* in case field doesn't exist */
03252   _dbus_header_get_field_basic (&message->header,
03253                                 DBUS_HEADER_FIELD_ERROR_NAME,
03254                                 DBUS_TYPE_STRING,
03255                                 (void *) &v);
03256   return v;
03257 }
03258 
03272 dbus_bool_t
03273 dbus_message_set_destination (DBusMessage  *message,
03274                               const char   *destination)
03275 {
03276   _dbus_return_val_if_fail (message != NULL, FALSE);
03277   _dbus_return_val_if_fail (!message->locked, FALSE);
03278   _dbus_return_val_if_fail (destination == NULL ||
03279                             _dbus_check_is_valid_bus_name (destination),
03280                             FALSE);
03281 
03282   return set_or_delete_string_field (message,
03283                                      DBUS_HEADER_FIELD_DESTINATION,
03284                                      DBUS_TYPE_STRING,
03285                                      destination);
03286 }
03287 
03297 const char*
03298 dbus_message_get_destination (DBusMessage *message)
03299 {
03300   const char *v;
03301 
03302   _dbus_return_val_if_fail (message != NULL, NULL);
03303 
03304   v = NULL; /* in case field doesn't exist */
03305   _dbus_header_get_field_basic (&message->header,
03306                                 DBUS_HEADER_FIELD_DESTINATION,
03307                                 DBUS_TYPE_STRING,
03308                                 (void *) &v);
03309   return v;
03310 }
03311 
03326 dbus_bool_t
03327 dbus_message_set_sender (DBusMessage  *message,
03328                          const char   *sender)
03329 {
03330   _dbus_return_val_if_fail (message != NULL, FALSE);
03331   _dbus_return_val_if_fail (!message->locked, FALSE);
03332   _dbus_return_val_if_fail (sender == NULL ||
03333                             _dbus_check_is_valid_bus_name (sender),
03334                             FALSE);
03335 
03336   return set_or_delete_string_field (message,
03337                                      DBUS_HEADER_FIELD_SENDER,
03338                                      DBUS_TYPE_STRING,
03339                                      sender);
03340 }
03341 
03357 const char*
03358 dbus_message_get_sender (DBusMessage *message)
03359 {
03360   const char *v;
03361 
03362   _dbus_return_val_if_fail (message != NULL, NULL);
03363 
03364   v = NULL; /* in case field doesn't exist */
03365   _dbus_header_get_field_basic (&message->header,
03366                                 DBUS_HEADER_FIELD_SENDER,
03367                                 DBUS_TYPE_STRING,
03368                                 (void *) &v);
03369   return v;
03370 }
03371 
03390 const char*
03391 dbus_message_get_signature (DBusMessage *message)
03392 {
03393   const DBusString *type_str;
03394   int type_pos;
03395 
03396   _dbus_return_val_if_fail (message != NULL, NULL);
03397 
03398   get_const_signature (&message->header, &type_str, &type_pos);
03399 
03400   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03401 }
03402 
03403 static dbus_bool_t
03404 _dbus_message_has_type_interface_member (DBusMessage *message,
03405                                          int          type,
03406                                          const char  *interface,
03407                                          const char  *member)
03408 {
03409   const char *n;
03410 
03411   _dbus_assert (message != NULL);
03412   _dbus_assert (interface != NULL);
03413   _dbus_assert (member != NULL);
03414 
03415   if (dbus_message_get_type (message) != type)
03416     return FALSE;
03417 
03418   /* Optimize by checking the short member name first
03419    * instead of the longer interface name
03420    */
03421 
03422   n = dbus_message_get_member (message);
03423 
03424   if (n && strcmp (n, member) == 0)
03425     {
03426       n = dbus_message_get_interface (message);
03427 
03428       if (n == NULL || strcmp (n, interface) == 0)
03429         return TRUE;
03430     }
03431 
03432   return FALSE;
03433 }
03434 
03449 dbus_bool_t
03450 dbus_message_is_method_call (DBusMessage *message,
03451                              const char  *interface,
03452                              const char  *method)
03453 {
03454   _dbus_return_val_if_fail (message != NULL, FALSE);
03455   _dbus_return_val_if_fail (interface != NULL, FALSE);
03456   _dbus_return_val_if_fail (method != NULL, FALSE);
03457   /* don't check that interface/method are valid since it would be
03458    * expensive, and not catch many common errors
03459    */
03460 
03461   return _dbus_message_has_type_interface_member (message,
03462                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03463                                                   interface, method);
03464 }
03465 
03477 dbus_bool_t
03478 dbus_message_is_signal (DBusMessage *message,
03479                         const char  *interface,
03480                         const char  *signal_name)
03481 {
03482   _dbus_return_val_if_fail (message != NULL, FALSE);
03483   _dbus_return_val_if_fail (interface != NULL, FALSE);
03484   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03485   /* don't check that interface/name are valid since it would be
03486    * expensive, and not catch many common errors
03487    */
03488 
03489   return _dbus_message_has_type_interface_member (message,
03490                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03491                                                   interface, signal_name);
03492 }
03493 
03504 dbus_bool_t
03505 dbus_message_is_error (DBusMessage *message,
03506                        const char  *error_name)
03507 {
03508   const char *n;
03509 
03510   _dbus_return_val_if_fail (message != NULL, FALSE);
03511   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03512   /* don't check that error_name is valid since it would be expensive,
03513    * and not catch many common errors
03514    */
03515 
03516   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03517     return FALSE;
03518 
03519   n = dbus_message_get_error_name (message);
03520 
03521   if (n && strcmp (n, error_name) == 0)
03522     return TRUE;
03523   else
03524     return FALSE;
03525 }
03526 
03537 dbus_bool_t
03538 dbus_message_has_destination (DBusMessage  *message,
03539                               const char   *name)
03540 {
03541   const char *s;
03542 
03543   _dbus_return_val_if_fail (message != NULL, FALSE);
03544   _dbus_return_val_if_fail (name != NULL, FALSE);
03545   /* don't check that name is valid since it would be expensive, and
03546    * not catch many common errors
03547    */
03548 
03549   s = dbus_message_get_destination (message);
03550 
03551   if (s && strcmp (s, name) == 0)
03552     return TRUE;
03553   else
03554     return FALSE;
03555 }
03556 
03572 dbus_bool_t
03573 dbus_message_has_sender (DBusMessage  *message,
03574                          const char   *name)
03575 {
03576   const char *s;
03577 
03578   _dbus_return_val_if_fail (message != NULL, FALSE);
03579   _dbus_return_val_if_fail (name != NULL, FALSE);
03580   /* don't check that name is valid since it would be expensive, and
03581    * not catch many common errors
03582    */
03583 
03584   s = dbus_message_get_sender (message);
03585 
03586   if (s && strcmp (s, name) == 0)
03587     return TRUE;
03588   else
03589     return FALSE;
03590 }
03591 
03601 dbus_bool_t
03602 dbus_message_has_signature (DBusMessage   *message,
03603                             const char    *signature)
03604 {
03605   const char *s;
03606 
03607   _dbus_return_val_if_fail (message != NULL, FALSE);
03608   _dbus_return_val_if_fail (signature != NULL, FALSE);
03609   /* don't check that signature is valid since it would be expensive,
03610    * and not catch many common errors
03611    */
03612 
03613   s = dbus_message_get_signature (message);
03614 
03615   if (s && strcmp (s, signature) == 0)
03616     return TRUE;
03617   else
03618     return FALSE;
03619 }
03620 
03643 dbus_bool_t
03644 dbus_set_error_from_message (DBusError   *error,
03645                              DBusMessage *message)
03646 {
03647   const char *str;
03648 
03649   _dbus_return_val_if_fail (message != NULL, FALSE);
03650   _dbus_return_val_if_error_is_set (error, FALSE);
03651 
03652   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03653     return FALSE;
03654 
03655   str = NULL;
03656   dbus_message_get_args (message, NULL,
03657                          DBUS_TYPE_STRING, &str,
03658                          DBUS_TYPE_INVALID);
03659 
03660   dbus_set_error (error, dbus_message_get_error_name (message),
03661                   str ? "%s" : NULL, str);
03662 
03663   return TRUE;
03664 }
03665 
03672 dbus_bool_t
03673 dbus_message_contains_unix_fds(DBusMessage *message)
03674 {
03675 #ifdef HAVE_UNIX_FD_PASSING
03676   _dbus_assert(message);
03677 
03678   return message->n_unix_fds > 0;
03679 #else
03680   return FALSE;
03681 #endif
03682 }
03683 
03702 #define INITIAL_LOADER_DATA_LEN 32
03703 
03710 DBusMessageLoader*
03711 _dbus_message_loader_new (void)
03712 {
03713   DBusMessageLoader *loader;
03714 
03715   loader = dbus_new0 (DBusMessageLoader, 1);
03716   if (loader == NULL)
03717     return NULL;
03718   
03719   loader->refcount = 1;
03720 
03721   loader->corrupted = FALSE;
03722   loader->corruption_reason = DBUS_VALID;
03723 
03724   /* this can be configured by the app, but defaults to the protocol max */
03725   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03726 
03727   /* We set a very relatively conservative default here since due to how
03728   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03729   number of unix fds we want to receive in advance. A
03730   try-and-reallocate loop is not possible. */
03731   loader->max_message_unix_fds = 1024;
03732 
03733   if (!_dbus_string_init (&loader->data))
03734     {
03735       dbus_free (loader);
03736       return NULL;
03737     }
03738 
03739   /* preallocate the buffer for speed, ignore failure */
03740   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03741   _dbus_string_set_length (&loader->data, 0);
03742 
03743 #ifdef HAVE_UNIX_FD_PASSING
03744   loader->unix_fds = NULL;
03745   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03746   loader->unix_fds_outstanding = FALSE;
03747 #endif
03748 
03749   return loader;
03750 }
03751 
03758 DBusMessageLoader *
03759 _dbus_message_loader_ref (DBusMessageLoader *loader)
03760 {
03761   loader->refcount += 1;
03762 
03763   return loader;
03764 }
03765 
03772 void
03773 _dbus_message_loader_unref (DBusMessageLoader *loader)
03774 {
03775   loader->refcount -= 1;
03776   if (loader->refcount == 0)
03777     {
03778 #ifdef HAVE_UNIX_FD_PASSING
03779       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
03780       dbus_free(loader->unix_fds);
03781 #endif
03782       _dbus_list_foreach (&loader->messages,
03783                           (DBusForeachFunction) dbus_message_unref,
03784                           NULL);
03785       _dbus_list_clear (&loader->messages);
03786       _dbus_string_free (&loader->data);
03787       dbus_free (loader);
03788     }
03789 }
03790 
03809 void
03810 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03811                                  DBusString        **buffer)
03812 {
03813   _dbus_assert (!loader->buffer_outstanding);
03814 
03815   *buffer = &loader->data;
03816 
03817   loader->buffer_outstanding = TRUE;
03818 }
03819 
03830 void
03831 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03832                                     DBusString         *buffer,
03833                                     int                 bytes_read)
03834 {
03835   _dbus_assert (loader->buffer_outstanding);
03836   _dbus_assert (buffer == &loader->data);
03837 
03838   loader->buffer_outstanding = FALSE;
03839 }
03840 
03851 dbus_bool_t
03852 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
03853                                   int               **fds,
03854                                   unsigned           *max_n_fds)
03855 {
03856 #ifdef HAVE_UNIX_FD_PASSING
03857   _dbus_assert (!loader->unix_fds_outstanding);
03858 
03859   /* Allocate space where we can put the fds we read. We allocate
03860      space for max_message_unix_fds since this is an
03861      upper limit how many fds can be received within a single
03862      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
03863      we are allocating the maximum possible array size right from the
03864      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
03865      there is no better way. */
03866 
03867   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
03868     {
03869       int *a = dbus_realloc(loader->unix_fds,
03870                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
03871 
03872       if (!a)
03873         return FALSE;
03874 
03875       loader->unix_fds = a;
03876       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
03877     }
03878 
03879   *fds = loader->unix_fds + loader->n_unix_fds;
03880   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
03881 
03882   loader->unix_fds_outstanding = TRUE;
03883   return TRUE;
03884 #else
03885   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03886   return FALSE;
03887 #endif
03888 }
03889 
03900 void
03901 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
03902                                      int                *fds,
03903                                      unsigned            n_fds)
03904 {
03905 #ifdef HAVE_UNIX_FD_PASSING
03906   _dbus_assert(loader->unix_fds_outstanding);
03907   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
03908   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
03909 
03910   loader->n_unix_fds += n_fds;
03911   loader->unix_fds_outstanding = FALSE;
03912 #else
03913   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03914 #endif
03915 }
03916 
03917 /*
03918  * FIXME when we move the header out of the buffer, that memmoves all
03919  * buffered messages. Kind of crappy.
03920  *
03921  * Also we copy the header and body, which is kind of crappy.  To
03922  * avoid this, we have to allow header and body to be in a single
03923  * memory block, which is good for messages we read and bad for
03924  * messages we are creating. But we could move_len() the buffer into
03925  * this single memory block, and move_len() will just swap the buffers
03926  * if you're moving the entire buffer replacing the dest string.
03927  *
03928  * We could also have the message loader tell the transport how many
03929  * bytes to read; so it would first ask for some arbitrary number like
03930  * 256, then if the message was incomplete it would use the
03931  * header/body len to ask for exactly the size of the message (or
03932  * blocks the size of a typical kernel buffer for the socket). That
03933  * way we don't get trailing bytes in the buffer that have to be
03934  * memmoved. Though I suppose we also don't have a chance of reading a
03935  * bunch of small messages at once, so the optimization may be stupid.
03936  *
03937  * Another approach would be to keep a "start" index into
03938  * loader->data and only delete it occasionally, instead of after
03939  * each message is loaded.
03940  *
03941  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03942  */
03943 static dbus_bool_t
03944 load_message (DBusMessageLoader *loader,
03945               DBusMessage       *message,
03946               int                byte_order,
03947               int                fields_array_len,
03948               int                header_len,
03949               int                body_len)
03950 {
03951   dbus_bool_t oom;
03952   DBusValidity validity;
03953   const DBusString *type_str;
03954   int type_pos;
03955   DBusValidationMode mode;
03956   dbus_uint32_t n_unix_fds = 0;
03957 
03958   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03959   
03960   oom = FALSE;
03961 
03962 #if 0
03963   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03964 #endif
03965 
03966   /* 1. VALIDATE AND COPY OVER HEADER */
03967   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03968   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03969 
03970   if (!_dbus_header_load (&message->header,
03971                           mode,
03972                           &validity,
03973                           byte_order,
03974                           fields_array_len,
03975                           header_len,
03976                           body_len,
03977                           &loader->data, 0,
03978                           _dbus_string_get_length (&loader->data)))
03979     {
03980       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03981 
03982       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03983          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03984       _dbus_assert (validity != DBUS_VALID);
03985 
03986       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03987         oom = TRUE;
03988       else
03989         {
03990           loader->corrupted = TRUE;
03991           loader->corruption_reason = validity;
03992         }
03993       goto failed;
03994     }
03995 
03996   _dbus_assert (validity == DBUS_VALID);
03997 
03998   message->byte_order = byte_order;
03999 
04000   /* 2. VALIDATE BODY */
04001   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04002     {
04003       get_const_signature (&message->header, &type_str, &type_pos);
04004       
04005       /* Because the bytes_remaining arg is NULL, this validates that the
04006        * body is the right length
04007        */
04008       validity = _dbus_validate_body_with_reason (type_str,
04009                                                   type_pos,
04010                                                   byte_order,
04011                                                   NULL,
04012                                                   &loader->data,
04013                                                   header_len,
04014                                                   body_len);
04015       if (validity != DBUS_VALID)
04016         {
04017           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04018 
04019           loader->corrupted = TRUE;
04020           loader->corruption_reason = validity;
04021           
04022           goto failed;
04023         }
04024     }
04025 
04026   /* 3. COPY OVER UNIX FDS */
04027   _dbus_header_get_field_basic(&message->header,
04028                                DBUS_HEADER_FIELD_UNIX_FDS,
04029                                DBUS_TYPE_UINT32,
04030                                &n_unix_fds);
04031 
04032 #ifdef HAVE_UNIX_FD_PASSING
04033 
04034   if (n_unix_fds > loader->n_unix_fds)
04035     {
04036       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04037                     n_unix_fds, loader->n_unix_fds);
04038 
04039       loader->corrupted = TRUE;
04040       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04041       goto failed;
04042     }
04043 
04044   /* If this was a recycled message there might still be
04045      some memory allocated for the fds */
04046   dbus_free(message->unix_fds);
04047 
04048   if (n_unix_fds > 0)
04049     {
04050       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04051       if (message->unix_fds == NULL)
04052         {
04053           _dbus_verbose ("Failed to allocate file descriptor array\n");
04054           oom = TRUE;
04055           goto failed;
04056         }
04057 
04058       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04059       loader->n_unix_fds -= n_unix_fds;
04060       memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds);
04061     }
04062   else
04063     message->unix_fds = NULL;
04064 
04065 #else
04066 
04067   if (n_unix_fds > 0)
04068     {
04069       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04070                      "but that's not supported on our platform, disconnecting.\n");
04071 
04072       loader->corrupted = TRUE;
04073       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04074       goto failed;
04075     }
04076 
04077 #endif
04078 
04079   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04080 
04081   if (!_dbus_list_append (&loader->messages, message))
04082     {
04083       _dbus_verbose ("Failed to append new message to loader queue\n");
04084       oom = TRUE;
04085       goto failed;
04086     }
04087 
04088   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04089   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04090                 (header_len + body_len));
04091 
04092   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04093     {
04094       _dbus_verbose ("Failed to move body into new message\n");
04095       oom = TRUE;
04096       goto failed;
04097     }
04098 
04099   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04100 
04101   /* don't waste more than 2k of memory */
04102   _dbus_string_compact (&loader->data, 2048);
04103 
04104   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04105   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04106 
04107   _dbus_verbose ("Loaded message %p\n", message);
04108 
04109   _dbus_assert (!oom);
04110   _dbus_assert (!loader->corrupted);
04111   _dbus_assert (loader->messages != NULL);
04112   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04113 
04114   return TRUE;
04115 
04116  failed:
04117 
04118   /* Clean up */
04119 
04120   /* does nothing if the message isn't in the list */
04121   _dbus_list_remove_last (&loader->messages, message);
04122   
04123   if (oom)
04124     _dbus_assert (!loader->corrupted);
04125   else
04126     _dbus_assert (loader->corrupted);
04127 
04128   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04129 
04130   return FALSE;
04131 }
04132 
04147 dbus_bool_t
04148 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04149 {
04150   while (!loader->corrupted &&
04151          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04152     {
04153       DBusValidity validity;
04154       int byte_order, fields_array_len, header_len, body_len;
04155 
04156       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04157                                                &validity,
04158                                                &byte_order,
04159                                                &fields_array_len,
04160                                                &header_len,
04161                                                &body_len,
04162                                                &loader->data, 0,
04163                                                _dbus_string_get_length (&loader->data)))
04164         {
04165           DBusMessage *message;
04166 
04167           _dbus_assert (validity == DBUS_VALID);
04168 
04169           message = dbus_message_new_empty_header ();
04170           if (message == NULL)
04171             return FALSE;
04172 
04173           if (!load_message (loader, message,
04174                              byte_order, fields_array_len,
04175                              header_len, body_len))
04176             {
04177               dbus_message_unref (message);
04178               /* load_message() returns false if corrupted or OOM; if
04179                * corrupted then return TRUE for not OOM
04180                */
04181               return loader->corrupted;
04182             }
04183 
04184           _dbus_assert (loader->messages != NULL);
04185           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04186         }
04187       else
04188         {
04189           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04190                          validity);
04191           if (validity != DBUS_VALID)
04192             {
04193               loader->corrupted = TRUE;
04194               loader->corruption_reason = validity;
04195             }
04196           return TRUE;
04197         }
04198     }
04199 
04200   return TRUE;
04201 }
04202 
04210 DBusMessage*
04211 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04212 {
04213   if (loader->messages)
04214     return loader->messages->data;
04215   else
04216     return NULL;
04217 }
04218 
04227 DBusMessage*
04228 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04229 {
04230   return _dbus_list_pop_first (&loader->messages);
04231 }
04232 
04241 DBusList*
04242 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04243 {
04244   return _dbus_list_pop_first_link (&loader->messages);
04245 }
04246 
04253 void
04254 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04255                                            DBusList           *link)
04256 {
04257   _dbus_list_prepend_link (&loader->messages, link);
04258 }
04259 
04269 dbus_bool_t
04270 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04271 {
04272   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04273                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04274   return loader->corrupted;
04275 }
04276 
04283 DBusValidity
04284 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04285 {
04286   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04287                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04288 
04289   return loader->corruption_reason;
04290 }
04291 
04298 void
04299 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04300                                            long                size)
04301 {
04302   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04303     {
04304       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04305                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04306       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04307     }
04308   loader->max_message_size = size;
04309 }
04310 
04317 long
04318 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04319 {
04320   return loader->max_message_size;
04321 }
04322 
04329 void
04330 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04331                                                long                n)
04332 {
04333   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04334     {
04335       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04336                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04337       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04338     }
04339   loader->max_message_unix_fds = n;
04340 }
04341 
04348 long
04349 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04350 {
04351   return loader->max_message_unix_fds;
04352 }
04353 
04354 static DBusDataSlotAllocator slot_allocator;
04355 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
04356 
04371 dbus_bool_t
04372 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04373 {
04374   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04375                                           &_DBUS_LOCK_NAME (message_slots),
04376                                           slot_p);
04377 }
04378 
04390 void
04391 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04392 {
04393   _dbus_return_if_fail (*slot_p >= 0);
04394 
04395   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04396 }
04397 
04411 dbus_bool_t
04412 dbus_message_set_data (DBusMessage     *message,
04413                        dbus_int32_t     slot,
04414                        void            *data,
04415                        DBusFreeFunction free_data_func)
04416 {
04417   DBusFreeFunction old_free_func;
04418   void *old_data;
04419   dbus_bool_t retval;
04420 
04421   _dbus_return_val_if_fail (message != NULL, FALSE);
04422   _dbus_return_val_if_fail (slot >= 0, FALSE);
04423 
04424   retval = _dbus_data_slot_list_set (&slot_allocator,
04425                                      &message->slot_list,
04426                                      slot, data, free_data_func,
04427                                      &old_free_func, &old_data);
04428 
04429   if (retval)
04430     {
04431       /* Do the actual free outside the message lock */
04432       if (old_free_func)
04433         (* old_free_func) (old_data);
04434     }
04435 
04436   return retval;
04437 }
04438 
04447 void*
04448 dbus_message_get_data (DBusMessage   *message,
04449                        dbus_int32_t   slot)
04450 {
04451   void *res;
04452 
04453   _dbus_return_val_if_fail (message != NULL, NULL);
04454 
04455   res = _dbus_data_slot_list_get (&slot_allocator,
04456                                   &message->slot_list,
04457                                   slot);
04458 
04459   return res;
04460 }
04461 
04475 int
04476 dbus_message_type_from_string (const char *type_str)
04477 {
04478   if (strcmp (type_str, "method_call") == 0)
04479     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04480   if (strcmp (type_str, "method_return") == 0)
04481     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04482   else if (strcmp (type_str, "signal") == 0)
04483     return DBUS_MESSAGE_TYPE_SIGNAL;
04484   else if (strcmp (type_str, "error") == 0)
04485     return DBUS_MESSAGE_TYPE_ERROR;
04486   else
04487     return DBUS_MESSAGE_TYPE_INVALID;
04488 }
04489 
04503 const char *
04504 dbus_message_type_to_string (int type)
04505 {
04506   switch (type)
04507     {
04508     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04509       return "method_call";
04510     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04511       return "method_return";
04512     case DBUS_MESSAGE_TYPE_SIGNAL:
04513       return "signal";
04514     case DBUS_MESSAGE_TYPE_ERROR:
04515       return "error";
04516     default:
04517       return "invalid";
04518     }
04519 }
04520 
04533 dbus_bool_t
04534 dbus_message_marshal (DBusMessage  *msg,
04535                       char        **marshalled_data_p,
04536                       int          *len_p)
04537 {
04538   DBusString tmp;
04539   dbus_bool_t was_locked;
04540 
04541   _dbus_return_val_if_fail (msg != NULL, FALSE);
04542   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04543   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04544   
04545   if (!_dbus_string_init (&tmp))
04546     return FALSE;
04547 
04548   /* Ensure the message is locked, to ensure the length header is filled in. */
04549   was_locked = msg->locked;
04550 
04551   if (!was_locked)
04552     dbus_message_lock (msg);
04553 
04554   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04555     goto fail;
04556 
04557   *len_p = _dbus_string_get_length (&tmp);
04558 
04559   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04560     goto fail;
04561 
04562   *len_p = _dbus_string_get_length (&tmp);
04563 
04564   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04565     goto fail;
04566 
04567   _dbus_string_free (&tmp);
04568 
04569   if (!was_locked)
04570     msg->locked = FALSE;
04571 
04572   return TRUE;
04573 
04574  fail:
04575   _dbus_string_free (&tmp);
04576 
04577   if (!was_locked)
04578     msg->locked = FALSE;
04579 
04580   return FALSE;
04581 }
04582 
04595 DBusMessage *
04596 dbus_message_demarshal (const char *str,
04597                         int         len,
04598                         DBusError  *error)
04599 {
04600   DBusMessageLoader *loader;
04601   DBusString *buffer;
04602   DBusMessage *msg;
04603 
04604   _dbus_return_val_if_fail (str != NULL, NULL);
04605 
04606   loader = _dbus_message_loader_new ();
04607 
04608   if (loader == NULL)
04609     return NULL;
04610 
04611   _dbus_message_loader_get_buffer (loader, &buffer);
04612   _dbus_string_append_len (buffer, str, len);
04613   _dbus_message_loader_return_buffer (loader, buffer, len);
04614 
04615   if (!_dbus_message_loader_queue_messages (loader))
04616     goto fail_oom;
04617 
04618   if (_dbus_message_loader_get_is_corrupted (loader))
04619     goto fail_corrupt;
04620 
04621   msg = _dbus_message_loader_pop_message (loader);
04622 
04623   if (!msg)
04624     goto fail_oom;
04625 
04626   _dbus_message_loader_unref (loader);
04627   return msg;
04628 
04629  fail_corrupt:
04630   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04631                   _dbus_validity_to_error_message (loader->corruption_reason));
04632   _dbus_message_loader_unref (loader);
04633   return NULL;
04634 
04635  fail_oom:
04636   _DBUS_SET_OOM (error);
04637   _dbus_message_loader_unref (loader);
04638   return NULL;
04639 }
04640 
04654 int 
04655 dbus_message_demarshal_bytes_needed(const char *buf, 
04656                                     int         len)
04657 {
04658   DBusString str;
04659   int byte_order, fields_array_len, header_len, body_len;
04660   DBusValidity validity = DBUS_VALID;
04661   int have_message;
04662 
04663   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04664     return 0;
04665 
04666   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04667     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04668   _dbus_string_init_const_len (&str, buf, len);
04669   
04670   validity = DBUS_VALID;
04671   have_message
04672     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04673                                           &validity, &byte_order,
04674                                           &fields_array_len,
04675                                           &header_len,
04676                                           &body_len,
04677                                           &str, 0,
04678                                           len);
04679   _dbus_string_free (&str);
04680 
04681   if (validity == DBUS_VALID)
04682     {
04683       _dbus_assert(have_message);
04684       return header_len + body_len;
04685     }
04686   else
04687     {
04688       return -1; /* broken! */
04689     }
04690 }
04691 
04694 /* tests in dbus-message-util.c */