D-Bus 1.4.6
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   if (!_dbus_message_iter_open_signature (real))
02519     return FALSE;
02520 
02521   if (type == DBUS_TYPE_UNIX_FD)
02522     {
02523 #ifdef HAVE_UNIX_FD_PASSING
02524       int *fds;
02525       dbus_uint32_t u;
02526 
02527       /* First step, include the fd in the fd list of this message */
02528       if (!(fds = expand_fd_array(real->message, 1)))
02529         return FALSE;
02530 
02531       *fds = _dbus_dup(*(int*) value, NULL);
02532       if (*fds < 0)
02533         return FALSE;
02534 
02535       u = real->message->n_unix_fds;
02536 
02537       /* Second step, write the index to the fd */
02538       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02539         _dbus_close(*fds, NULL);
02540         return FALSE;
02541       }
02542 
02543       real->message->n_unix_fds += 1;
02544       u += 1;
02545 
02546       /* Final step, update the header accordingly */
02547       ret = _dbus_header_set_field_basic (&real->message->header,
02548                                           DBUS_HEADER_FIELD_UNIX_FDS,
02549                                           DBUS_TYPE_UINT32,
02550                                           &u);
02551 
02552       /* If any of these operations fail the message is
02553          hosed. However, no memory or fds should be leaked since what
02554          has been added to message has been added to the message, and
02555          can hence be accounted for when the message is being
02556          freed. */
02557 #else
02558       ret = FALSE;
02559 #endif
02560     }
02561   else
02562     {
02563       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02564     }
02565 
02566   if (!_dbus_message_iter_close_signature (real))
02567     ret = FALSE;
02568 
02569   return ret;
02570 }
02571 
02611 dbus_bool_t
02612 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02613                                       int              element_type,
02614                                       const void      *value,
02615                                       int              n_elements)
02616 {
02617   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02618   dbus_bool_t ret;
02619 
02620   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02621   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02622   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02623   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02624   _dbus_return_val_if_fail (value != NULL, FALSE);
02625   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02626   _dbus_return_val_if_fail (n_elements <=
02627                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02628                             FALSE);
02629 
02630   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02631 
02632   return ret;
02633 }
02634 
02656 dbus_bool_t
02657 dbus_message_iter_open_container (DBusMessageIter *iter,
02658                                   int              type,
02659                                   const char      *contained_signature,
02660                                   DBusMessageIter *sub)
02661 {
02662   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02663   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02664   DBusString contained_str;
02665 
02666   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02667   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02668   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02669   _dbus_return_val_if_fail (sub != NULL, FALSE);
02670   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02671                              contained_signature == NULL) ||
02672                             (type == DBUS_TYPE_DICT_ENTRY &&
02673                              contained_signature == NULL) ||
02674                             (type == DBUS_TYPE_VARIANT &&
02675                              contained_signature != NULL) ||
02676                             (type == DBUS_TYPE_ARRAY &&
02677                              contained_signature != NULL), FALSE);
02678   
02679   /* this would fail if the contained_signature is a dict entry, since
02680    * dict entries are invalid signatures standalone (they must be in
02681    * an array)
02682    */
02683   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02684                             (contained_signature == NULL ||
02685                              _dbus_check_is_valid_signature (contained_signature)),
02686                             FALSE);
02687 
02688   if (!_dbus_message_iter_open_signature (real))
02689     return FALSE;
02690 
02691   *real_sub = *real;
02692 
02693   if (contained_signature != NULL)
02694     {
02695       _dbus_string_init_const (&contained_str, contained_signature);
02696 
02697       return _dbus_type_writer_recurse (&real->u.writer,
02698                                         type,
02699                                         &contained_str, 0,
02700                                         &real_sub->u.writer);
02701     }
02702   else
02703     {
02704       return _dbus_type_writer_recurse (&real->u.writer,
02705                                         type,
02706                                         NULL, 0,
02707                                         &real_sub->u.writer);
02708     } 
02709 }
02710 
02711 
02725 dbus_bool_t
02726 dbus_message_iter_close_container (DBusMessageIter *iter,
02727                                    DBusMessageIter *sub)
02728 {
02729   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02730   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02731   dbus_bool_t ret;
02732 
02733   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02734   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02735   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02736   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02737 
02738   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02739                                      &real_sub->u.writer);
02740 
02741   if (!_dbus_message_iter_close_signature (real))
02742     ret = FALSE;
02743 
02744   return ret;
02745 }
02746 
02758 void
02759 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02760                                      DBusMessageIter *sub)
02761 {
02762   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02763   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02764 
02765   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02766   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02767   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02768   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02769 
02770   _dbus_message_iter_abandon_signature (real);
02771 }
02772 
02789 void
02790 dbus_message_set_no_reply (DBusMessage *message,
02791                            dbus_bool_t  no_reply)
02792 {
02793   _dbus_return_if_fail (message != NULL);
02794   _dbus_return_if_fail (!message->locked);
02795 
02796   _dbus_header_toggle_flag (&message->header,
02797                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02798                             no_reply);
02799 }
02800 
02808 dbus_bool_t
02809 dbus_message_get_no_reply (DBusMessage *message)
02810 {
02811   _dbus_return_val_if_fail (message != NULL, FALSE);
02812 
02813   return _dbus_header_get_flag (&message->header,
02814                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02815 }
02816 
02831 void
02832 dbus_message_set_auto_start (DBusMessage *message,
02833                              dbus_bool_t  auto_start)
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_AUTO_START,
02840                             !auto_start);
02841 }
02842 
02850 dbus_bool_t
02851 dbus_message_get_auto_start (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_AUTO_START);
02857 }
02858 
02859 
02872 dbus_bool_t
02873 dbus_message_set_path (DBusMessage   *message,
02874                        const char    *object_path)
02875 {
02876   _dbus_return_val_if_fail (message != NULL, FALSE);
02877   _dbus_return_val_if_fail (!message->locked, FALSE);
02878   _dbus_return_val_if_fail (object_path == NULL ||
02879                             _dbus_check_is_valid_path (object_path),
02880                             FALSE);
02881 
02882   return set_or_delete_string_field (message,
02883                                      DBUS_HEADER_FIELD_PATH,
02884                                      DBUS_TYPE_OBJECT_PATH,
02885                                      object_path);
02886 }
02887 
02901 const char*
02902 dbus_message_get_path (DBusMessage   *message)
02903 {
02904   const char *v;
02905 
02906   _dbus_return_val_if_fail (message != NULL, NULL);
02907 
02908   v = NULL; /* in case field doesn't exist */
02909   _dbus_header_get_field_basic (&message->header,
02910                                 DBUS_HEADER_FIELD_PATH,
02911                                 DBUS_TYPE_OBJECT_PATH,
02912                                 (void *) &v);
02913   return v;
02914 }
02915 
02925 dbus_bool_t
02926 dbus_message_has_path (DBusMessage   *message,
02927                        const char    *path)
02928 {
02929   const char *msg_path;
02930   msg_path = dbus_message_get_path (message);
02931   
02932   if (msg_path == NULL)
02933     {
02934       if (path == NULL)
02935         return TRUE;
02936       else
02937         return FALSE;
02938     }
02939 
02940   if (path == NULL)
02941     return FALSE;
02942    
02943   if (strcmp (msg_path, path) == 0)
02944     return TRUE;
02945 
02946   return FALSE;
02947 }
02948 
02969 dbus_bool_t
02970 dbus_message_get_path_decomposed (DBusMessage   *message,
02971                                   char        ***path)
02972 {
02973   const char *v;
02974 
02975   _dbus_return_val_if_fail (message != NULL, FALSE);
02976   _dbus_return_val_if_fail (path != NULL, FALSE);
02977 
02978   *path = NULL;
02979 
02980   v = dbus_message_get_path (message);
02981   if (v != NULL)
02982     {
02983       if (!_dbus_decompose_path (v, strlen (v),
02984                                  path, NULL))
02985         return FALSE;
02986     }
02987   return TRUE;
02988 }
02989 
03003 dbus_bool_t
03004 dbus_message_set_interface (DBusMessage  *message,
03005                             const char   *interface)
03006 {
03007   _dbus_return_val_if_fail (message != NULL, FALSE);
03008   _dbus_return_val_if_fail (!message->locked, FALSE);
03009   _dbus_return_val_if_fail (interface == NULL ||
03010                             _dbus_check_is_valid_interface (interface),
03011                             FALSE);
03012 
03013   return set_or_delete_string_field (message,
03014                                      DBUS_HEADER_FIELD_INTERFACE,
03015                                      DBUS_TYPE_STRING,
03016                                      interface);
03017 }
03018 
03032 const char*
03033 dbus_message_get_interface (DBusMessage *message)
03034 {
03035   const char *v;
03036 
03037   _dbus_return_val_if_fail (message != NULL, NULL);
03038 
03039   v = NULL; /* in case field doesn't exist */
03040   _dbus_header_get_field_basic (&message->header,
03041                                 DBUS_HEADER_FIELD_INTERFACE,
03042                                 DBUS_TYPE_STRING,
03043                                 (void *) &v);
03044   return v;
03045 }
03046 
03054 dbus_bool_t
03055 dbus_message_has_interface (DBusMessage   *message,
03056                             const char    *interface)
03057 {
03058   const char *msg_interface;
03059   msg_interface = dbus_message_get_interface (message);
03060    
03061   if (msg_interface == NULL)
03062     {
03063       if (interface == NULL)
03064         return TRUE;
03065       else
03066         return FALSE;
03067     }
03068 
03069   if (interface == NULL)
03070     return FALSE;
03071      
03072   if (strcmp (msg_interface, interface) == 0)
03073     return TRUE;
03074 
03075   return FALSE;
03076 
03077 }
03078 
03091 dbus_bool_t
03092 dbus_message_set_member (DBusMessage  *message,
03093                          const char   *member)
03094 {
03095   _dbus_return_val_if_fail (message != NULL, FALSE);
03096   _dbus_return_val_if_fail (!message->locked, FALSE);
03097   _dbus_return_val_if_fail (member == NULL ||
03098                             _dbus_check_is_valid_member (member),
03099                             FALSE);
03100 
03101   return set_or_delete_string_field (message,
03102                                      DBUS_HEADER_FIELD_MEMBER,
03103                                      DBUS_TYPE_STRING,
03104                                      member);
03105 }
03106 
03118 const char*
03119 dbus_message_get_member (DBusMessage *message)
03120 {
03121   const char *v;
03122 
03123   _dbus_return_val_if_fail (message != NULL, NULL);
03124 
03125   v = NULL; /* in case field doesn't exist */
03126   _dbus_header_get_field_basic (&message->header,
03127                                 DBUS_HEADER_FIELD_MEMBER,
03128                                 DBUS_TYPE_STRING,
03129                                 (void *) &v);
03130   return v;
03131 }
03132 
03140 dbus_bool_t
03141 dbus_message_has_member (DBusMessage   *message,
03142                          const char    *member)
03143 {
03144   const char *msg_member;
03145   msg_member = dbus_message_get_member (message);
03146  
03147   if (msg_member == NULL)
03148     {
03149       if (member == NULL)
03150         return TRUE;
03151       else
03152         return FALSE;
03153     }
03154 
03155   if (member == NULL)
03156     return FALSE;
03157     
03158   if (strcmp (msg_member, member) == 0)
03159     return TRUE;
03160 
03161   return FALSE;
03162 
03163 }
03164 
03176 dbus_bool_t
03177 dbus_message_set_error_name (DBusMessage  *message,
03178                              const char   *error_name)
03179 {
03180   _dbus_return_val_if_fail (message != NULL, FALSE);
03181   _dbus_return_val_if_fail (!message->locked, FALSE);
03182   _dbus_return_val_if_fail (error_name == NULL ||
03183                             _dbus_check_is_valid_error_name (error_name),
03184                             FALSE);
03185 
03186   return set_or_delete_string_field (message,
03187                                      DBUS_HEADER_FIELD_ERROR_NAME,
03188                                      DBUS_TYPE_STRING,
03189                                      error_name);
03190 }
03191 
03202 const char*
03203 dbus_message_get_error_name (DBusMessage *message)
03204 {
03205   const char *v;
03206 
03207   _dbus_return_val_if_fail (message != NULL, NULL);
03208 
03209   v = NULL; /* in case field doesn't exist */
03210   _dbus_header_get_field_basic (&message->header,
03211                                 DBUS_HEADER_FIELD_ERROR_NAME,
03212                                 DBUS_TYPE_STRING,
03213                                 (void *) &v);
03214   return v;
03215 }
03216 
03230 dbus_bool_t
03231 dbus_message_set_destination (DBusMessage  *message,
03232                               const char   *destination)
03233 {
03234   _dbus_return_val_if_fail (message != NULL, FALSE);
03235   _dbus_return_val_if_fail (!message->locked, FALSE);
03236   _dbus_return_val_if_fail (destination == NULL ||
03237                             _dbus_check_is_valid_bus_name (destination),
03238                             FALSE);
03239 
03240   return set_or_delete_string_field (message,
03241                                      DBUS_HEADER_FIELD_DESTINATION,
03242                                      DBUS_TYPE_STRING,
03243                                      destination);
03244 }
03245 
03255 const char*
03256 dbus_message_get_destination (DBusMessage *message)
03257 {
03258   const char *v;
03259 
03260   _dbus_return_val_if_fail (message != NULL, NULL);
03261 
03262   v = NULL; /* in case field doesn't exist */
03263   _dbus_header_get_field_basic (&message->header,
03264                                 DBUS_HEADER_FIELD_DESTINATION,
03265                                 DBUS_TYPE_STRING,
03266                                 (void *) &v);
03267   return v;
03268 }
03269 
03284 dbus_bool_t
03285 dbus_message_set_sender (DBusMessage  *message,
03286                          const char   *sender)
03287 {
03288   _dbus_return_val_if_fail (message != NULL, FALSE);
03289   _dbus_return_val_if_fail (!message->locked, FALSE);
03290   _dbus_return_val_if_fail (sender == NULL ||
03291                             _dbus_check_is_valid_bus_name (sender),
03292                             FALSE);
03293 
03294   return set_or_delete_string_field (message,
03295                                      DBUS_HEADER_FIELD_SENDER,
03296                                      DBUS_TYPE_STRING,
03297                                      sender);
03298 }
03299 
03315 const char*
03316 dbus_message_get_sender (DBusMessage *message)
03317 {
03318   const char *v;
03319 
03320   _dbus_return_val_if_fail (message != NULL, NULL);
03321 
03322   v = NULL; /* in case field doesn't exist */
03323   _dbus_header_get_field_basic (&message->header,
03324                                 DBUS_HEADER_FIELD_SENDER,
03325                                 DBUS_TYPE_STRING,
03326                                 (void *) &v);
03327   return v;
03328 }
03329 
03348 const char*
03349 dbus_message_get_signature (DBusMessage *message)
03350 {
03351   const DBusString *type_str;
03352   int type_pos;
03353 
03354   _dbus_return_val_if_fail (message != NULL, NULL);
03355 
03356   get_const_signature (&message->header, &type_str, &type_pos);
03357 
03358   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03359 }
03360 
03361 static dbus_bool_t
03362 _dbus_message_has_type_interface_member (DBusMessage *message,
03363                                          int          type,
03364                                          const char  *interface,
03365                                          const char  *member)
03366 {
03367   const char *n;
03368 
03369   _dbus_assert (message != NULL);
03370   _dbus_assert (interface != NULL);
03371   _dbus_assert (member != NULL);
03372 
03373   if (dbus_message_get_type (message) != type)
03374     return FALSE;
03375 
03376   /* Optimize by checking the short member name first
03377    * instead of the longer interface name
03378    */
03379 
03380   n = dbus_message_get_member (message);
03381 
03382   if (n && strcmp (n, member) == 0)
03383     {
03384       n = dbus_message_get_interface (message);
03385 
03386       if (n == NULL || strcmp (n, interface) == 0)
03387         return TRUE;
03388     }
03389 
03390   return FALSE;
03391 }
03392 
03407 dbus_bool_t
03408 dbus_message_is_method_call (DBusMessage *message,
03409                              const char  *interface,
03410                              const char  *method)
03411 {
03412   _dbus_return_val_if_fail (message != NULL, FALSE);
03413   _dbus_return_val_if_fail (interface != NULL, FALSE);
03414   _dbus_return_val_if_fail (method != NULL, FALSE);
03415   /* don't check that interface/method are valid since it would be
03416    * expensive, and not catch many common errors
03417    */
03418 
03419   return _dbus_message_has_type_interface_member (message,
03420                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03421                                                   interface, method);
03422 }
03423 
03435 dbus_bool_t
03436 dbus_message_is_signal (DBusMessage *message,
03437                         const char  *interface,
03438                         const char  *signal_name)
03439 {
03440   _dbus_return_val_if_fail (message != NULL, FALSE);
03441   _dbus_return_val_if_fail (interface != NULL, FALSE);
03442   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03443   /* don't check that interface/name are valid since it would be
03444    * expensive, and not catch many common errors
03445    */
03446 
03447   return _dbus_message_has_type_interface_member (message,
03448                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03449                                                   interface, signal_name);
03450 }
03451 
03462 dbus_bool_t
03463 dbus_message_is_error (DBusMessage *message,
03464                        const char  *error_name)
03465 {
03466   const char *n;
03467 
03468   _dbus_return_val_if_fail (message != NULL, FALSE);
03469   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03470   /* don't check that error_name is valid since it would be expensive,
03471    * and not catch many common errors
03472    */
03473 
03474   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03475     return FALSE;
03476 
03477   n = dbus_message_get_error_name (message);
03478 
03479   if (n && strcmp (n, error_name) == 0)
03480     return TRUE;
03481   else
03482     return FALSE;
03483 }
03484 
03495 dbus_bool_t
03496 dbus_message_has_destination (DBusMessage  *message,
03497                               const char   *name)
03498 {
03499   const char *s;
03500 
03501   _dbus_return_val_if_fail (message != NULL, FALSE);
03502   _dbus_return_val_if_fail (name != NULL, FALSE);
03503   /* don't check that name is valid since it would be expensive, and
03504    * not catch many common errors
03505    */
03506 
03507   s = dbus_message_get_destination (message);
03508 
03509   if (s && strcmp (s, name) == 0)
03510     return TRUE;
03511   else
03512     return FALSE;
03513 }
03514 
03530 dbus_bool_t
03531 dbus_message_has_sender (DBusMessage  *message,
03532                          const char   *name)
03533 {
03534   const char *s;
03535 
03536   _dbus_return_val_if_fail (message != NULL, FALSE);
03537   _dbus_return_val_if_fail (name != NULL, FALSE);
03538   /* don't check that name is valid since it would be expensive, and
03539    * not catch many common errors
03540    */
03541 
03542   s = dbus_message_get_sender (message);
03543 
03544   if (s && strcmp (s, name) == 0)
03545     return TRUE;
03546   else
03547     return FALSE;
03548 }
03549 
03559 dbus_bool_t
03560 dbus_message_has_signature (DBusMessage   *message,
03561                             const char    *signature)
03562 {
03563   const char *s;
03564 
03565   _dbus_return_val_if_fail (message != NULL, FALSE);
03566   _dbus_return_val_if_fail (signature != NULL, FALSE);
03567   /* don't check that signature is valid since it would be expensive,
03568    * and not catch many common errors
03569    */
03570 
03571   s = dbus_message_get_signature (message);
03572 
03573   if (s && strcmp (s, signature) == 0)
03574     return TRUE;
03575   else
03576     return FALSE;
03577 }
03578 
03601 dbus_bool_t
03602 dbus_set_error_from_message (DBusError   *error,
03603                              DBusMessage *message)
03604 {
03605   const char *str;
03606 
03607   _dbus_return_val_if_fail (message != NULL, FALSE);
03608   _dbus_return_val_if_error_is_set (error, FALSE);
03609 
03610   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03611     return FALSE;
03612 
03613   str = NULL;
03614   dbus_message_get_args (message, NULL,
03615                          DBUS_TYPE_STRING, &str,
03616                          DBUS_TYPE_INVALID);
03617 
03618   dbus_set_error (error, dbus_message_get_error_name (message),
03619                   str ? "%s" : NULL, str);
03620 
03621   return TRUE;
03622 }
03623 
03630 dbus_bool_t
03631 dbus_message_contains_unix_fds(DBusMessage *message)
03632 {
03633 #ifdef HAVE_UNIX_FD_PASSING
03634   _dbus_assert(message);
03635 
03636   return message->n_unix_fds > 0;
03637 #else
03638   return FALSE;
03639 #endif
03640 }
03641 
03660 #define INITIAL_LOADER_DATA_LEN 32
03661 
03668 DBusMessageLoader*
03669 _dbus_message_loader_new (void)
03670 {
03671   DBusMessageLoader *loader;
03672 
03673   loader = dbus_new0 (DBusMessageLoader, 1);
03674   if (loader == NULL)
03675     return NULL;
03676   
03677   loader->refcount = 1;
03678 
03679   loader->corrupted = FALSE;
03680   loader->corruption_reason = DBUS_VALID;
03681 
03682   /* this can be configured by the app, but defaults to the protocol max */
03683   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03684 
03685   /* We set a very relatively conservative default here since due to how
03686   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03687   number of unix fds we want to receive in advance. A
03688   try-and-reallocate loop is not possible. */
03689   loader->max_message_unix_fds = 1024;
03690 
03691   if (!_dbus_string_init (&loader->data))
03692     {
03693       dbus_free (loader);
03694       return NULL;
03695     }
03696 
03697   /* preallocate the buffer for speed, ignore failure */
03698   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03699   _dbus_string_set_length (&loader->data, 0);
03700 
03701 #ifdef HAVE_UNIX_FD_PASSING
03702   loader->unix_fds = NULL;
03703   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03704   loader->unix_fds_outstanding = FALSE;
03705 #endif
03706 
03707   return loader;
03708 }
03709 
03716 DBusMessageLoader *
03717 _dbus_message_loader_ref (DBusMessageLoader *loader)
03718 {
03719   loader->refcount += 1;
03720 
03721   return loader;
03722 }
03723 
03730 void
03731 _dbus_message_loader_unref (DBusMessageLoader *loader)
03732 {
03733   loader->refcount -= 1;
03734   if (loader->refcount == 0)
03735     {
03736 #ifdef HAVE_UNIX_FD_PASSING
03737       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
03738       dbus_free(loader->unix_fds);
03739 #endif
03740       _dbus_list_foreach (&loader->messages,
03741                           (DBusForeachFunction) dbus_message_unref,
03742                           NULL);
03743       _dbus_list_clear (&loader->messages);
03744       _dbus_string_free (&loader->data);
03745       dbus_free (loader);
03746     }
03747 }
03748 
03767 void
03768 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03769                                  DBusString        **buffer)
03770 {
03771   _dbus_assert (!loader->buffer_outstanding);
03772 
03773   *buffer = &loader->data;
03774 
03775   loader->buffer_outstanding = TRUE;
03776 }
03777 
03788 void
03789 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03790                                     DBusString         *buffer,
03791                                     int                 bytes_read)
03792 {
03793   _dbus_assert (loader->buffer_outstanding);
03794   _dbus_assert (buffer == &loader->data);
03795 
03796   loader->buffer_outstanding = FALSE;
03797 }
03798 
03809 dbus_bool_t
03810 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
03811                                   int               **fds,
03812                                   unsigned           *max_n_fds)
03813 {
03814 #ifdef HAVE_UNIX_FD_PASSING
03815   _dbus_assert (!loader->unix_fds_outstanding);
03816 
03817   /* Allocate space where we can put the fds we read. We allocate
03818      space for max_message_unix_fds since this is an
03819      upper limit how many fds can be received within a single
03820      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
03821      we are allocating the maximum possible array size right from the
03822      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
03823      there is no better way. */
03824 
03825   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
03826     {
03827       int *a = dbus_realloc(loader->unix_fds,
03828                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
03829 
03830       if (!a)
03831         return FALSE;
03832 
03833       loader->unix_fds = a;
03834       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
03835     }
03836 
03837   *fds = loader->unix_fds + loader->n_unix_fds;
03838   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
03839 
03840   loader->unix_fds_outstanding = TRUE;
03841   return TRUE;
03842 #else
03843   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03844   return FALSE;
03845 #endif
03846 }
03847 
03858 void
03859 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
03860                                      int                *fds,
03861                                      unsigned            n_fds)
03862 {
03863 #ifdef HAVE_UNIX_FD_PASSING
03864   _dbus_assert(loader->unix_fds_outstanding);
03865   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
03866   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
03867 
03868   loader->n_unix_fds += n_fds;
03869   loader->unix_fds_outstanding = FALSE;
03870 #else
03871   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03872 #endif
03873 }
03874 
03875 /*
03876  * FIXME when we move the header out of the buffer, that memmoves all
03877  * buffered messages. Kind of crappy.
03878  *
03879  * Also we copy the header and body, which is kind of crappy.  To
03880  * avoid this, we have to allow header and body to be in a single
03881  * memory block, which is good for messages we read and bad for
03882  * messages we are creating. But we could move_len() the buffer into
03883  * this single memory block, and move_len() will just swap the buffers
03884  * if you're moving the entire buffer replacing the dest string.
03885  *
03886  * We could also have the message loader tell the transport how many
03887  * bytes to read; so it would first ask for some arbitrary number like
03888  * 256, then if the message was incomplete it would use the
03889  * header/body len to ask for exactly the size of the message (or
03890  * blocks the size of a typical kernel buffer for the socket). That
03891  * way we don't get trailing bytes in the buffer that have to be
03892  * memmoved. Though I suppose we also don't have a chance of reading a
03893  * bunch of small messages at once, so the optimization may be stupid.
03894  *
03895  * Another approach would be to keep a "start" index into
03896  * loader->data and only delete it occasionally, instead of after
03897  * each message is loaded.
03898  *
03899  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03900  */
03901 static dbus_bool_t
03902 load_message (DBusMessageLoader *loader,
03903               DBusMessage       *message,
03904               int                byte_order,
03905               int                fields_array_len,
03906               int                header_len,
03907               int                body_len)
03908 {
03909   dbus_bool_t oom;
03910   DBusValidity validity;
03911   const DBusString *type_str;
03912   int type_pos;
03913   DBusValidationMode mode;
03914   dbus_uint32_t n_unix_fds = 0;
03915 
03916   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03917   
03918   oom = FALSE;
03919 
03920 #if 0
03921   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03922 #endif
03923 
03924   /* 1. VALIDATE AND COPY OVER HEADER */
03925   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03926   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03927 
03928   if (!_dbus_header_load (&message->header,
03929                           mode,
03930                           &validity,
03931                           byte_order,
03932                           fields_array_len,
03933                           header_len,
03934                           body_len,
03935                           &loader->data, 0,
03936                           _dbus_string_get_length (&loader->data)))
03937     {
03938       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03939 
03940       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03941          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03942       _dbus_assert (validity != DBUS_VALID);
03943 
03944       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03945         oom = TRUE;
03946       else
03947         {
03948           loader->corrupted = TRUE;
03949           loader->corruption_reason = validity;
03950         }
03951       goto failed;
03952     }
03953 
03954   _dbus_assert (validity == DBUS_VALID);
03955 
03956   message->byte_order = byte_order;
03957 
03958   /* 2. VALIDATE BODY */
03959   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
03960     {
03961       get_const_signature (&message->header, &type_str, &type_pos);
03962       
03963       /* Because the bytes_remaining arg is NULL, this validates that the
03964        * body is the right length
03965        */
03966       validity = _dbus_validate_body_with_reason (type_str,
03967                                                   type_pos,
03968                                                   byte_order,
03969                                                   NULL,
03970                                                   &loader->data,
03971                                                   header_len,
03972                                                   body_len);
03973       if (validity != DBUS_VALID)
03974         {
03975           _dbus_verbose ("Failed to validate message body code %d\n", validity);
03976 
03977           loader->corrupted = TRUE;
03978           loader->corruption_reason = validity;
03979           
03980           goto failed;
03981         }
03982     }
03983 
03984   /* 3. COPY OVER UNIX FDS */
03985   _dbus_header_get_field_basic(&message->header,
03986                                DBUS_HEADER_FIELD_UNIX_FDS,
03987                                DBUS_TYPE_UINT32,
03988                                &n_unix_fds);
03989 
03990 #ifdef HAVE_UNIX_FD_PASSING
03991 
03992   if (n_unix_fds > loader->n_unix_fds)
03993     {
03994       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
03995                     n_unix_fds, loader->n_unix_fds);
03996 
03997       loader->corrupted = TRUE;
03998       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
03999       goto failed;
04000     }
04001 
04002   /* If this was a recycled message there might still be
04003      some memory allocated for the fds */
04004   dbus_free(message->unix_fds);
04005 
04006   if (n_unix_fds > 0)
04007     {
04008       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04009       if (message->unix_fds == NULL)
04010         {
04011           _dbus_verbose ("Failed to allocate file descriptor array\n");
04012           oom = TRUE;
04013           goto failed;
04014         }
04015 
04016       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04017       loader->n_unix_fds -= n_unix_fds;
04018       memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds);
04019     }
04020   else
04021     message->unix_fds = NULL;
04022 
04023 #else
04024 
04025   if (n_unix_fds > 0)
04026     {
04027       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04028                      "but that's not supported on our platform, disconnecting.\n");
04029 
04030       loader->corrupted = TRUE;
04031       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04032       goto failed;
04033     }
04034 
04035 #endif
04036 
04037   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04038 
04039   if (!_dbus_list_append (&loader->messages, message))
04040     {
04041       _dbus_verbose ("Failed to append new message to loader queue\n");
04042       oom = TRUE;
04043       goto failed;
04044     }
04045 
04046   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04047   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04048                 (header_len + body_len));
04049 
04050   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04051     {
04052       _dbus_verbose ("Failed to move body into new message\n");
04053       oom = TRUE;
04054       goto failed;
04055     }
04056 
04057   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04058 
04059   /* don't waste more than 2k of memory */
04060   _dbus_string_compact (&loader->data, 2048);
04061 
04062   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04063   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04064 
04065   _dbus_verbose ("Loaded message %p\n", message);
04066 
04067   _dbus_assert (!oom);
04068   _dbus_assert (!loader->corrupted);
04069   _dbus_assert (loader->messages != NULL);
04070   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04071 
04072   return TRUE;
04073 
04074  failed:
04075 
04076   /* Clean up */
04077 
04078   /* does nothing if the message isn't in the list */
04079   _dbus_list_remove_last (&loader->messages, message);
04080   
04081   if (oom)
04082     _dbus_assert (!loader->corrupted);
04083   else
04084     _dbus_assert (loader->corrupted);
04085 
04086   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04087 
04088   return FALSE;
04089 }
04090 
04105 dbus_bool_t
04106 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04107 {
04108   while (!loader->corrupted &&
04109          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04110     {
04111       DBusValidity validity;
04112       int byte_order, fields_array_len, header_len, body_len;
04113 
04114       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04115                                                &validity,
04116                                                &byte_order,
04117                                                &fields_array_len,
04118                                                &header_len,
04119                                                &body_len,
04120                                                &loader->data, 0,
04121                                                _dbus_string_get_length (&loader->data)))
04122         {
04123           DBusMessage *message;
04124 
04125           _dbus_assert (validity == DBUS_VALID);
04126 
04127           message = dbus_message_new_empty_header ();
04128           if (message == NULL)
04129             return FALSE;
04130 
04131           if (!load_message (loader, message,
04132                              byte_order, fields_array_len,
04133                              header_len, body_len))
04134             {
04135               dbus_message_unref (message);
04136               /* load_message() returns false if corrupted or OOM; if
04137                * corrupted then return TRUE for not OOM
04138                */
04139               return loader->corrupted;
04140             }
04141 
04142           _dbus_assert (loader->messages != NULL);
04143           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04144         }
04145       else
04146         {
04147           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04148                          validity);
04149           if (validity != DBUS_VALID)
04150             {
04151               loader->corrupted = TRUE;
04152               loader->corruption_reason = validity;
04153             }
04154           return TRUE;
04155         }
04156     }
04157 
04158   return TRUE;
04159 }
04160 
04168 DBusMessage*
04169 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04170 {
04171   if (loader->messages)
04172     return loader->messages->data;
04173   else
04174     return NULL;
04175 }
04176 
04185 DBusMessage*
04186 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04187 {
04188   return _dbus_list_pop_first (&loader->messages);
04189 }
04190 
04199 DBusList*
04200 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04201 {
04202   return _dbus_list_pop_first_link (&loader->messages);
04203 }
04204 
04211 void
04212 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04213                                            DBusList           *link)
04214 {
04215   _dbus_list_prepend_link (&loader->messages, link);
04216 }
04217 
04227 dbus_bool_t
04228 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04229 {
04230   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04231                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04232   return loader->corrupted;
04233 }
04234 
04241 DBusValidity
04242 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04243 {
04244   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04245                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04246 
04247   return loader->corruption_reason;
04248 }
04249 
04256 void
04257 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04258                                            long                size)
04259 {
04260   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04261     {
04262       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04263                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04264       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04265     }
04266   loader->max_message_size = size;
04267 }
04268 
04275 long
04276 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04277 {
04278   return loader->max_message_size;
04279 }
04280 
04287 void
04288 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04289                                                long                n)
04290 {
04291   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04292     {
04293       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04294                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04295       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04296     }
04297   loader->max_message_unix_fds = n;
04298 }
04299 
04306 long
04307 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04308 {
04309   return loader->max_message_unix_fds;
04310 }
04311 
04312 static DBusDataSlotAllocator slot_allocator;
04313 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
04314 
04329 dbus_bool_t
04330 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04331 {
04332   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04333                                           &_DBUS_LOCK_NAME (message_slots),
04334                                           slot_p);
04335 }
04336 
04348 void
04349 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04350 {
04351   _dbus_return_if_fail (*slot_p >= 0);
04352 
04353   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04354 }
04355 
04369 dbus_bool_t
04370 dbus_message_set_data (DBusMessage     *message,
04371                        dbus_int32_t     slot,
04372                        void            *data,
04373                        DBusFreeFunction free_data_func)
04374 {
04375   DBusFreeFunction old_free_func;
04376   void *old_data;
04377   dbus_bool_t retval;
04378 
04379   _dbus_return_val_if_fail (message != NULL, FALSE);
04380   _dbus_return_val_if_fail (slot >= 0, FALSE);
04381 
04382   retval = _dbus_data_slot_list_set (&slot_allocator,
04383                                      &message->slot_list,
04384                                      slot, data, free_data_func,
04385                                      &old_free_func, &old_data);
04386 
04387   if (retval)
04388     {
04389       /* Do the actual free outside the message lock */
04390       if (old_free_func)
04391         (* old_free_func) (old_data);
04392     }
04393 
04394   return retval;
04395 }
04396 
04405 void*
04406 dbus_message_get_data (DBusMessage   *message,
04407                        dbus_int32_t   slot)
04408 {
04409   void *res;
04410 
04411   _dbus_return_val_if_fail (message != NULL, NULL);
04412 
04413   res = _dbus_data_slot_list_get (&slot_allocator,
04414                                   &message->slot_list,
04415                                   slot);
04416 
04417   return res;
04418 }
04419 
04433 int
04434 dbus_message_type_from_string (const char *type_str)
04435 {
04436   if (strcmp (type_str, "method_call") == 0)
04437     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04438   if (strcmp (type_str, "method_return") == 0)
04439     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04440   else if (strcmp (type_str, "signal") == 0)
04441     return DBUS_MESSAGE_TYPE_SIGNAL;
04442   else if (strcmp (type_str, "error") == 0)
04443     return DBUS_MESSAGE_TYPE_ERROR;
04444   else
04445     return DBUS_MESSAGE_TYPE_INVALID;
04446 }
04447 
04461 const char *
04462 dbus_message_type_to_string (int type)
04463 {
04464   switch (type)
04465     {
04466     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04467       return "method_call";
04468     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04469       return "method_return";
04470     case DBUS_MESSAGE_TYPE_SIGNAL:
04471       return "signal";
04472     case DBUS_MESSAGE_TYPE_ERROR:
04473       return "error";
04474     default:
04475       return "invalid";
04476     }
04477 }
04478 
04491 dbus_bool_t
04492 dbus_message_marshal (DBusMessage  *msg,
04493                       char        **marshalled_data_p,
04494                       int          *len_p)
04495 {
04496   DBusString tmp;
04497   dbus_bool_t was_locked;
04498 
04499   _dbus_return_val_if_fail (msg != NULL, FALSE);
04500   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04501   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04502   
04503   if (!_dbus_string_init (&tmp))
04504     return FALSE;
04505 
04506   /* Ensure the message is locked, to ensure the length header is filled in. */
04507   was_locked = msg->locked;
04508 
04509   if (!was_locked)
04510     dbus_message_lock (msg);
04511 
04512   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04513     goto fail;
04514 
04515   *len_p = _dbus_string_get_length (&tmp);
04516 
04517   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04518     goto fail;
04519 
04520   *len_p = _dbus_string_get_length (&tmp);
04521 
04522   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04523     goto fail;
04524 
04525   _dbus_string_free (&tmp);
04526 
04527   if (!was_locked)
04528     msg->locked = FALSE;
04529 
04530   return TRUE;
04531 
04532  fail:
04533   _dbus_string_free (&tmp);
04534 
04535   if (!was_locked)
04536     msg->locked = FALSE;
04537 
04538   return FALSE;
04539 }
04540 
04553 DBusMessage *
04554 dbus_message_demarshal (const char *str,
04555                         int         len,
04556                         DBusError  *error)
04557 {
04558   DBusMessageLoader *loader;
04559   DBusString *buffer;
04560   DBusMessage *msg;
04561 
04562   _dbus_return_val_if_fail (str != NULL, NULL);
04563 
04564   loader = _dbus_message_loader_new ();
04565 
04566   if (loader == NULL)
04567     return NULL;
04568 
04569   _dbus_message_loader_get_buffer (loader, &buffer);
04570   _dbus_string_append_len (buffer, str, len);
04571   _dbus_message_loader_return_buffer (loader, buffer, len);
04572 
04573   if (!_dbus_message_loader_queue_messages (loader))
04574     goto fail_oom;
04575 
04576   if (_dbus_message_loader_get_is_corrupted (loader))
04577     goto fail_corrupt;
04578 
04579   msg = _dbus_message_loader_pop_message (loader);
04580 
04581   if (!msg)
04582     goto fail_oom;
04583 
04584   _dbus_message_loader_unref (loader);
04585   return msg;
04586 
04587  fail_corrupt:
04588   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04589                   _dbus_validity_to_error_message (loader->corruption_reason));
04590   _dbus_message_loader_unref (loader);
04591   return NULL;
04592 
04593  fail_oom:
04594   _DBUS_SET_OOM (error);
04595   _dbus_message_loader_unref (loader);
04596   return NULL;
04597 }
04598 
04612 int 
04613 dbus_message_demarshal_bytes_needed(const char *buf, 
04614                                     int         len)
04615 {
04616   DBusString str;
04617   int byte_order, fields_array_len, header_len, body_len;
04618   DBusValidity validity = DBUS_VALID;
04619   int have_message;
04620 
04621   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04622     return 0;
04623 
04624   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04625     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04626   _dbus_string_init_const_len (&str, buf, len);
04627   
04628   validity = DBUS_VALID;
04629   have_message
04630     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04631                                           &validity, &byte_order,
04632                                           &fields_array_len,
04633                                           &header_len,
04634                                           &body_len,
04635                                           &str, 0,
04636                                           len);
04637   _dbus_string_free (&str);
04638 
04639   if (validity == DBUS_VALID)
04640     {
04641       _dbus_assert (have_message || (header_len + body_len) > len);
04642       return header_len + body_len;
04643     }
04644   else
04645     {
04646       return -1; /* broken! */
04647     }
04648 }
04649 
04652 /* tests in dbus-message-util.c */