D-Bus 1.4.20

dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-validate.h"
00029 #include "dbus-marshal-byteswap.h"
00030 #include "dbus-marshal-header.h"
00031 #include "dbus-signature.h"
00032 #include "dbus-message-private.h"
00033 #include "dbus-object-tree.h"
00034 #include "dbus-memory.h"
00035 #include "dbus-list.h"
00036 #include "dbus-threads-internal.h"
00037 #ifdef HAVE_UNIX_FD_PASSING
00038 #include "dbus-sysdeps-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 (_dbus_atomic_get (&message->refcount) == 0);
00530 
00531   _dbus_assert (message->counters == NULL);
00532   
00533   _DBUS_UNLOCK (message_cache);
00534 
00535   return message;
00536 }
00537 
00538 #ifdef HAVE_UNIX_FD_PASSING
00539 static void
00540 close_unix_fds(int *fds, unsigned *n_fds)
00541 {
00542   DBusError e;
00543   int i;
00544 
00545   if (*n_fds <= 0)
00546     return;
00547 
00548   dbus_error_init(&e);
00549 
00550   for (i = 0; i < *n_fds; i++)
00551     {
00552       if (!_dbus_close(fds[i], &e))
00553         {
00554           _dbus_warn("Failed to close file descriptor: %s\n", e.message);
00555           dbus_error_free(&e);
00556         }
00557     }
00558 
00559   *n_fds = 0;
00560 
00561   /* We don't free the array here, in case we can recycle it later */
00562 }
00563 #endif
00564 
00565 static void
00566 free_counter (void *element,
00567               void *data)
00568 {
00569   DBusCounter *counter = element;
00570   DBusMessage *message = data;
00571 
00572   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00573 #ifdef HAVE_UNIX_FD_PASSING
00574   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00575 #endif
00576 
00577   _dbus_counter_unref (counter);
00578 }
00579 
00585 static void
00586 dbus_message_cache_or_finalize (DBusMessage *message)
00587 {
00588   dbus_bool_t was_cached;
00589   int i;
00590 
00591   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00592 
00593   /* This calls application code and has to be done first thing
00594    * without holding the lock
00595    */
00596   _dbus_data_slot_list_clear (&message->slot_list);
00597 
00598   _dbus_list_foreach (&message->counters,
00599                       free_counter, message);
00600   _dbus_list_clear (&message->counters);
00601 
00602 #ifdef HAVE_UNIX_FD_PASSING
00603   close_unix_fds(message->unix_fds, &message->n_unix_fds);
00604 #endif
00605 
00606   was_cached = FALSE;
00607 
00608   _DBUS_LOCK (message_cache);
00609 
00610   if (!message_cache_shutdown_registered)
00611     {
00612       _dbus_assert (message_cache_count == 0);
00613 
00614       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00615         goto out;
00616 
00617       i = 0;
00618       while (i < MAX_MESSAGE_CACHE_SIZE)
00619         {
00620           message_cache[i] = NULL;
00621           ++i;
00622         }
00623 
00624       message_cache_shutdown_registered = TRUE;
00625     }
00626 
00627   _dbus_assert (message_cache_count >= 0);
00628 
00629   if ((_dbus_string_get_length (&message->header.data) +
00630        _dbus_string_get_length (&message->body)) >
00631       MAX_MESSAGE_SIZE_TO_CACHE)
00632     goto out;
00633 
00634   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00635     goto out;
00636 
00637   /* Find empty slot */
00638   i = 0;
00639   while (message_cache[i] != NULL)
00640     ++i;
00641 
00642   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00643 
00644   _dbus_assert (message_cache[i] == NULL);
00645   message_cache[i] = message;
00646   message_cache_count += 1;
00647   was_cached = TRUE;
00648 #ifndef DBUS_DISABLE_CHECKS
00649   message->in_cache = TRUE;
00650 #endif
00651 
00652  out:
00653   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00654 
00655   _DBUS_UNLOCK (message_cache);
00656   
00657   if (!was_cached)
00658     dbus_message_finalize (message);
00659 }
00660 
00661 #ifndef DBUS_DISABLE_CHECKS
00662 static dbus_bool_t
00663 _dbus_message_iter_check (DBusMessageRealIter *iter)
00664 {
00665   if (iter == NULL)
00666     {
00667       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00668       return FALSE;
00669     }
00670 
00671   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00672     {
00673       if (iter->u.reader.byte_order != iter->message->byte_order)
00674         {
00675           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00676           return FALSE;
00677         }
00678       /* because we swap the message into compiler order when you init an iter */
00679       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00680     }
00681   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00682     {
00683       if (iter->u.writer.byte_order != iter->message->byte_order)
00684         {
00685           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00686           return FALSE;
00687         }
00688       /* because we swap the message into compiler order when you init an iter */
00689       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00690     }
00691   else
00692     {
00693       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00694       return FALSE;
00695     }
00696 
00697   if (iter->changed_stamp != iter->message->changed_stamp)
00698     {
00699       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00700       return FALSE;
00701     }
00702 
00703   return TRUE;
00704 }
00705 #endif /* DBUS_DISABLE_CHECKS */
00706 
00721 dbus_bool_t
00722 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00723                                     DBusError       *error,
00724                                     int              first_arg_type,
00725                                     va_list          var_args)
00726 {
00727   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00728   int spec_type, msg_type, i;
00729   dbus_bool_t retval;
00730 
00731   _dbus_assert (_dbus_message_iter_check (real));
00732 
00733   retval = FALSE;
00734 
00735   spec_type = first_arg_type;
00736   i = 0;
00737 
00738   while (spec_type != DBUS_TYPE_INVALID)
00739     {
00740       msg_type = dbus_message_iter_get_arg_type (iter);
00741 
00742       if (msg_type != spec_type)
00743         {
00744           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00745                           "Argument %d is specified to be of type \"%s\", but "
00746                           "is actually of type \"%s\"\n", i,
00747                           _dbus_type_to_string (spec_type),
00748                           _dbus_type_to_string (msg_type));
00749 
00750           goto out;
00751         }
00752 
00753       if (spec_type == DBUS_TYPE_UNIX_FD)
00754         {
00755 #ifdef HAVE_UNIX_FD_PASSING
00756           DBusBasicValue idx;
00757           int *pfd, nfd;
00758 
00759           pfd = va_arg (var_args, int*);
00760           _dbus_assert(pfd);
00761 
00762           _dbus_type_reader_read_basic(&real->u.reader, &idx);
00763 
00764           if (idx.u32 >= real->message->n_unix_fds)
00765             {
00766               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
00767                               "Message refers to file descriptor at index %i,"
00768                               "but has only %i descriptors attached.\n",
00769                               idx.u32,
00770                               real->message->n_unix_fds);
00771               goto out;
00772             }
00773 
00774           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
00775             goto out;
00776 
00777           *pfd = nfd;
00778 #else
00779           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00780                           "Platform does not support file desciptor passing.\n");
00781           goto out;
00782 #endif
00783         }
00784       else if (dbus_type_is_basic (spec_type))
00785         {
00786           DBusBasicValue *ptr;
00787 
00788           ptr = va_arg (var_args, DBusBasicValue*);
00789 
00790           _dbus_assert (ptr != NULL);
00791 
00792           _dbus_type_reader_read_basic (&real->u.reader,
00793                                         ptr);
00794         }
00795       else if (spec_type == DBUS_TYPE_ARRAY)
00796         {
00797           int element_type;
00798           int spec_element_type;
00799           const DBusBasicValue **ptr;
00800           int *n_elements_p;
00801           DBusTypeReader array;
00802 
00803           spec_element_type = va_arg (var_args, int);
00804           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00805 
00806           if (spec_element_type != element_type)
00807             {
00808               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00809                               "Argument %d is specified to be an array of \"%s\", but "
00810                               "is actually an array of \"%s\"\n",
00811                               i,
00812                               _dbus_type_to_string (spec_element_type),
00813                               _dbus_type_to_string (element_type));
00814 
00815               goto out;
00816             }
00817 
00818           if (dbus_type_is_fixed (spec_element_type) &&
00819               element_type != DBUS_TYPE_UNIX_FD)
00820             {
00821               ptr = va_arg (var_args, const DBusBasicValue**);
00822               n_elements_p = va_arg (var_args, int*);
00823 
00824               _dbus_assert (ptr != NULL);
00825               _dbus_assert (n_elements_p != NULL);
00826 
00827               _dbus_type_reader_recurse (&real->u.reader, &array);
00828 
00829               _dbus_type_reader_read_fixed_multi (&array,
00830                                                   (void *) ptr, n_elements_p);
00831             }
00832           else if (spec_element_type == DBUS_TYPE_STRING ||
00833                    spec_element_type == DBUS_TYPE_SIGNATURE ||
00834                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
00835             {
00836               char ***str_array_p;
00837               int n_elements;
00838               char **str_array;
00839 
00840               str_array_p = va_arg (var_args, char***);
00841               n_elements_p = va_arg (var_args, int*);
00842 
00843               _dbus_assert (str_array_p != NULL);
00844               _dbus_assert (n_elements_p != NULL);
00845 
00846               /* Count elements in the array */
00847               _dbus_type_reader_recurse (&real->u.reader, &array);
00848 
00849               n_elements = 0;
00850               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00851                 {
00852                   ++n_elements;
00853                   _dbus_type_reader_next (&array);
00854                 }
00855 
00856               str_array = dbus_new0 (char*, n_elements + 1);
00857               if (str_array == NULL)
00858                 {
00859                   _DBUS_SET_OOM (error);
00860                   goto out;
00861                 }
00862 
00863               /* Now go through and dup each string */
00864               _dbus_type_reader_recurse (&real->u.reader, &array);
00865 
00866               i = 0;
00867               while (i < n_elements)
00868                 {
00869                   const char *s;
00870                   _dbus_type_reader_read_basic (&array,
00871                                                 (void *) &s);
00872                   
00873                   str_array[i] = _dbus_strdup (s);
00874                   if (str_array[i] == NULL)
00875                     {
00876                       dbus_free_string_array (str_array);
00877                       _DBUS_SET_OOM (error);
00878                       goto out;
00879                     }
00880                   
00881                   ++i;
00882                   
00883                   if (!_dbus_type_reader_next (&array))
00884                     _dbus_assert (i == n_elements);
00885                 }
00886 
00887               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00888               _dbus_assert (i == n_elements);
00889               _dbus_assert (str_array[i] == NULL);
00890 
00891               *str_array_p = str_array;
00892               *n_elements_p = n_elements;
00893             }
00894 #ifndef DBUS_DISABLE_CHECKS
00895           else
00896             {
00897               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00898                           _DBUS_FUNCTION_NAME);
00899               goto out;
00900             }
00901 #endif
00902         }
00903 #ifndef DBUS_DISABLE_CHECKS
00904       else
00905         {
00906           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00907                       _DBUS_FUNCTION_NAME);
00908           goto out;
00909         }
00910 #endif
00911 
00912       spec_type = va_arg (var_args, int);
00913       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00914         {
00915           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00916                           "Message has only %d arguments, but more were expected", i);
00917           goto out;
00918         }
00919 
00920       i++;
00921     }
00922 
00923   retval = TRUE;
00924 
00925  out:
00926 
00927   return retval;
00928 }
00929 
00988 dbus_uint32_t
00989 dbus_message_get_serial (DBusMessage *message)
00990 {
00991   _dbus_return_val_if_fail (message != NULL, 0);
00992 
00993   return _dbus_header_get_serial (&message->header);
00994 }
00995 
01004 dbus_bool_t
01005 dbus_message_set_reply_serial (DBusMessage   *message,
01006                                dbus_uint32_t  reply_serial)
01007 {
01008   _dbus_return_val_if_fail (message != NULL, FALSE);
01009   _dbus_return_val_if_fail (!message->locked, FALSE);
01010   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01011 
01012   return _dbus_header_set_field_basic (&message->header,
01013                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01014                                        DBUS_TYPE_UINT32,
01015                                        &reply_serial);
01016 }
01017 
01024 dbus_uint32_t
01025 dbus_message_get_reply_serial  (DBusMessage *message)
01026 {
01027   dbus_uint32_t v_UINT32;
01028 
01029   _dbus_return_val_if_fail (message != NULL, 0);
01030 
01031   if (_dbus_header_get_field_basic (&message->header,
01032                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01033                                     DBUS_TYPE_UINT32,
01034                                     &v_UINT32))
01035     return v_UINT32;
01036   else
01037     return 0;
01038 }
01039 
01040 static void
01041 dbus_message_finalize (DBusMessage *message)
01042 {
01043   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01044 
01045   /* This calls application callbacks! */
01046   _dbus_data_slot_list_free (&message->slot_list);
01047 
01048   _dbus_list_foreach (&message->counters,
01049                       free_counter, message);
01050   _dbus_list_clear (&message->counters);
01051 
01052   _dbus_header_free (&message->header);
01053   _dbus_string_free (&message->body);
01054 
01055 #ifdef HAVE_UNIX_FD_PASSING
01056   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01057   dbus_free(message->unix_fds);
01058 #endif
01059 
01060   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01061 
01062   dbus_free (message);
01063 }
01064 
01065 static DBusMessage*
01066 dbus_message_new_empty_header (void)
01067 {
01068   DBusMessage *message;
01069   dbus_bool_t from_cache;
01070 
01071   message = dbus_message_get_cached ();
01072 
01073   if (message != NULL)
01074     {
01075       from_cache = TRUE;
01076     }
01077   else
01078     {
01079       from_cache = FALSE;
01080       message = dbus_new0 (DBusMessage, 1);
01081       if (message == NULL)
01082         return NULL;
01083 #ifndef DBUS_DISABLE_CHECKS
01084       message->generation = _dbus_current_generation;
01085 #endif
01086 
01087 #ifdef HAVE_UNIX_FD_PASSING
01088       message->unix_fds = NULL;
01089       message->n_unix_fds_allocated = 0;
01090 #endif
01091     }
01092 
01093   _dbus_atomic_inc (&message->refcount);
01094 
01095   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
01096   message->locked = FALSE;
01097 #ifndef DBUS_DISABLE_CHECKS
01098   message->in_cache = FALSE;
01099 #endif
01100   message->counters = NULL;
01101   message->size_counter_delta = 0;
01102   message->changed_stamp = 0;
01103 
01104 #ifdef HAVE_UNIX_FD_PASSING
01105   message->n_unix_fds = 0;
01106   message->n_unix_fds_allocated = 0;
01107   message->unix_fd_counter_delta = 0;
01108 #endif
01109 
01110   if (!from_cache)
01111     _dbus_data_slot_list_init (&message->slot_list);
01112 
01113   if (from_cache)
01114     {
01115       _dbus_header_reinit (&message->header, message->byte_order);
01116       _dbus_string_set_length (&message->body, 0);
01117     }
01118   else
01119     {
01120       if (!_dbus_header_init (&message->header, message->byte_order))
01121         {
01122           dbus_free (message);
01123           return NULL;
01124         }
01125 
01126       if (!_dbus_string_init_preallocated (&message->body, 32))
01127         {
01128           _dbus_header_free (&message->header);
01129           dbus_free (message);
01130           return NULL;
01131         }
01132     }
01133 
01134   return message;
01135 }
01136 
01149 DBusMessage*
01150 dbus_message_new (int message_type)
01151 {
01152   DBusMessage *message;
01153 
01154   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01155 
01156   message = dbus_message_new_empty_header ();
01157   if (message == NULL)
01158     return NULL;
01159 
01160   if (!_dbus_header_create (&message->header,
01161                             message_type,
01162                             NULL, NULL, NULL, NULL, NULL))
01163     {
01164       dbus_message_unref (message);
01165       return NULL;
01166     }
01167 
01168   return message;
01169 }
01170 
01192 DBusMessage*
01193 dbus_message_new_method_call (const char *destination,
01194                               const char *path,
01195                               const char *interface,
01196                               const char *method)
01197 {
01198   DBusMessage *message;
01199 
01200   _dbus_return_val_if_fail (path != NULL, NULL);
01201   _dbus_return_val_if_fail (method != NULL, NULL);
01202   _dbus_return_val_if_fail (destination == NULL ||
01203                             _dbus_check_is_valid_bus_name (destination), NULL);
01204   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01205   _dbus_return_val_if_fail (interface == NULL ||
01206                             _dbus_check_is_valid_interface (interface), NULL);
01207   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01208 
01209   message = dbus_message_new_empty_header ();
01210   if (message == NULL)
01211     return NULL;
01212 
01213   if (!_dbus_header_create (&message->header,
01214                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01215                             destination, path, interface, method, NULL))
01216     {
01217       dbus_message_unref (message);
01218       return NULL;
01219     }
01220 
01221   return message;
01222 }
01223 
01231 DBusMessage*
01232 dbus_message_new_method_return (DBusMessage *method_call)
01233 {
01234   DBusMessage *message;
01235   const char *sender;
01236 
01237   _dbus_return_val_if_fail (method_call != NULL, NULL);
01238 
01239   sender = dbus_message_get_sender (method_call);
01240 
01241   /* sender is allowed to be null here in peer-to-peer case */
01242 
01243   message = dbus_message_new_empty_header ();
01244   if (message == NULL)
01245     return NULL;
01246 
01247   if (!_dbus_header_create (&message->header,
01248                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01249                             sender, NULL, NULL, NULL, NULL))
01250     {
01251       dbus_message_unref (message);
01252       return NULL;
01253     }
01254 
01255   dbus_message_set_no_reply (message, TRUE);
01256 
01257   if (!dbus_message_set_reply_serial (message,
01258                                       dbus_message_get_serial (method_call)))
01259     {
01260       dbus_message_unref (message);
01261       return NULL;
01262     }
01263 
01264   return message;
01265 }
01266 
01281 DBusMessage*
01282 dbus_message_new_signal (const char *path,
01283                          const char *interface,
01284                          const char *name)
01285 {
01286   DBusMessage *message;
01287 
01288   _dbus_return_val_if_fail (path != NULL, NULL);
01289   _dbus_return_val_if_fail (interface != NULL, NULL);
01290   _dbus_return_val_if_fail (name != NULL, NULL);
01291   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01292   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
01293   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01294 
01295   message = dbus_message_new_empty_header ();
01296   if (message == NULL)
01297     return NULL;
01298 
01299   if (!_dbus_header_create (&message->header,
01300                             DBUS_MESSAGE_TYPE_SIGNAL,
01301                             NULL, path, interface, name, NULL))
01302     {
01303       dbus_message_unref (message);
01304       return NULL;
01305     }
01306 
01307   dbus_message_set_no_reply (message, TRUE);
01308 
01309   return message;
01310 }
01311 
01326 DBusMessage*
01327 dbus_message_new_error (DBusMessage *reply_to,
01328                         const char  *error_name,
01329                         const char  *error_message)
01330 {
01331   DBusMessage *message;
01332   const char *sender;
01333   DBusMessageIter iter;
01334 
01335   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01336   _dbus_return_val_if_fail (error_name != NULL, NULL);
01337   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01338 
01339   sender = dbus_message_get_sender (reply_to);
01340 
01341   /* sender may be NULL for non-message-bus case or
01342    * when the message bus is dealing with an unregistered
01343    * connection.
01344    */
01345   message = dbus_message_new_empty_header ();
01346   if (message == NULL)
01347     return NULL;
01348 
01349   if (!_dbus_header_create (&message->header,
01350                             DBUS_MESSAGE_TYPE_ERROR,
01351                             sender, NULL, NULL, NULL, error_name))
01352     {
01353       dbus_message_unref (message);
01354       return NULL;
01355     }
01356 
01357   dbus_message_set_no_reply (message, TRUE);
01358 
01359   if (!dbus_message_set_reply_serial (message,
01360                                       dbus_message_get_serial (reply_to)))
01361     {
01362       dbus_message_unref (message);
01363       return NULL;
01364     }
01365 
01366   if (error_message != NULL)
01367     {
01368       dbus_message_iter_init_append (message, &iter);
01369       if (!dbus_message_iter_append_basic (&iter,
01370                                            DBUS_TYPE_STRING,
01371                                            &error_message))
01372         {
01373           dbus_message_unref (message);
01374           return NULL;
01375         }
01376     }
01377 
01378   return message;
01379 }
01380 
01397 DBusMessage*
01398 dbus_message_new_error_printf (DBusMessage *reply_to,
01399                                const char  *error_name,
01400                                const char  *error_format,
01401                                ...)
01402 {
01403   va_list args;
01404   DBusString str;
01405   DBusMessage *message;
01406 
01407   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01408   _dbus_return_val_if_fail (error_name != NULL, NULL);
01409   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01410 
01411   if (!_dbus_string_init (&str))
01412     return NULL;
01413 
01414   va_start (args, error_format);
01415 
01416   if (_dbus_string_append_printf_valist (&str, error_format, args))
01417     message = dbus_message_new_error (reply_to, error_name,
01418                                       _dbus_string_get_const_data (&str));
01419   else
01420     message = NULL;
01421 
01422   _dbus_string_free (&str);
01423 
01424   va_end (args);
01425 
01426   return message;
01427 }
01428 
01429 
01442 DBusMessage *
01443 dbus_message_copy (const DBusMessage *message)
01444 {
01445   DBusMessage *retval;
01446 
01447   _dbus_return_val_if_fail (message != NULL, NULL);
01448 
01449   retval = dbus_new0 (DBusMessage, 1);
01450   if (retval == NULL)
01451     return NULL;
01452 
01453   _dbus_atomic_inc (&retval->refcount);
01454   retval->byte_order = message->byte_order;
01455   retval->locked = FALSE;
01456 #ifndef DBUS_DISABLE_CHECKS
01457   retval->generation = message->generation;
01458 #endif
01459 
01460   if (!_dbus_header_copy (&message->header, &retval->header))
01461     {
01462       dbus_free (retval);
01463       return NULL;
01464     }
01465 
01466   if (!_dbus_string_init_preallocated (&retval->body,
01467                                        _dbus_string_get_length (&message->body)))
01468     {
01469       _dbus_header_free (&retval->header);
01470       dbus_free (retval);
01471       return NULL;
01472     }
01473 
01474   if (!_dbus_string_copy (&message->body, 0,
01475                           &retval->body, 0))
01476     goto failed_copy;
01477 
01478 #ifdef HAVE_UNIX_FD_PASSING
01479   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01480   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01481     goto failed_copy;
01482 
01483   retval->n_unix_fds_allocated = message->n_unix_fds;
01484 
01485   for (retval->n_unix_fds = 0;
01486        retval->n_unix_fds < message->n_unix_fds;
01487        retval->n_unix_fds++)
01488     {
01489       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01490 
01491       if (retval->unix_fds[retval->n_unix_fds] < 0)
01492         goto failed_copy;
01493     }
01494 
01495 #endif
01496 
01497   return retval;
01498 
01499  failed_copy:
01500   _dbus_header_free (&retval->header);
01501   _dbus_string_free (&retval->body);
01502 
01503 #ifdef HAVE_UNIX_FD_PASSING
01504   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01505   dbus_free(retval->unix_fds);
01506 #endif
01507 
01508   dbus_free (retval);
01509 
01510   return NULL;
01511 }
01512 
01513 
01521 DBusMessage *
01522 dbus_message_ref (DBusMessage *message)
01523 {
01524 #ifndef DBUS_DISABLE_ASSERT
01525   dbus_int32_t old_refcount;
01526 #endif
01527 
01528   _dbus_return_val_if_fail (message != NULL, NULL);
01529   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01530   _dbus_return_val_if_fail (!message->in_cache, NULL);
01531 
01532 #ifdef DBUS_DISABLE_ASSERT
01533   _dbus_atomic_inc (&message->refcount);
01534 #else
01535   old_refcount = _dbus_atomic_inc (&message->refcount);
01536   _dbus_assert (old_refcount >= 1);
01537 #endif
01538 
01539   return message;
01540 }
01541 
01549 void
01550 dbus_message_unref (DBusMessage *message)
01551 {
01552  dbus_int32_t old_refcount;
01553 
01554   _dbus_return_if_fail (message != NULL);
01555   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01556   _dbus_return_if_fail (!message->in_cache);
01557 
01558   old_refcount = _dbus_atomic_dec (&message->refcount);
01559 
01560   _dbus_assert (old_refcount >= 1);
01561 
01562   if (old_refcount == 1)
01563     {
01564       /* Calls application callbacks! */
01565       dbus_message_cache_or_finalize (message);
01566     }
01567 }
01568 
01579 int
01580 dbus_message_get_type (DBusMessage *message)
01581 {
01582   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01583 
01584   return _dbus_header_get_message_type (&message->header);
01585 }
01586 
01649 dbus_bool_t
01650 dbus_message_append_args (DBusMessage *message,
01651                           int          first_arg_type,
01652                           ...)
01653 {
01654   dbus_bool_t retval;
01655   va_list var_args;
01656 
01657   _dbus_return_val_if_fail (message != NULL, FALSE);
01658 
01659   va_start (var_args, first_arg_type);
01660   retval = dbus_message_append_args_valist (message,
01661                                             first_arg_type,
01662                                             var_args);
01663   va_end (var_args);
01664 
01665   return retval;
01666 }
01667 
01681 dbus_bool_t
01682 dbus_message_append_args_valist (DBusMessage *message,
01683                                  int          first_arg_type,
01684                                  va_list      var_args)
01685 {
01686   int type;
01687   DBusMessageIter iter;
01688 
01689   _dbus_return_val_if_fail (message != NULL, FALSE);
01690 
01691   type = first_arg_type;
01692 
01693   dbus_message_iter_init_append (message, &iter);
01694 
01695   while (type != DBUS_TYPE_INVALID)
01696     {
01697       if (dbus_type_is_basic (type))
01698         {
01699           const DBusBasicValue *value;
01700           value = va_arg (var_args, const DBusBasicValue*);
01701 
01702           if (!dbus_message_iter_append_basic (&iter,
01703                                                type,
01704                                                value))
01705             goto failed;
01706         }
01707       else if (type == DBUS_TYPE_ARRAY)
01708         {
01709           int element_type;
01710           DBusMessageIter array;
01711           char buf[2];
01712 
01713           element_type = va_arg (var_args, int);
01714               
01715           buf[0] = element_type;
01716           buf[1] = '\0';
01717           if (!dbus_message_iter_open_container (&iter,
01718                                                  DBUS_TYPE_ARRAY,
01719                                                  buf,
01720                                                  &array))
01721             goto failed;
01722 
01723           if (dbus_type_is_fixed (element_type) &&
01724               element_type != DBUS_TYPE_UNIX_FD)
01725             {
01726               const DBusBasicValue **value;
01727               int n_elements;
01728 
01729               value = va_arg (var_args, const DBusBasicValue**);
01730               n_elements = va_arg (var_args, int);
01731               
01732               if (!dbus_message_iter_append_fixed_array (&array,
01733                                                          element_type,
01734                                                          value,
01735                                                          n_elements)) {
01736                 dbus_message_iter_abandon_container (&iter, &array);
01737                 goto failed;
01738               }
01739             }
01740           else if (element_type == DBUS_TYPE_STRING ||
01741                    element_type == DBUS_TYPE_SIGNATURE ||
01742                    element_type == DBUS_TYPE_OBJECT_PATH)
01743             {
01744               const char ***value_p;
01745               const char **value;
01746               int n_elements;
01747               int i;
01748               
01749               value_p = va_arg (var_args, const char***);
01750               n_elements = va_arg (var_args, int);
01751 
01752               value = *value_p;
01753               
01754               i = 0;
01755               while (i < n_elements)
01756                 {
01757                   if (!dbus_message_iter_append_basic (&array,
01758                                                        element_type,
01759                                                        &value[i])) {
01760                     dbus_message_iter_abandon_container (&iter, &array);
01761                     goto failed;
01762                   }
01763                   ++i;
01764                 }
01765             }
01766           else
01767             {
01768               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01769                           _dbus_type_to_string (element_type),
01770                           _DBUS_FUNCTION_NAME);
01771               goto failed;
01772             }
01773 
01774           if (!dbus_message_iter_close_container (&iter, &array))
01775             goto failed;
01776         }
01777 #ifndef DBUS_DISABLE_CHECKS
01778       else
01779         {
01780           _dbus_warn ("type %s isn't supported yet in %s\n",
01781                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01782           goto failed;
01783         }
01784 #endif
01785 
01786       type = va_arg (var_args, int);
01787     }
01788 
01789   return TRUE;
01790 
01791  failed:
01792   return FALSE;
01793 }
01794 
01839 dbus_bool_t
01840 dbus_message_get_args (DBusMessage     *message,
01841                        DBusError       *error,
01842                        int              first_arg_type,
01843                        ...)
01844 {
01845   dbus_bool_t retval;
01846   va_list var_args;
01847 
01848   _dbus_return_val_if_fail (message != NULL, FALSE);
01849   _dbus_return_val_if_error_is_set (error, FALSE);
01850 
01851   va_start (var_args, first_arg_type);
01852   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01853   va_end (var_args);
01854 
01855   return retval;
01856 }
01857 
01868 dbus_bool_t
01869 dbus_message_get_args_valist (DBusMessage     *message,
01870                               DBusError       *error,
01871                               int              first_arg_type,
01872                               va_list          var_args)
01873 {
01874   DBusMessageIter iter;
01875 
01876   _dbus_return_val_if_fail (message != NULL, FALSE);
01877   _dbus_return_val_if_error_is_set (error, FALSE);
01878 
01879   dbus_message_iter_init (message, &iter);
01880   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01881 }
01882 
01883 static void
01884 _dbus_message_iter_init_common (DBusMessage         *message,
01885                                 DBusMessageRealIter *real,
01886                                 int                  iter_type)
01887 {
01888   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01889 
01890   /* Since the iterator will read or write who-knows-what from the
01891    * message, we need to get in the right byte order
01892    */
01893   ensure_byte_order (message);
01894   
01895   real->message = message;
01896   real->changed_stamp = message->changed_stamp;
01897   real->iter_type = iter_type;
01898   real->sig_refcount = 0;
01899 }
01900 
01923 dbus_bool_t
01924 dbus_message_iter_init (DBusMessage     *message,
01925                         DBusMessageIter *iter)
01926 {
01927   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01928   const DBusString *type_str;
01929   int type_pos;
01930 
01931   _dbus_return_val_if_fail (message != NULL, FALSE);
01932   _dbus_return_val_if_fail (iter != NULL, FALSE);
01933 
01934   get_const_signature (&message->header, &type_str, &type_pos);
01935 
01936   _dbus_message_iter_init_common (message, real,
01937                                   DBUS_MESSAGE_ITER_TYPE_READER);
01938 
01939   _dbus_type_reader_init (&real->u.reader,
01940                           message->byte_order,
01941                           type_str, type_pos,
01942                           &message->body,
01943                           0);
01944 
01945   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
01946 }
01947 
01954 dbus_bool_t
01955 dbus_message_iter_has_next (DBusMessageIter *iter)
01956 {
01957   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01958 
01959   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01960   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01961 
01962   return _dbus_type_reader_has_next (&real->u.reader);
01963 }
01964 
01973 dbus_bool_t
01974 dbus_message_iter_next (DBusMessageIter *iter)
01975 {
01976   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01977 
01978   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01979   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01980 
01981   return _dbus_type_reader_next (&real->u.reader);
01982 }
01983 
01998 int
01999 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02000 {
02001   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02002 
02003   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02004   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02005 
02006   return _dbus_type_reader_get_current_type (&real->u.reader);
02007 }
02008 
02017 int
02018 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02019 {
02020   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02021 
02022   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02023   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02024   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02025 
02026   return _dbus_type_reader_get_element_type (&real->u.reader);
02027 }
02028 
02054 void
02055 dbus_message_iter_recurse (DBusMessageIter  *iter,
02056                            DBusMessageIter  *sub)
02057 {
02058   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02059   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02060 
02061   _dbus_return_if_fail (_dbus_message_iter_check (real));
02062   _dbus_return_if_fail (sub != NULL);
02063 
02064   *real_sub = *real;
02065   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02066 }
02067 
02079 char *
02080 dbus_message_iter_get_signature (DBusMessageIter *iter)
02081 {
02082   const DBusString *sig;
02083   DBusString retstr;
02084   char *ret;
02085   int start, len;
02086   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02087 
02088   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02089 
02090   if (!_dbus_string_init (&retstr))
02091     return NULL;
02092 
02093   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02094                                    &start, &len);
02095   if (!_dbus_string_append_len (&retstr,
02096                                 _dbus_string_get_const_data (sig) + start,
02097                                 len))
02098     return NULL;
02099   if (!_dbus_string_steal_data (&retstr, &ret))
02100     return NULL;
02101   _dbus_string_free (&retstr);
02102   return ret;
02103 }
02104 
02152 void
02153 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02154                              void             *value)
02155 {
02156   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02157 
02158   _dbus_return_if_fail (_dbus_message_iter_check (real));
02159   _dbus_return_if_fail (value != NULL);
02160 
02161   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02162     {
02163 #ifdef HAVE_UNIX_FD_PASSING
02164       DBusBasicValue idx;
02165 
02166       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02167 
02168       if (idx.u32 >= real->message->n_unix_fds) {
02169         /* Hmm, we cannot really signal an error here, so let's make
02170            sure to return an invalid fd. */
02171         *((int*) value) = -1;
02172         return;
02173       }
02174 
02175       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02176 #else
02177       *((int*) value) = -1;
02178 #endif
02179     }
02180   else
02181     {
02182       _dbus_type_reader_read_basic (&real->u.reader,
02183                                     value);
02184     }
02185 }
02186 
02205 int
02206 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02207 {
02208   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02209 
02210   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02211 
02212   return _dbus_type_reader_get_array_length (&real->u.reader);
02213 }
02214 
02250 void
02251 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02252                                    void             *value,
02253                                    int              *n_elements)
02254 {
02255   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02256   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02257 
02258   _dbus_return_if_fail (_dbus_message_iter_check (real));
02259   _dbus_return_if_fail (value != NULL);
02260   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02261                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02262 
02263   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02264                                       value, n_elements);
02265 }
02266 
02278 void
02279 dbus_message_iter_init_append (DBusMessage     *message,
02280                                DBusMessageIter *iter)
02281 {
02282   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02283 
02284   _dbus_return_if_fail (message != NULL);
02285   _dbus_return_if_fail (iter != NULL);
02286 
02287   _dbus_message_iter_init_common (message, real,
02288                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02289 
02290   /* We create the signature string and point iterators at it "on demand"
02291    * when a value is actually appended. That means that init() never fails
02292    * due to OOM.
02293    */
02294   _dbus_type_writer_init_types_delayed (&real->u.writer,
02295                                         message->byte_order,
02296                                         &message->body,
02297                                         _dbus_string_get_length (&message->body));
02298 }
02299 
02308 static dbus_bool_t
02309 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02310 {
02311   DBusString *str;
02312   const DBusString *current_sig;
02313   int current_sig_pos;
02314 
02315   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02316 
02317   if (real->u.writer.type_str != NULL)
02318     {
02319       _dbus_assert (real->sig_refcount > 0);
02320       real->sig_refcount += 1;
02321       return TRUE;
02322     }
02323 
02324   str = dbus_new (DBusString, 1);
02325   if (str == NULL)
02326     return FALSE;
02327 
02328   if (!_dbus_header_get_field_raw (&real->message->header,
02329                                    DBUS_HEADER_FIELD_SIGNATURE,
02330                                    &current_sig, &current_sig_pos))
02331     current_sig = NULL;
02332 
02333   if (current_sig)
02334     {
02335       int current_len;
02336 
02337       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02338       current_sig_pos += 1; /* move on to sig data */
02339 
02340       if (!_dbus_string_init_preallocated (str, current_len + 4))
02341         {
02342           dbus_free (str);
02343           return FALSE;
02344         }
02345 
02346       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02347                                   str, 0))
02348         {
02349           _dbus_string_free (str);
02350           dbus_free (str);
02351           return FALSE;
02352         }
02353     }
02354   else
02355     {
02356       if (!_dbus_string_init_preallocated (str, 4))
02357         {
02358           dbus_free (str);
02359           return FALSE;
02360         }
02361     }
02362 
02363   real->sig_refcount = 1;
02364 
02365   _dbus_type_writer_add_types (&real->u.writer,
02366                                str, _dbus_string_get_length (str));
02367   return TRUE;
02368 }
02369 
02379 static dbus_bool_t
02380 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02381 {
02382   DBusString *str;
02383   const char *v_STRING;
02384   dbus_bool_t retval;
02385 
02386   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02387   _dbus_assert (real->u.writer.type_str != NULL);
02388   _dbus_assert (real->sig_refcount > 0);
02389 
02390   real->sig_refcount -= 1;
02391 
02392   if (real->sig_refcount > 0)
02393     return TRUE;
02394   _dbus_assert (real->sig_refcount == 0);
02395 
02396   retval = TRUE;
02397 
02398   str = real->u.writer.type_str;
02399 
02400   v_STRING = _dbus_string_get_const_data (str);
02401   if (!_dbus_header_set_field_basic (&real->message->header,
02402                                      DBUS_HEADER_FIELD_SIGNATURE,
02403                                      DBUS_TYPE_SIGNATURE,
02404                                      &v_STRING))
02405     retval = FALSE;
02406 
02407   _dbus_type_writer_remove_types (&real->u.writer);
02408   _dbus_string_free (str);
02409   dbus_free (str);
02410 
02411   return retval;
02412 }
02413 
02421 static void
02422 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02423 {
02424   DBusString *str;
02425 
02426   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02427   _dbus_assert (real->u.writer.type_str != NULL);
02428   _dbus_assert (real->sig_refcount > 0);
02429 
02430   real->sig_refcount -= 1;
02431 
02432   if (real->sig_refcount > 0)
02433     return;
02434   _dbus_assert (real->sig_refcount == 0);
02435 
02436   str = real->u.writer.type_str;
02437 
02438   _dbus_type_writer_remove_types (&real->u.writer);
02439   _dbus_string_free (str);
02440   dbus_free (str);
02441 }
02442 
02443 #ifndef DBUS_DISABLE_CHECKS
02444 static dbus_bool_t
02445 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02446 {
02447   if (!_dbus_message_iter_check (iter))
02448     return FALSE;
02449 
02450   if (iter->message->locked)
02451     {
02452       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02453       return FALSE;
02454     }
02455 
02456   return TRUE;
02457 }
02458 #endif /* DBUS_DISABLE_CHECKS */
02459 
02460 #ifdef HAVE_UNIX_FD_PASSING
02461 static int *
02462 expand_fd_array(DBusMessage *m,
02463                 unsigned     n)
02464 {
02465   _dbus_assert(m);
02466 
02467   /* This makes space for adding n new fds to the array and returns a
02468      pointer to the place were the first fd should be put. */
02469 
02470   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02471     {
02472       unsigned k;
02473       int *p;
02474 
02475       /* Make twice as much space as necessary */
02476       k = (m->n_unix_fds + n) * 2;
02477 
02478       /* Allocate at least four */
02479       if (k < 4)
02480         k = 4;
02481 
02482       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02483       if (p == NULL)
02484         return NULL;
02485 
02486       m->unix_fds = p;
02487       m->n_unix_fds_allocated = k;
02488     }
02489 
02490   return m->unix_fds + m->n_unix_fds;
02491 }
02492 #endif
02493 
02513 dbus_bool_t
02514 dbus_message_iter_append_basic (DBusMessageIter *iter,
02515                                 int              type,
02516                                 const void      *value)
02517 {
02518   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02519   dbus_bool_t ret;
02520 
02521   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02522   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02523   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02524   _dbus_return_val_if_fail (value != NULL, FALSE);
02525 
02526 #ifndef DBUS_DISABLE_CHECKS
02527   switch (type)
02528     {
02529       const char * const *string_p;
02530       const dbus_bool_t *bool_p;
02531 
02532       case DBUS_TYPE_STRING:
02533         string_p = value;
02534         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02535         break;
02536 
02537       case DBUS_TYPE_OBJECT_PATH:
02538         string_p = value;
02539         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02540         break;
02541 
02542       case DBUS_TYPE_SIGNATURE:
02543         string_p = value;
02544         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02545         break;
02546 
02547       case DBUS_TYPE_BOOLEAN:
02548         bool_p = value;
02549         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02550         break;
02551 
02552       default:
02553           {
02554             /* nothing to check, all possible values are allowed */
02555           }
02556     }
02557 #endif
02558 
02559   if (!_dbus_message_iter_open_signature (real))
02560     return FALSE;
02561 
02562   if (type == DBUS_TYPE_UNIX_FD)
02563     {
02564 #ifdef HAVE_UNIX_FD_PASSING
02565       int *fds;
02566       dbus_uint32_t u;
02567 
02568       /* First step, include the fd in the fd list of this message */
02569       if (!(fds = expand_fd_array(real->message, 1)))
02570         return FALSE;
02571 
02572       *fds = _dbus_dup(*(int*) value, NULL);
02573       if (*fds < 0)
02574         return FALSE;
02575 
02576       u = real->message->n_unix_fds;
02577 
02578       /* Second step, write the index to the fd */
02579       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02580         _dbus_close(*fds, NULL);
02581         return FALSE;
02582       }
02583 
02584       real->message->n_unix_fds += 1;
02585       u += 1;
02586 
02587       /* Final step, update the header accordingly */
02588       ret = _dbus_header_set_field_basic (&real->message->header,
02589                                           DBUS_HEADER_FIELD_UNIX_FDS,
02590                                           DBUS_TYPE_UINT32,
02591                                           &u);
02592 
02593       /* If any of these operations fail the message is
02594          hosed. However, no memory or fds should be leaked since what
02595          has been added to message has been added to the message, and
02596          can hence be accounted for when the message is being
02597          freed. */
02598 #else
02599       ret = FALSE;
02600 #endif
02601     }
02602   else
02603     {
02604       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02605     }
02606 
02607   if (!_dbus_message_iter_close_signature (real))
02608     ret = FALSE;
02609 
02610   return ret;
02611 }
02612 
02648 dbus_bool_t
02649 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02650                                       int              element_type,
02651                                       const void      *value,
02652                                       int              n_elements)
02653 {
02654   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02655   dbus_bool_t ret;
02656 
02657   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02658   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02659   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02660   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02661   _dbus_return_val_if_fail (value != NULL, FALSE);
02662   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02663   _dbus_return_val_if_fail (n_elements <=
02664                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02665                             FALSE);
02666 
02667 #ifndef DBUS_DISABLE_CHECKS
02668   if (element_type == DBUS_TYPE_BOOLEAN)
02669     {
02670       const dbus_bool_t * const *bools = value;
02671       int i;
02672 
02673       for (i = 0; i < n_elements; i++)
02674         {
02675           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02676         }
02677     }
02678 #endif
02679 
02680   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02681 
02682   return ret;
02683 }
02684 
02706 dbus_bool_t
02707 dbus_message_iter_open_container (DBusMessageIter *iter,
02708                                   int              type,
02709                                   const char      *contained_signature,
02710                                   DBusMessageIter *sub)
02711 {
02712   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02713   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02714   DBusString contained_str;
02715 
02716   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02717   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02718   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02719   _dbus_return_val_if_fail (sub != NULL, FALSE);
02720   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02721                              contained_signature == NULL) ||
02722                             (type == DBUS_TYPE_DICT_ENTRY &&
02723                              contained_signature == NULL) ||
02724                             (type == DBUS_TYPE_VARIANT &&
02725                              contained_signature != NULL) ||
02726                             (type == DBUS_TYPE_ARRAY &&
02727                              contained_signature != NULL), FALSE);
02728   
02729   /* this would fail if the contained_signature is a dict entry, since
02730    * dict entries are invalid signatures standalone (they must be in
02731    * an array)
02732    */
02733   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02734                             (contained_signature == NULL ||
02735                              _dbus_check_is_valid_signature (contained_signature)),
02736                             FALSE);
02737 
02738   if (!_dbus_message_iter_open_signature (real))
02739     return FALSE;
02740 
02741   *real_sub = *real;
02742 
02743   if (contained_signature != NULL)
02744     {
02745       _dbus_string_init_const (&contained_str, contained_signature);
02746 
02747       return _dbus_type_writer_recurse (&real->u.writer,
02748                                         type,
02749                                         &contained_str, 0,
02750                                         &real_sub->u.writer);
02751     }
02752   else
02753     {
02754       return _dbus_type_writer_recurse (&real->u.writer,
02755                                         type,
02756                                         NULL, 0,
02757                                         &real_sub->u.writer);
02758     } 
02759 }
02760 
02761 
02775 dbus_bool_t
02776 dbus_message_iter_close_container (DBusMessageIter *iter,
02777                                    DBusMessageIter *sub)
02778 {
02779   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02780   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02781   dbus_bool_t ret;
02782 
02783   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02784   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02785   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02786   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02787 
02788   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02789                                      &real_sub->u.writer);
02790 
02791   if (!_dbus_message_iter_close_signature (real))
02792     ret = FALSE;
02793 
02794   return ret;
02795 }
02796 
02808 void
02809 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02810                                      DBusMessageIter *sub)
02811 {
02812   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02813   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02814 
02815   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02816   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02817   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02818   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02819 
02820   _dbus_message_iter_abandon_signature (real);
02821 }
02822 
02839 void
02840 dbus_message_set_no_reply (DBusMessage *message,
02841                            dbus_bool_t  no_reply)
02842 {
02843   _dbus_return_if_fail (message != NULL);
02844   _dbus_return_if_fail (!message->locked);
02845 
02846   _dbus_header_toggle_flag (&message->header,
02847                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02848                             no_reply);
02849 }
02850 
02858 dbus_bool_t
02859 dbus_message_get_no_reply (DBusMessage *message)
02860 {
02861   _dbus_return_val_if_fail (message != NULL, FALSE);
02862 
02863   return _dbus_header_get_flag (&message->header,
02864                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02865 }
02866 
02881 void
02882 dbus_message_set_auto_start (DBusMessage *message,
02883                              dbus_bool_t  auto_start)
02884 {
02885   _dbus_return_if_fail (message != NULL);
02886   _dbus_return_if_fail (!message->locked);
02887 
02888   _dbus_header_toggle_flag (&message->header,
02889                             DBUS_HEADER_FLAG_NO_AUTO_START,
02890                             !auto_start);
02891 }
02892 
02900 dbus_bool_t
02901 dbus_message_get_auto_start (DBusMessage *message)
02902 {
02903   _dbus_return_val_if_fail (message != NULL, FALSE);
02904 
02905   return !_dbus_header_get_flag (&message->header,
02906                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02907 }
02908 
02909 
02922 dbus_bool_t
02923 dbus_message_set_path (DBusMessage   *message,
02924                        const char    *object_path)
02925 {
02926   _dbus_return_val_if_fail (message != NULL, FALSE);
02927   _dbus_return_val_if_fail (!message->locked, FALSE);
02928   _dbus_return_val_if_fail (object_path == NULL ||
02929                             _dbus_check_is_valid_path (object_path),
02930                             FALSE);
02931 
02932   return set_or_delete_string_field (message,
02933                                      DBUS_HEADER_FIELD_PATH,
02934                                      DBUS_TYPE_OBJECT_PATH,
02935                                      object_path);
02936 }
02937 
02951 const char*
02952 dbus_message_get_path (DBusMessage   *message)
02953 {
02954   const char *v;
02955 
02956   _dbus_return_val_if_fail (message != NULL, NULL);
02957 
02958   v = NULL; /* in case field doesn't exist */
02959   _dbus_header_get_field_basic (&message->header,
02960                                 DBUS_HEADER_FIELD_PATH,
02961                                 DBUS_TYPE_OBJECT_PATH,
02962                                 (void *) &v);
02963   return v;
02964 }
02965 
02975 dbus_bool_t
02976 dbus_message_has_path (DBusMessage   *message,
02977                        const char    *path)
02978 {
02979   const char *msg_path;
02980   msg_path = dbus_message_get_path (message);
02981   
02982   if (msg_path == NULL)
02983     {
02984       if (path == NULL)
02985         return TRUE;
02986       else
02987         return FALSE;
02988     }
02989 
02990   if (path == NULL)
02991     return FALSE;
02992    
02993   if (strcmp (msg_path, path) == 0)
02994     return TRUE;
02995 
02996   return FALSE;
02997 }
02998 
03019 dbus_bool_t
03020 dbus_message_get_path_decomposed (DBusMessage   *message,
03021                                   char        ***path)
03022 {
03023   const char *v;
03024 
03025   _dbus_return_val_if_fail (message != NULL, FALSE);
03026   _dbus_return_val_if_fail (path != NULL, FALSE);
03027 
03028   *path = NULL;
03029 
03030   v = dbus_message_get_path (message);
03031   if (v != NULL)
03032     {
03033       if (!_dbus_decompose_path (v, strlen (v),
03034                                  path, NULL))
03035         return FALSE;
03036     }
03037   return TRUE;
03038 }
03039 
03053 dbus_bool_t
03054 dbus_message_set_interface (DBusMessage  *message,
03055                             const char   *interface)
03056 {
03057   _dbus_return_val_if_fail (message != NULL, FALSE);
03058   _dbus_return_val_if_fail (!message->locked, FALSE);
03059   _dbus_return_val_if_fail (interface == NULL ||
03060                             _dbus_check_is_valid_interface (interface),
03061                             FALSE);
03062 
03063   return set_or_delete_string_field (message,
03064                                      DBUS_HEADER_FIELD_INTERFACE,
03065                                      DBUS_TYPE_STRING,
03066                                      interface);
03067 }
03068 
03082 const char*
03083 dbus_message_get_interface (DBusMessage *message)
03084 {
03085   const char *v;
03086 
03087   _dbus_return_val_if_fail (message != NULL, NULL);
03088 
03089   v = NULL; /* in case field doesn't exist */
03090   _dbus_header_get_field_basic (&message->header,
03091                                 DBUS_HEADER_FIELD_INTERFACE,
03092                                 DBUS_TYPE_STRING,
03093                                 (void *) &v);
03094   return v;
03095 }
03096 
03104 dbus_bool_t
03105 dbus_message_has_interface (DBusMessage   *message,
03106                             const char    *interface)
03107 {
03108   const char *msg_interface;
03109   msg_interface = dbus_message_get_interface (message);
03110    
03111   if (msg_interface == NULL)
03112     {
03113       if (interface == NULL)
03114         return TRUE;
03115       else
03116         return FALSE;
03117     }
03118 
03119   if (interface == NULL)
03120     return FALSE;
03121      
03122   if (strcmp (msg_interface, interface) == 0)
03123     return TRUE;
03124 
03125   return FALSE;
03126 
03127 }
03128 
03141 dbus_bool_t
03142 dbus_message_set_member (DBusMessage  *message,
03143                          const char   *member)
03144 {
03145   _dbus_return_val_if_fail (message != NULL, FALSE);
03146   _dbus_return_val_if_fail (!message->locked, FALSE);
03147   _dbus_return_val_if_fail (member == NULL ||
03148                             _dbus_check_is_valid_member (member),
03149                             FALSE);
03150 
03151   return set_or_delete_string_field (message,
03152                                      DBUS_HEADER_FIELD_MEMBER,
03153                                      DBUS_TYPE_STRING,
03154                                      member);
03155 }
03156 
03168 const char*
03169 dbus_message_get_member (DBusMessage *message)
03170 {
03171   const char *v;
03172 
03173   _dbus_return_val_if_fail (message != NULL, NULL);
03174 
03175   v = NULL; /* in case field doesn't exist */
03176   _dbus_header_get_field_basic (&message->header,
03177                                 DBUS_HEADER_FIELD_MEMBER,
03178                                 DBUS_TYPE_STRING,
03179                                 (void *) &v);
03180   return v;
03181 }
03182 
03190 dbus_bool_t
03191 dbus_message_has_member (DBusMessage   *message,
03192                          const char    *member)
03193 {
03194   const char *msg_member;
03195   msg_member = dbus_message_get_member (message);
03196  
03197   if (msg_member == NULL)
03198     {
03199       if (member == NULL)
03200         return TRUE;
03201       else
03202         return FALSE;
03203     }
03204 
03205   if (member == NULL)
03206     return FALSE;
03207     
03208   if (strcmp (msg_member, member) == 0)
03209     return TRUE;
03210 
03211   return FALSE;
03212 
03213 }
03214 
03226 dbus_bool_t
03227 dbus_message_set_error_name (DBusMessage  *message,
03228                              const char   *error_name)
03229 {
03230   _dbus_return_val_if_fail (message != NULL, FALSE);
03231   _dbus_return_val_if_fail (!message->locked, FALSE);
03232   _dbus_return_val_if_fail (error_name == NULL ||
03233                             _dbus_check_is_valid_error_name (error_name),
03234                             FALSE);
03235 
03236   return set_or_delete_string_field (message,
03237                                      DBUS_HEADER_FIELD_ERROR_NAME,
03238                                      DBUS_TYPE_STRING,
03239                                      error_name);
03240 }
03241 
03252 const char*
03253 dbus_message_get_error_name (DBusMessage *message)
03254 {
03255   const char *v;
03256 
03257   _dbus_return_val_if_fail (message != NULL, NULL);
03258 
03259   v = NULL; /* in case field doesn't exist */
03260   _dbus_header_get_field_basic (&message->header,
03261                                 DBUS_HEADER_FIELD_ERROR_NAME,
03262                                 DBUS_TYPE_STRING,
03263                                 (void *) &v);
03264   return v;
03265 }
03266 
03280 dbus_bool_t
03281 dbus_message_set_destination (DBusMessage  *message,
03282                               const char   *destination)
03283 {
03284   _dbus_return_val_if_fail (message != NULL, FALSE);
03285   _dbus_return_val_if_fail (!message->locked, FALSE);
03286   _dbus_return_val_if_fail (destination == NULL ||
03287                             _dbus_check_is_valid_bus_name (destination),
03288                             FALSE);
03289 
03290   return set_or_delete_string_field (message,
03291                                      DBUS_HEADER_FIELD_DESTINATION,
03292                                      DBUS_TYPE_STRING,
03293                                      destination);
03294 }
03295 
03305 const char*
03306 dbus_message_get_destination (DBusMessage *message)
03307 {
03308   const char *v;
03309 
03310   _dbus_return_val_if_fail (message != NULL, NULL);
03311 
03312   v = NULL; /* in case field doesn't exist */
03313   _dbus_header_get_field_basic (&message->header,
03314                                 DBUS_HEADER_FIELD_DESTINATION,
03315                                 DBUS_TYPE_STRING,
03316                                 (void *) &v);
03317   return v;
03318 }
03319 
03334 dbus_bool_t
03335 dbus_message_set_sender (DBusMessage  *message,
03336                          const char   *sender)
03337 {
03338   _dbus_return_val_if_fail (message != NULL, FALSE);
03339   _dbus_return_val_if_fail (!message->locked, FALSE);
03340   _dbus_return_val_if_fail (sender == NULL ||
03341                             _dbus_check_is_valid_bus_name (sender),
03342                             FALSE);
03343 
03344   return set_or_delete_string_field (message,
03345                                      DBUS_HEADER_FIELD_SENDER,
03346                                      DBUS_TYPE_STRING,
03347                                      sender);
03348 }
03349 
03365 const char*
03366 dbus_message_get_sender (DBusMessage *message)
03367 {
03368   const char *v;
03369 
03370   _dbus_return_val_if_fail (message != NULL, NULL);
03371 
03372   v = NULL; /* in case field doesn't exist */
03373   _dbus_header_get_field_basic (&message->header,
03374                                 DBUS_HEADER_FIELD_SENDER,
03375                                 DBUS_TYPE_STRING,
03376                                 (void *) &v);
03377   return v;
03378 }
03379 
03398 const char*
03399 dbus_message_get_signature (DBusMessage *message)
03400 {
03401   const DBusString *type_str;
03402   int type_pos;
03403 
03404   _dbus_return_val_if_fail (message != NULL, NULL);
03405 
03406   get_const_signature (&message->header, &type_str, &type_pos);
03407 
03408   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03409 }
03410 
03411 static dbus_bool_t
03412 _dbus_message_has_type_interface_member (DBusMessage *message,
03413                                          int          type,
03414                                          const char  *interface,
03415                                          const char  *member)
03416 {
03417   const char *n;
03418 
03419   _dbus_assert (message != NULL);
03420   _dbus_assert (interface != NULL);
03421   _dbus_assert (member != NULL);
03422 
03423   if (dbus_message_get_type (message) != type)
03424     return FALSE;
03425 
03426   /* Optimize by checking the short member name first
03427    * instead of the longer interface name
03428    */
03429 
03430   n = dbus_message_get_member (message);
03431 
03432   if (n && strcmp (n, member) == 0)
03433     {
03434       n = dbus_message_get_interface (message);
03435 
03436       if (n == NULL || strcmp (n, interface) == 0)
03437         return TRUE;
03438     }
03439 
03440   return FALSE;
03441 }
03442 
03457 dbus_bool_t
03458 dbus_message_is_method_call (DBusMessage *message,
03459                              const char  *interface,
03460                              const char  *method)
03461 {
03462   _dbus_return_val_if_fail (message != NULL, FALSE);
03463   _dbus_return_val_if_fail (interface != NULL, FALSE);
03464   _dbus_return_val_if_fail (method != NULL, FALSE);
03465   /* don't check that interface/method are valid since it would be
03466    * expensive, and not catch many common errors
03467    */
03468 
03469   return _dbus_message_has_type_interface_member (message,
03470                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03471                                                   interface, method);
03472 }
03473 
03485 dbus_bool_t
03486 dbus_message_is_signal (DBusMessage *message,
03487                         const char  *interface,
03488                         const char  *signal_name)
03489 {
03490   _dbus_return_val_if_fail (message != NULL, FALSE);
03491   _dbus_return_val_if_fail (interface != NULL, FALSE);
03492   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03493   /* don't check that interface/name are valid since it would be
03494    * expensive, and not catch many common errors
03495    */
03496 
03497   return _dbus_message_has_type_interface_member (message,
03498                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03499                                                   interface, signal_name);
03500 }
03501 
03512 dbus_bool_t
03513 dbus_message_is_error (DBusMessage *message,
03514                        const char  *error_name)
03515 {
03516   const char *n;
03517 
03518   _dbus_return_val_if_fail (message != NULL, FALSE);
03519   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03520   /* don't check that error_name is valid since it would be expensive,
03521    * and not catch many common errors
03522    */
03523 
03524   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03525     return FALSE;
03526 
03527   n = dbus_message_get_error_name (message);
03528 
03529   if (n && strcmp (n, error_name) == 0)
03530     return TRUE;
03531   else
03532     return FALSE;
03533 }
03534 
03545 dbus_bool_t
03546 dbus_message_has_destination (DBusMessage  *message,
03547                               const char   *name)
03548 {
03549   const char *s;
03550 
03551   _dbus_return_val_if_fail (message != NULL, FALSE);
03552   _dbus_return_val_if_fail (name != NULL, FALSE);
03553   /* don't check that name is valid since it would be expensive, and
03554    * not catch many common errors
03555    */
03556 
03557   s = dbus_message_get_destination (message);
03558 
03559   if (s && strcmp (s, name) == 0)
03560     return TRUE;
03561   else
03562     return FALSE;
03563 }
03564 
03580 dbus_bool_t
03581 dbus_message_has_sender (DBusMessage  *message,
03582                          const char   *name)
03583 {
03584   const char *s;
03585 
03586   _dbus_return_val_if_fail (message != NULL, FALSE);
03587   _dbus_return_val_if_fail (name != NULL, FALSE);
03588   /* don't check that name is valid since it would be expensive, and
03589    * not catch many common errors
03590    */
03591 
03592   s = dbus_message_get_sender (message);
03593 
03594   if (s && strcmp (s, name) == 0)
03595     return TRUE;
03596   else
03597     return FALSE;
03598 }
03599 
03609 dbus_bool_t
03610 dbus_message_has_signature (DBusMessage   *message,
03611                             const char    *signature)
03612 {
03613   const char *s;
03614 
03615   _dbus_return_val_if_fail (message != NULL, FALSE);
03616   _dbus_return_val_if_fail (signature != NULL, FALSE);
03617   /* don't check that signature is valid since it would be expensive,
03618    * and not catch many common errors
03619    */
03620 
03621   s = dbus_message_get_signature (message);
03622 
03623   if (s && strcmp (s, signature) == 0)
03624     return TRUE;
03625   else
03626     return FALSE;
03627 }
03628 
03651 dbus_bool_t
03652 dbus_set_error_from_message (DBusError   *error,
03653                              DBusMessage *message)
03654 {
03655   const char *str;
03656 
03657   _dbus_return_val_if_fail (message != NULL, FALSE);
03658   _dbus_return_val_if_error_is_set (error, FALSE);
03659 
03660   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03661     return FALSE;
03662 
03663   str = NULL;
03664   dbus_message_get_args (message, NULL,
03665                          DBUS_TYPE_STRING, &str,
03666                          DBUS_TYPE_INVALID);
03667 
03668   dbus_set_error (error, dbus_message_get_error_name (message),
03669                   str ? "%s" : NULL, str);
03670 
03671   return TRUE;
03672 }
03673 
03680 dbus_bool_t
03681 dbus_message_contains_unix_fds(DBusMessage *message)
03682 {
03683 #ifdef HAVE_UNIX_FD_PASSING
03684   _dbus_assert(message);
03685 
03686   return message->n_unix_fds > 0;
03687 #else
03688   return FALSE;
03689 #endif
03690 }
03691 
03710 #define INITIAL_LOADER_DATA_LEN 32
03711 
03718 DBusMessageLoader*
03719 _dbus_message_loader_new (void)
03720 {
03721   DBusMessageLoader *loader;
03722 
03723   loader = dbus_new0 (DBusMessageLoader, 1);
03724   if (loader == NULL)
03725     return NULL;
03726   
03727   loader->refcount = 1;
03728 
03729   loader->corrupted = FALSE;
03730   loader->corruption_reason = DBUS_VALID;
03731 
03732   /* this can be configured by the app, but defaults to the protocol max */
03733   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03734 
03735   /* We set a very relatively conservative default here since due to how
03736   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03737   number of unix fds we want to receive in advance. A
03738   try-and-reallocate loop is not possible. */
03739   loader->max_message_unix_fds = 1024;
03740 
03741   if (!_dbus_string_init (&loader->data))
03742     {
03743       dbus_free (loader);
03744       return NULL;
03745     }
03746 
03747   /* preallocate the buffer for speed, ignore failure */
03748   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03749   _dbus_string_set_length (&loader->data, 0);
03750 
03751 #ifdef HAVE_UNIX_FD_PASSING
03752   loader->unix_fds = NULL;
03753   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03754   loader->unix_fds_outstanding = FALSE;
03755 #endif
03756 
03757   return loader;
03758 }
03759 
03766 DBusMessageLoader *
03767 _dbus_message_loader_ref (DBusMessageLoader *loader)
03768 {
03769   loader->refcount += 1;
03770 
03771   return loader;
03772 }
03773 
03780 void
03781 _dbus_message_loader_unref (DBusMessageLoader *loader)
03782 {
03783   loader->refcount -= 1;
03784   if (loader->refcount == 0)
03785     {
03786 #ifdef HAVE_UNIX_FD_PASSING
03787       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
03788       dbus_free(loader->unix_fds);
03789 #endif
03790       _dbus_list_foreach (&loader->messages,
03791                           (DBusForeachFunction) dbus_message_unref,
03792                           NULL);
03793       _dbus_list_clear (&loader->messages);
03794       _dbus_string_free (&loader->data);
03795       dbus_free (loader);
03796     }
03797 }
03798 
03817 void
03818 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03819                                  DBusString        **buffer)
03820 {
03821   _dbus_assert (!loader->buffer_outstanding);
03822 
03823   *buffer = &loader->data;
03824 
03825   loader->buffer_outstanding = TRUE;
03826 }
03827 
03838 void
03839 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03840                                     DBusString         *buffer,
03841                                     int                 bytes_read)
03842 {
03843   _dbus_assert (loader->buffer_outstanding);
03844   _dbus_assert (buffer == &loader->data);
03845 
03846   loader->buffer_outstanding = FALSE;
03847 }
03848 
03859 dbus_bool_t
03860 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
03861                                   int               **fds,
03862                                   unsigned           *max_n_fds)
03863 {
03864 #ifdef HAVE_UNIX_FD_PASSING
03865   _dbus_assert (!loader->unix_fds_outstanding);
03866 
03867   /* Allocate space where we can put the fds we read. We allocate
03868      space for max_message_unix_fds since this is an
03869      upper limit how many fds can be received within a single
03870      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
03871      we are allocating the maximum possible array size right from the
03872      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
03873      there is no better way. */
03874 
03875   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
03876     {
03877       int *a = dbus_realloc(loader->unix_fds,
03878                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
03879 
03880       if (!a)
03881         return FALSE;
03882 
03883       loader->unix_fds = a;
03884       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
03885     }
03886 
03887   *fds = loader->unix_fds + loader->n_unix_fds;
03888   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
03889 
03890   loader->unix_fds_outstanding = TRUE;
03891   return TRUE;
03892 #else
03893   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03894   return FALSE;
03895 #endif
03896 }
03897 
03908 void
03909 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
03910                                      int                *fds,
03911                                      unsigned            n_fds)
03912 {
03913 #ifdef HAVE_UNIX_FD_PASSING
03914   _dbus_assert(loader->unix_fds_outstanding);
03915   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
03916   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
03917 
03918   loader->n_unix_fds += n_fds;
03919   loader->unix_fds_outstanding = FALSE;
03920 #else
03921   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03922 #endif
03923 }
03924 
03925 /*
03926  * FIXME when we move the header out of the buffer, that memmoves all
03927  * buffered messages. Kind of crappy.
03928  *
03929  * Also we copy the header and body, which is kind of crappy.  To
03930  * avoid this, we have to allow header and body to be in a single
03931  * memory block, which is good for messages we read and bad for
03932  * messages we are creating. But we could move_len() the buffer into
03933  * this single memory block, and move_len() will just swap the buffers
03934  * if you're moving the entire buffer replacing the dest string.
03935  *
03936  * We could also have the message loader tell the transport how many
03937  * bytes to read; so it would first ask for some arbitrary number like
03938  * 256, then if the message was incomplete it would use the
03939  * header/body len to ask for exactly the size of the message (or
03940  * blocks the size of a typical kernel buffer for the socket). That
03941  * way we don't get trailing bytes in the buffer that have to be
03942  * memmoved. Though I suppose we also don't have a chance of reading a
03943  * bunch of small messages at once, so the optimization may be stupid.
03944  *
03945  * Another approach would be to keep a "start" index into
03946  * loader->data and only delete it occasionally, instead of after
03947  * each message is loaded.
03948  *
03949  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03950  */
03951 static dbus_bool_t
03952 load_message (DBusMessageLoader *loader,
03953               DBusMessage       *message,
03954               int                byte_order,
03955               int                fields_array_len,
03956               int                header_len,
03957               int                body_len)
03958 {
03959   dbus_bool_t oom;
03960   DBusValidity validity;
03961   const DBusString *type_str;
03962   int type_pos;
03963   DBusValidationMode mode;
03964   dbus_uint32_t n_unix_fds = 0;
03965 
03966   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03967   
03968   oom = FALSE;
03969 
03970 #if 0
03971   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03972 #endif
03973 
03974   /* 1. VALIDATE AND COPY OVER HEADER */
03975   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03976   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03977 
03978   if (!_dbus_header_load (&message->header,
03979                           mode,
03980                           &validity,
03981                           byte_order,
03982                           fields_array_len,
03983                           header_len,
03984                           body_len,
03985                           &loader->data, 0,
03986                           _dbus_string_get_length (&loader->data)))
03987     {
03988       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03989 
03990       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03991          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03992       _dbus_assert (validity != DBUS_VALID);
03993 
03994       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03995         oom = TRUE;
03996       else
03997         {
03998           loader->corrupted = TRUE;
03999           loader->corruption_reason = validity;
04000         }
04001       goto failed;
04002     }
04003 
04004   _dbus_assert (validity == DBUS_VALID);
04005 
04006   message->byte_order = byte_order;
04007 
04008   /* 2. VALIDATE BODY */
04009   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04010     {
04011       get_const_signature (&message->header, &type_str, &type_pos);
04012       
04013       /* Because the bytes_remaining arg is NULL, this validates that the
04014        * body is the right length
04015        */
04016       validity = _dbus_validate_body_with_reason (type_str,
04017                                                   type_pos,
04018                                                   byte_order,
04019                                                   NULL,
04020                                                   &loader->data,
04021                                                   header_len,
04022                                                   body_len);
04023       if (validity != DBUS_VALID)
04024         {
04025           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04026 
04027           loader->corrupted = TRUE;
04028           loader->corruption_reason = validity;
04029           
04030           goto failed;
04031         }
04032     }
04033 
04034   /* 3. COPY OVER UNIX FDS */
04035   _dbus_header_get_field_basic(&message->header,
04036                                DBUS_HEADER_FIELD_UNIX_FDS,
04037                                DBUS_TYPE_UINT32,
04038                                &n_unix_fds);
04039 
04040 #ifdef HAVE_UNIX_FD_PASSING
04041 
04042   if (n_unix_fds > loader->n_unix_fds)
04043     {
04044       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04045                     n_unix_fds, loader->n_unix_fds);
04046 
04047       loader->corrupted = TRUE;
04048       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04049       goto failed;
04050     }
04051 
04052   /* If this was a recycled message there might still be
04053      some memory allocated for the fds */
04054   dbus_free(message->unix_fds);
04055 
04056   if (n_unix_fds > 0)
04057     {
04058       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04059       if (message->unix_fds == NULL)
04060         {
04061           _dbus_verbose ("Failed to allocate file descriptor array\n");
04062           oom = TRUE;
04063           goto failed;
04064         }
04065 
04066       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04067       loader->n_unix_fds -= n_unix_fds;
04068       memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds);
04069     }
04070   else
04071     message->unix_fds = NULL;
04072 
04073 #else
04074 
04075   if (n_unix_fds > 0)
04076     {
04077       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04078                      "but that's not supported on our platform, disconnecting.\n");
04079 
04080       loader->corrupted = TRUE;
04081       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04082       goto failed;
04083     }
04084 
04085 #endif
04086 
04087   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04088 
04089   if (!_dbus_list_append (&loader->messages, message))
04090     {
04091       _dbus_verbose ("Failed to append new message to loader queue\n");
04092       oom = TRUE;
04093       goto failed;
04094     }
04095 
04096   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04097   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04098                 (header_len + body_len));
04099 
04100   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04101     {
04102       _dbus_verbose ("Failed to move body into new message\n");
04103       oom = TRUE;
04104       goto failed;
04105     }
04106 
04107   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04108 
04109   /* don't waste more than 2k of memory */
04110   _dbus_string_compact (&loader->data, 2048);
04111 
04112   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04113   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04114 
04115   _dbus_verbose ("Loaded message %p\n", message);
04116 
04117   _dbus_assert (!oom);
04118   _dbus_assert (!loader->corrupted);
04119   _dbus_assert (loader->messages != NULL);
04120   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04121 
04122   return TRUE;
04123 
04124  failed:
04125 
04126   /* Clean up */
04127 
04128   /* does nothing if the message isn't in the list */
04129   _dbus_list_remove_last (&loader->messages, message);
04130   
04131   if (oom)
04132     _dbus_assert (!loader->corrupted);
04133   else
04134     _dbus_assert (loader->corrupted);
04135 
04136   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04137 
04138   return FALSE;
04139 }
04140 
04155 dbus_bool_t
04156 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04157 {
04158   while (!loader->corrupted &&
04159          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04160     {
04161       DBusValidity validity;
04162       int byte_order, fields_array_len, header_len, body_len;
04163 
04164       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04165                                                &validity,
04166                                                &byte_order,
04167                                                &fields_array_len,
04168                                                &header_len,
04169                                                &body_len,
04170                                                &loader->data, 0,
04171                                                _dbus_string_get_length (&loader->data)))
04172         {
04173           DBusMessage *message;
04174 
04175           _dbus_assert (validity == DBUS_VALID);
04176 
04177           message = dbus_message_new_empty_header ();
04178           if (message == NULL)
04179             return FALSE;
04180 
04181           if (!load_message (loader, message,
04182                              byte_order, fields_array_len,
04183                              header_len, body_len))
04184             {
04185               dbus_message_unref (message);
04186               /* load_message() returns false if corrupted or OOM; if
04187                * corrupted then return TRUE for not OOM
04188                */
04189               return loader->corrupted;
04190             }
04191 
04192           _dbus_assert (loader->messages != NULL);
04193           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04194         }
04195       else
04196         {
04197           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04198                          validity);
04199           if (validity != DBUS_VALID)
04200             {
04201               loader->corrupted = TRUE;
04202               loader->corruption_reason = validity;
04203             }
04204           return TRUE;
04205         }
04206     }
04207 
04208   return TRUE;
04209 }
04210 
04218 DBusMessage*
04219 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04220 {
04221   if (loader->messages)
04222     return loader->messages->data;
04223   else
04224     return NULL;
04225 }
04226 
04235 DBusMessage*
04236 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04237 {
04238   return _dbus_list_pop_first (&loader->messages);
04239 }
04240 
04249 DBusList*
04250 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04251 {
04252   return _dbus_list_pop_first_link (&loader->messages);
04253 }
04254 
04261 void
04262 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04263                                            DBusList           *link)
04264 {
04265   _dbus_list_prepend_link (&loader->messages, link);
04266 }
04267 
04277 dbus_bool_t
04278 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04279 {
04280   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04281                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04282   return loader->corrupted;
04283 }
04284 
04291 DBusValidity
04292 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04293 {
04294   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04295                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04296 
04297   return loader->corruption_reason;
04298 }
04299 
04306 void
04307 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04308                                            long                size)
04309 {
04310   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04311     {
04312       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04313                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04314       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04315     }
04316   loader->max_message_size = size;
04317 }
04318 
04325 long
04326 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04327 {
04328   return loader->max_message_size;
04329 }
04330 
04337 void
04338 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04339                                                long                n)
04340 {
04341   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04342     {
04343       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04344                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04345       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04346     }
04347   loader->max_message_unix_fds = n;
04348 }
04349 
04356 long
04357 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04358 {
04359   return loader->max_message_unix_fds;
04360 }
04361 
04362 static DBusDataSlotAllocator slot_allocator;
04363 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
04364 
04379 dbus_bool_t
04380 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04381 {
04382   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04383                                           &_DBUS_LOCK_NAME (message_slots),
04384                                           slot_p);
04385 }
04386 
04398 void
04399 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04400 {
04401   _dbus_return_if_fail (*slot_p >= 0);
04402 
04403   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04404 }
04405 
04419 dbus_bool_t
04420 dbus_message_set_data (DBusMessage     *message,
04421                        dbus_int32_t     slot,
04422                        void            *data,
04423                        DBusFreeFunction free_data_func)
04424 {
04425   DBusFreeFunction old_free_func;
04426   void *old_data;
04427   dbus_bool_t retval;
04428 
04429   _dbus_return_val_if_fail (message != NULL, FALSE);
04430   _dbus_return_val_if_fail (slot >= 0, FALSE);
04431 
04432   retval = _dbus_data_slot_list_set (&slot_allocator,
04433                                      &message->slot_list,
04434                                      slot, data, free_data_func,
04435                                      &old_free_func, &old_data);
04436 
04437   if (retval)
04438     {
04439       /* Do the actual free outside the message lock */
04440       if (old_free_func)
04441         (* old_free_func) (old_data);
04442     }
04443 
04444   return retval;
04445 }
04446 
04455 void*
04456 dbus_message_get_data (DBusMessage   *message,
04457                        dbus_int32_t   slot)
04458 {
04459   void *res;
04460 
04461   _dbus_return_val_if_fail (message != NULL, NULL);
04462 
04463   res = _dbus_data_slot_list_get (&slot_allocator,
04464                                   &message->slot_list,
04465                                   slot);
04466 
04467   return res;
04468 }
04469 
04483 int
04484 dbus_message_type_from_string (const char *type_str)
04485 {
04486   if (strcmp (type_str, "method_call") == 0)
04487     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04488   if (strcmp (type_str, "method_return") == 0)
04489     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04490   else if (strcmp (type_str, "signal") == 0)
04491     return DBUS_MESSAGE_TYPE_SIGNAL;
04492   else if (strcmp (type_str, "error") == 0)
04493     return DBUS_MESSAGE_TYPE_ERROR;
04494   else
04495     return DBUS_MESSAGE_TYPE_INVALID;
04496 }
04497 
04511 const char *
04512 dbus_message_type_to_string (int type)
04513 {
04514   switch (type)
04515     {
04516     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04517       return "method_call";
04518     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04519       return "method_return";
04520     case DBUS_MESSAGE_TYPE_SIGNAL:
04521       return "signal";
04522     case DBUS_MESSAGE_TYPE_ERROR:
04523       return "error";
04524     default:
04525       return "invalid";
04526     }
04527 }
04528 
04541 dbus_bool_t
04542 dbus_message_marshal (DBusMessage  *msg,
04543                       char        **marshalled_data_p,
04544                       int          *len_p)
04545 {
04546   DBusString tmp;
04547   dbus_bool_t was_locked;
04548 
04549   _dbus_return_val_if_fail (msg != NULL, FALSE);
04550   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04551   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04552   
04553   if (!_dbus_string_init (&tmp))
04554     return FALSE;
04555 
04556   /* Ensure the message is locked, to ensure the length header is filled in. */
04557   was_locked = msg->locked;
04558 
04559   if (!was_locked)
04560     dbus_message_lock (msg);
04561 
04562   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04563     goto fail;
04564 
04565   *len_p = _dbus_string_get_length (&tmp);
04566 
04567   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04568     goto fail;
04569 
04570   *len_p = _dbus_string_get_length (&tmp);
04571 
04572   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04573     goto fail;
04574 
04575   _dbus_string_free (&tmp);
04576 
04577   if (!was_locked)
04578     msg->locked = FALSE;
04579 
04580   return TRUE;
04581 
04582  fail:
04583   _dbus_string_free (&tmp);
04584 
04585   if (!was_locked)
04586     msg->locked = FALSE;
04587 
04588   return FALSE;
04589 }
04590 
04603 DBusMessage *
04604 dbus_message_demarshal (const char *str,
04605                         int         len,
04606                         DBusError  *error)
04607 {
04608   DBusMessageLoader *loader;
04609   DBusString *buffer;
04610   DBusMessage *msg;
04611 
04612   _dbus_return_val_if_fail (str != NULL, NULL);
04613 
04614   loader = _dbus_message_loader_new ();
04615 
04616   if (loader == NULL)
04617     return NULL;
04618 
04619   _dbus_message_loader_get_buffer (loader, &buffer);
04620   _dbus_string_append_len (buffer, str, len);
04621   _dbus_message_loader_return_buffer (loader, buffer, len);
04622 
04623   if (!_dbus_message_loader_queue_messages (loader))
04624     goto fail_oom;
04625 
04626   if (_dbus_message_loader_get_is_corrupted (loader))
04627     goto fail_corrupt;
04628 
04629   msg = _dbus_message_loader_pop_message (loader);
04630 
04631   if (!msg)
04632     goto fail_oom;
04633 
04634   _dbus_message_loader_unref (loader);
04635   return msg;
04636 
04637  fail_corrupt:
04638   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04639                   _dbus_validity_to_error_message (loader->corruption_reason));
04640   _dbus_message_loader_unref (loader);
04641   return NULL;
04642 
04643  fail_oom:
04644   _DBUS_SET_OOM (error);
04645   _dbus_message_loader_unref (loader);
04646   return NULL;
04647 }
04648 
04662 int 
04663 dbus_message_demarshal_bytes_needed(const char *buf, 
04664                                     int         len)
04665 {
04666   DBusString str;
04667   int byte_order, fields_array_len, header_len, body_len;
04668   DBusValidity validity = DBUS_VALID;
04669   int have_message;
04670 
04671   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04672     return 0;
04673 
04674   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04675     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04676   _dbus_string_init_const_len (&str, buf, len);
04677   
04678   validity = DBUS_VALID;
04679   have_message
04680     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04681                                           &validity, &byte_order,
04682                                           &fields_array_len,
04683                                           &header_len,
04684                                           &body_len,
04685                                           &str, 0,
04686                                           len);
04687   _dbus_string_free (&str);
04688 
04689   if (validity == DBUS_VALID)
04690     {
04691       _dbus_assert (have_message || (header_len + body_len) > len);
04692       return header_len + body_len;
04693     }
04694   else
04695     {
04696       return -1; /* broken! */
04697     }
04698 }
04699 
04702 /* tests in dbus-message-util.c */