D-Bus  1.4.18
dbus-message.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-validate.h"
00029 #include "dbus-marshal-byteswap.h"
00030 #include "dbus-marshal-header.h"
00031 #include "dbus-signature.h"
00032 #include "dbus-message-private.h"
00033 #include "dbus-object-tree.h"
00034 #include "dbus-memory.h"
00035 #include "dbus-list.h"
00036 #include "dbus-threads-internal.h"
00037 #ifdef HAVE_UNIX_FD_PASSING
00038 #include "dbus-sysdeps.h"
00039 #include "dbus-sysdeps-unix.h"
00040 #endif
00041 
00042 #include <string.h>
00043 
00044 static void dbus_message_finalize (DBusMessage *message);
00045 
00056 /* Not thread locked, but strictly const/read-only so should be OK
00057  */
00059 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
00060 
00061 /* these have wacky values to help trap uninitialized iterators;
00062  * but has to fit in 3 bits
00063  */
00064 enum {
00065   DBUS_MESSAGE_ITER_TYPE_READER = 3,
00066   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
00067 };
00068 
00070 typedef struct DBusMessageRealIter DBusMessageRealIter;
00071 
00077 struct DBusMessageRealIter
00078 {
00079   DBusMessage *message; 
00080   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 
00081   dbus_uint32_t iter_type : 3;      
00082   dbus_uint32_t sig_refcount : 8;   
00083   union
00084   {
00085     DBusTypeWriter writer; 
00086     DBusTypeReader reader; 
00087   } u; 
00088 };
00089 
00090 static void
00091 get_const_signature (DBusHeader        *header,
00092                      const DBusString **type_str_p,
00093                      int               *type_pos_p)
00094 {
00095   if (_dbus_header_get_field_raw (header,
00096                                   DBUS_HEADER_FIELD_SIGNATURE,
00097                                   type_str_p,
00098                                   type_pos_p))
00099     {
00100       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00101     }
00102   else
00103     {
00104       *type_str_p = &_dbus_empty_signature_str;
00105       *type_pos_p = 0;
00106     }
00107 }
00108 
00114 static void
00115 _dbus_message_byteswap (DBusMessage *message)
00116 {
00117   const DBusString *type_str;
00118   int type_pos;
00119   
00120   if (message->byte_order == DBUS_COMPILER_BYTE_ORDER)
00121     return;
00122 
00123   _dbus_verbose ("Swapping message into compiler byte order\n");
00124   
00125   get_const_signature (&message->header, &type_str, &type_pos);
00126   
00127   _dbus_marshal_byteswap (type_str, type_pos,
00128                           message->byte_order,
00129                           DBUS_COMPILER_BYTE_ORDER,
00130                           &message->body, 0);
00131 
00132   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00133   
00134   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00135 }
00136 
00143 #define ensure_byte_order(message)                      \
00144  if (message->byte_order != DBUS_COMPILER_BYTE_ORDER)   \
00145    _dbus_message_byteswap (message)
00146 
00157 void
00158 _dbus_message_get_network_data (DBusMessage          *message,
00159                                 const DBusString    **header,
00160                                 const DBusString    **body)
00161 {
00162   _dbus_assert (message->locked);
00163 
00164   *header = &message->header.data;
00165   *body = &message->body;
00166 }
00167 
00177 void _dbus_message_get_unix_fds(DBusMessage *message,
00178                                 const int  **fds,
00179                                 unsigned    *n_fds)
00180 {
00181   _dbus_assert (message->locked);
00182 
00183 #ifdef HAVE_UNIX_FD_PASSING
00184   *fds = message->unix_fds;
00185   *n_fds = message->n_unix_fds;
00186 #else
00187   *fds = NULL;
00188   *n_fds = 0;
00189 #endif
00190 }
00191 
00203 void 
00204 dbus_message_set_serial (DBusMessage   *message,
00205                          dbus_uint32_t  serial)
00206 {
00207   _dbus_return_if_fail (message != NULL);
00208   _dbus_return_if_fail (!message->locked);
00209 
00210   _dbus_header_set_serial (&message->header, serial);
00211 }
00212 
00224 void
00225 _dbus_message_add_counter_link (DBusMessage  *message,
00226                                 DBusList     *link)
00227 {
00228   /* right now we don't recompute the delta when message
00229    * size changes, and that's OK for current purposes
00230    * I think, but could be important to change later.
00231    * Do recompute it whenever there are no outstanding counters,
00232    * since it's basically free.
00233    */
00234   if (message->counters == NULL)
00235     {
00236       message->size_counter_delta =
00237         _dbus_string_get_length (&message->header.data) +
00238         _dbus_string_get_length (&message->body);
00239 
00240 #ifdef HAVE_UNIX_FD_PASSING
00241       message->unix_fd_counter_delta = message->n_unix_fds;
00242 #endif
00243 
00244 #if 0
00245       _dbus_verbose ("message has size %ld\n",
00246                      message->size_counter_delta);
00247 #endif
00248     }
00249 
00250   _dbus_list_append_link (&message->counters, link);
00251 
00252   _dbus_counter_adjust_size (link->data, message->size_counter_delta);
00253 
00254 #ifdef HAVE_UNIX_FD_PASSING
00255   _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
00256 #endif
00257 }
00258 
00268 dbus_bool_t
00269 _dbus_message_add_counter (DBusMessage *message,
00270                            DBusCounter *counter)
00271 {
00272   DBusList *link;
00273 
00274   link = _dbus_list_alloc_link (counter);
00275   if (link == NULL)
00276     return FALSE;
00277 
00278   _dbus_counter_ref (counter);
00279   _dbus_message_add_counter_link (message, link);
00280 
00281   return TRUE;
00282 }
00283 
00292 void
00293 _dbus_message_remove_counter (DBusMessage  *message,
00294                               DBusCounter  *counter,
00295                               DBusList    **link_return)
00296 {
00297   DBusList *link;
00298 
00299   link = _dbus_list_find_last (&message->counters,
00300                                counter);
00301   _dbus_assert (link != NULL);
00302 
00303   _dbus_list_unlink (&message->counters,
00304                      link);
00305   if (link_return)
00306     *link_return = link;
00307   else
00308     _dbus_list_free_link (link);
00309 
00310   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00311 
00312 #ifdef HAVE_UNIX_FD_PASSING
00313   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00314 #endif
00315 
00316   _dbus_counter_unref (counter);
00317 }
00318 
00329 void
00330 dbus_message_lock (DBusMessage  *message)
00331 {
00332   if (!message->locked)
00333     {
00334       _dbus_header_update_lengths (&message->header,
00335                                    _dbus_string_get_length (&message->body));
00336 
00337       /* must have a signature if you have a body */
00338       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00339                     dbus_message_get_signature (message) != NULL);
00340 
00341       message->locked = TRUE;
00342     }
00343 }
00344 
00345 static dbus_bool_t
00346 set_or_delete_string_field (DBusMessage *message,
00347                             int          field,
00348                             int          typecode,
00349                             const char  *value)
00350 {
00351   if (value == NULL)
00352     return _dbus_header_delete_field (&message->header, field);
00353   else
00354     return _dbus_header_set_field_basic (&message->header,
00355                                          field,
00356                                          typecode,
00357                                          &value);
00358 }
00359 
00360 #if 0
00361 /* Probably we don't need to use this */
00385 static dbus_bool_t
00386 _dbus_message_set_signature (DBusMessage *message,
00387                              const char  *signature)
00388 {
00389   _dbus_return_val_if_fail (message != NULL, FALSE);
00390   _dbus_return_val_if_fail (!message->locked, FALSE);
00391   _dbus_return_val_if_fail (signature == NULL ||
00392                             _dbus_check_is_valid_signature (signature));
00393   /* can't delete the signature if you have a message body */
00394   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00395                             signature != NULL);
00396 
00397   return set_or_delete_string_field (message,
00398                                      DBUS_HEADER_FIELD_SIGNATURE,
00399                                      DBUS_TYPE_SIGNATURE,
00400                                      signature);
00401 }
00402 #endif
00403 
00404 /* Message Cache
00405  *
00406  * We cache some DBusMessage to reduce the overhead of allocating
00407  * them.  In my profiling this consistently made about an 8%
00408  * difference.  It avoids the malloc for the message, the malloc for
00409  * the slot list, the malloc for the header string and body string,
00410  * and the associated free() calls. It does introduce another global
00411  * lock which could be a performance issue in certain cases.
00412  *
00413  * For the echo client/server the round trip time goes from around
00414  * .000077 to .000069 with the message cache on my laptop. The sysprof
00415  * change is as follows (numbers are cumulative percentage):
00416  *
00417  *  with message cache implemented as array as it is now (0.000069 per):
00418  *    new_empty_header           1.46
00419  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00420  *      mutex_unlock             0.25
00421  *      self                     0.41
00422  *    unref                      2.24
00423  *      self                     0.68
00424  *      list_clear               0.43
00425  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00426  *      mutex_unlock             0.25
00427  *
00428  *  with message cache implemented as list (0.000070 per roundtrip):
00429  *    new_empty_header           2.72
00430  *      list_pop_first           1.88
00431  *    unref                      3.3
00432  *      list_prepend             1.63
00433  *
00434  * without cache (0.000077 per roundtrip):
00435  *    new_empty_header           6.7
00436  *      string_init_preallocated 3.43
00437  *        dbus_malloc            2.43
00438  *      dbus_malloc0             2.59
00439  *
00440  *    unref                      4.02
00441  *      string_free              1.82
00442  *        dbus_free              1.63
00443  *      dbus_free                0.71
00444  *
00445  * If you implement the message_cache with a list, the primary reason
00446  * it's slower is that you add another thread lock (on the DBusList
00447  * mempool).
00448  */
00449 
00451 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00452 
00454 #define MAX_MESSAGE_CACHE_SIZE    5
00455 
00456 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00457 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00458 static int message_cache_count = 0;
00459 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00460 
00461 static void
00462 dbus_message_cache_shutdown (void *data)
00463 {
00464   int i;
00465 
00466   _DBUS_LOCK (message_cache);
00467 
00468   i = 0;
00469   while (i < MAX_MESSAGE_CACHE_SIZE)
00470     {
00471       if (message_cache[i])
00472         dbus_message_finalize (message_cache[i]);
00473 
00474       ++i;
00475     }
00476 
00477   message_cache_count = 0;
00478   message_cache_shutdown_registered = FALSE;
00479 
00480   _DBUS_UNLOCK (message_cache);
00481 }
00482 
00490 static DBusMessage*
00491 dbus_message_get_cached (void)
00492 {
00493   DBusMessage *message;
00494   int i;
00495 
00496   message = NULL;
00497 
00498   _DBUS_LOCK (message_cache);
00499 
00500   _dbus_assert (message_cache_count >= 0);
00501 
00502   if (message_cache_count == 0)
00503     {
00504       _DBUS_UNLOCK (message_cache);
00505       return NULL;
00506     }
00507 
00508   /* This is not necessarily true unless count > 0, and
00509    * message_cache is uninitialized until the shutdown is
00510    * registered
00511    */
00512   _dbus_assert (message_cache_shutdown_registered);
00513 
00514   i = 0;
00515   while (i < MAX_MESSAGE_CACHE_SIZE)
00516     {
00517       if (message_cache[i])
00518         {
00519           message = message_cache[i];
00520           message_cache[i] = NULL;
00521           message_cache_count -= 1;
00522           break;
00523         }
00524       ++i;
00525     }
00526   _dbus_assert (message_cache_count >= 0);
00527   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00528   _dbus_assert (message != NULL);
00529 
00530   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00531 
00532   _dbus_assert (message->counters == NULL);
00533   
00534   _DBUS_UNLOCK (message_cache);
00535 
00536   return message;
00537 }
00538 
00539 #ifdef HAVE_UNIX_FD_PASSING
00540 static void
00541 close_unix_fds(int *fds, unsigned *n_fds)
00542 {
00543   DBusError e;
00544   int i;
00545 
00546   if (*n_fds <= 0)
00547     return;
00548 
00549   dbus_error_init(&e);
00550 
00551   for (i = 0; i < *n_fds; i++)
00552     {
00553       if (!_dbus_close(fds[i], &e))
00554         {
00555           _dbus_warn("Failed to close file descriptor: %s\n", e.message);
00556           dbus_error_free(&e);
00557         }
00558     }
00559 
00560   *n_fds = 0;
00561 
00562   /* We don't free the array here, in case we can recycle it later */
00563 }
00564 #endif
00565 
00566 static void
00567 free_counter (void *element,
00568               void *data)
00569 {
00570   DBusCounter *counter = element;
00571   DBusMessage *message = data;
00572 
00573   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00574 #ifdef HAVE_UNIX_FD_PASSING
00575   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00576 #endif
00577 
00578   _dbus_counter_unref (counter);
00579 }
00580 
00586 static void
00587 dbus_message_cache_or_finalize (DBusMessage *message)
00588 {
00589   dbus_bool_t was_cached;
00590   int i;
00591 
00592   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00593 
00594   /* This calls application code and has to be done first thing
00595    * without holding the lock
00596    */
00597   _dbus_data_slot_list_clear (&message->slot_list);
00598 
00599   _dbus_list_foreach (&message->counters,
00600                       free_counter, message);
00601   _dbus_list_clear (&message->counters);
00602 
00603 #ifdef HAVE_UNIX_FD_PASSING
00604   close_unix_fds(message->unix_fds, &message->n_unix_fds);
00605 #endif
00606 
00607   was_cached = FALSE;
00608 
00609   _DBUS_LOCK (message_cache);
00610 
00611   if (!message_cache_shutdown_registered)
00612     {
00613       _dbus_assert (message_cache_count == 0);
00614 
00615       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00616         goto out;
00617 
00618       i = 0;
00619       while (i < MAX_MESSAGE_CACHE_SIZE)
00620         {
00621           message_cache[i] = NULL;
00622           ++i;
00623         }
00624 
00625       message_cache_shutdown_registered = TRUE;
00626     }
00627 
00628   _dbus_assert (message_cache_count >= 0);
00629 
00630   if ((_dbus_string_get_length (&message->header.data) +
00631        _dbus_string_get_length (&message->body)) >
00632       MAX_MESSAGE_SIZE_TO_CACHE)
00633     goto out;
00634 
00635   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00636     goto out;
00637 
00638   /* Find empty slot */
00639   i = 0;
00640   while (message_cache[i] != NULL)
00641     ++i;
00642 
00643   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00644 
00645   _dbus_assert (message_cache[i] == NULL);
00646   message_cache[i] = message;
00647   message_cache_count += 1;
00648   was_cached = TRUE;
00649 #ifndef DBUS_DISABLE_CHECKS
00650   message->in_cache = TRUE;
00651 #endif
00652 
00653  out:
00654   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00655 
00656   _DBUS_UNLOCK (message_cache);
00657   
00658   if (!was_cached)
00659     dbus_message_finalize (message);
00660 }
00661 
00662 #ifndef DBUS_DISABLE_CHECKS
00663 static dbus_bool_t
00664 _dbus_message_iter_check (DBusMessageRealIter *iter)
00665 {
00666   if (iter == NULL)
00667     {
00668       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00669       return FALSE;
00670     }
00671 
00672   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00673     {
00674       if (iter->u.reader.byte_order != iter->message->byte_order)
00675         {
00676           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00677           return FALSE;
00678         }
00679       /* because we swap the message into compiler order when you init an iter */
00680       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00681     }
00682   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00683     {
00684       if (iter->u.writer.byte_order != iter->message->byte_order)
00685         {
00686           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00687           return FALSE;
00688         }
00689       /* because we swap the message into compiler order when you init an iter */
00690       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00691     }
00692   else
00693     {
00694       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00695       return FALSE;
00696     }
00697 
00698   if (iter->changed_stamp != iter->message->changed_stamp)
00699     {
00700       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00701       return FALSE;
00702     }
00703 
00704   return TRUE;
00705 }
00706 #endif /* DBUS_DISABLE_CHECKS */
00707 
00722 dbus_bool_t
00723 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00724                                     DBusError       *error,
00725                                     int              first_arg_type,
00726                                     va_list          var_args)
00727 {
00728   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00729   int spec_type, msg_type, i;
00730   dbus_bool_t retval;
00731 
00732   _dbus_assert (_dbus_message_iter_check (real));
00733 
00734   retval = FALSE;
00735 
00736   spec_type = first_arg_type;
00737   i = 0;
00738 
00739   while (spec_type != DBUS_TYPE_INVALID)
00740     {
00741       msg_type = dbus_message_iter_get_arg_type (iter);
00742 
00743       if (msg_type != spec_type)
00744         {
00745           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00746                           "Argument %d is specified to be of type \"%s\", but "
00747                           "is actually of type \"%s\"\n", i,
00748                           _dbus_type_to_string (spec_type),
00749                           _dbus_type_to_string (msg_type));
00750 
00751           goto out;
00752         }
00753 
00754       if (spec_type == DBUS_TYPE_UNIX_FD)
00755         {
00756 #ifdef HAVE_UNIX_FD_PASSING
00757           DBusBasicValue idx;
00758           int *pfd, nfd;
00759 
00760           pfd = va_arg (var_args, int*);
00761           _dbus_assert(pfd);
00762 
00763           _dbus_type_reader_read_basic(&real->u.reader, &idx);
00764 
00765           if (idx.u32 >= real->message->n_unix_fds)
00766             {
00767               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
00768                               "Message refers to file descriptor at index %i,"
00769                               "but has only %i descriptors attached.\n",
00770                               idx.u32,
00771                               real->message->n_unix_fds);
00772               goto out;
00773             }
00774 
00775           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
00776             goto out;
00777 
00778           *pfd = nfd;
00779 #else
00780           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00781                           "Platform does not support file desciptor passing.\n");
00782           goto out;
00783 #endif
00784         }
00785       else if (dbus_type_is_basic (spec_type))
00786         {
00787           DBusBasicValue *ptr;
00788 
00789           ptr = va_arg (var_args, DBusBasicValue*);
00790 
00791           _dbus_assert (ptr != NULL);
00792 
00793           _dbus_type_reader_read_basic (&real->u.reader,
00794                                         ptr);
00795         }
00796       else if (spec_type == DBUS_TYPE_ARRAY)
00797         {
00798           int element_type;
00799           int spec_element_type;
00800           const DBusBasicValue **ptr;
00801           int *n_elements_p;
00802           DBusTypeReader array;
00803 
00804           spec_element_type = va_arg (var_args, int);
00805           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00806 
00807           if (spec_element_type != element_type)
00808             {
00809               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00810                               "Argument %d is specified to be an array of \"%s\", but "
00811                               "is actually an array of \"%s\"\n",
00812                               i,
00813                               _dbus_type_to_string (spec_element_type),
00814                               _dbus_type_to_string (element_type));
00815 
00816               goto out;
00817             }
00818 
00819           if (dbus_type_is_fixed (spec_element_type) &&
00820               element_type != DBUS_TYPE_UNIX_FD)
00821             {
00822               ptr = va_arg (var_args, const DBusBasicValue**);
00823               n_elements_p = va_arg (var_args, int*);
00824 
00825               _dbus_assert (ptr != NULL);
00826               _dbus_assert (n_elements_p != NULL);
00827 
00828               _dbus_type_reader_recurse (&real->u.reader, &array);
00829 
00830               _dbus_type_reader_read_fixed_multi (&array,
00831                                                   (void *) ptr, n_elements_p);
00832             }
00833           else if (spec_element_type == DBUS_TYPE_STRING ||
00834                    spec_element_type == DBUS_TYPE_SIGNATURE ||
00835                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
00836             {
00837               char ***str_array_p;
00838               int n_elements;
00839               char **str_array;
00840 
00841               str_array_p = va_arg (var_args, char***);
00842               n_elements_p = va_arg (var_args, int*);
00843 
00844               _dbus_assert (str_array_p != NULL);
00845               _dbus_assert (n_elements_p != NULL);
00846 
00847               /* Count elements in the array */
00848               _dbus_type_reader_recurse (&real->u.reader, &array);
00849 
00850               n_elements = 0;
00851               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00852                 {
00853                   ++n_elements;
00854                   _dbus_type_reader_next (&array);
00855                 }
00856 
00857               str_array = dbus_new0 (char*, n_elements + 1);
00858               if (str_array == NULL)
00859                 {
00860                   _DBUS_SET_OOM (error);
00861                   goto out;
00862                 }
00863 
00864               /* Now go through and dup each string */
00865               _dbus_type_reader_recurse (&real->u.reader, &array);
00866 
00867               i = 0;
00868               while (i < n_elements)
00869                 {
00870                   const char *s;
00871                   _dbus_type_reader_read_basic (&array,
00872                                                 (void *) &s);
00873                   
00874                   str_array[i] = _dbus_strdup (s);
00875                   if (str_array[i] == NULL)
00876                     {
00877                       dbus_free_string_array (str_array);
00878                       _DBUS_SET_OOM (error);
00879                       goto out;
00880                     }
00881                   
00882                   ++i;
00883                   
00884                   if (!_dbus_type_reader_next (&array))
00885                     _dbus_assert (i == n_elements);
00886                 }
00887 
00888               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00889               _dbus_assert (i == n_elements);
00890               _dbus_assert (str_array[i] == NULL);
00891 
00892               *str_array_p = str_array;
00893               *n_elements_p = n_elements;
00894             }
00895 #ifndef DBUS_DISABLE_CHECKS
00896           else
00897             {
00898               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00899                           _DBUS_FUNCTION_NAME);
00900               goto out;
00901             }
00902 #endif
00903         }
00904 #ifndef DBUS_DISABLE_CHECKS
00905       else
00906         {
00907           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00908                       _DBUS_FUNCTION_NAME);
00909           goto out;
00910         }
00911 #endif
00912 
00913       spec_type = va_arg (var_args, int);
00914       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00915         {
00916           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00917                           "Message has only %d arguments, but more were expected", i);
00918           goto out;
00919         }
00920 
00921       i++;
00922     }
00923 
00924   retval = TRUE;
00925 
00926  out:
00927 
00928   return retval;
00929 }
00930 
00989 dbus_uint32_t
00990 dbus_message_get_serial (DBusMessage *message)
00991 {
00992   _dbus_return_val_if_fail (message != NULL, 0);
00993 
00994   return _dbus_header_get_serial (&message->header);
00995 }
00996 
01005 dbus_bool_t
01006 dbus_message_set_reply_serial (DBusMessage   *message,
01007                                dbus_uint32_t  reply_serial)
01008 {
01009   _dbus_return_val_if_fail (message != NULL, FALSE);
01010   _dbus_return_val_if_fail (!message->locked, FALSE);
01011   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01012 
01013   return _dbus_header_set_field_basic (&message->header,
01014                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01015                                        DBUS_TYPE_UINT32,
01016                                        &reply_serial);
01017 }
01018 
01025 dbus_uint32_t
01026 dbus_message_get_reply_serial  (DBusMessage *message)
01027 {
01028   dbus_uint32_t v_UINT32;
01029 
01030   _dbus_return_val_if_fail (message != NULL, 0);
01031 
01032   if (_dbus_header_get_field_basic (&message->header,
01033                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01034                                     DBUS_TYPE_UINT32,
01035                                     &v_UINT32))
01036     return v_UINT32;
01037   else
01038     return 0;
01039 }
01040 
01041 static void
01042 dbus_message_finalize (DBusMessage *message)
01043 {
01044   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01045 
01046   /* This calls application callbacks! */
01047   _dbus_data_slot_list_free (&message->slot_list);
01048 
01049   _dbus_list_foreach (&message->counters,
01050                       free_counter, message);
01051   _dbus_list_clear (&message->counters);
01052 
01053   _dbus_header_free (&message->header);
01054   _dbus_string_free (&message->body);
01055 
01056 #ifdef HAVE_UNIX_FD_PASSING
01057   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01058   dbus_free(message->unix_fds);
01059 #endif
01060 
01061   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01062 
01063   dbus_free (message);
01064 }
01065 
01066 static DBusMessage*
01067 dbus_message_new_empty_header (void)
01068 {
01069   DBusMessage *message;
01070   dbus_bool_t from_cache;
01071 
01072   message = dbus_message_get_cached ();
01073 
01074   if (message != NULL)
01075     {
01076       from_cache = TRUE;
01077     }
01078   else
01079     {
01080       from_cache = FALSE;
01081       message = dbus_new0 (DBusMessage, 1);
01082       if (message == NULL)
01083         return NULL;
01084 #ifndef DBUS_DISABLE_CHECKS
01085       message->generation = _dbus_current_generation;
01086 #endif
01087 
01088 #ifdef HAVE_UNIX_FD_PASSING
01089       message->unix_fds = NULL;
01090       message->n_unix_fds_allocated = 0;
01091 #endif
01092     }
01093 
01094   _dbus_atomic_inc (&message->refcount);
01095 
01096   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
01097   message->locked = FALSE;
01098 #ifndef DBUS_DISABLE_CHECKS
01099   message->in_cache = FALSE;
01100 #endif
01101   message->counters = NULL;
01102   message->size_counter_delta = 0;
01103   message->changed_stamp = 0;
01104 
01105 #ifdef HAVE_UNIX_FD_PASSING
01106   message->n_unix_fds = 0;
01107   message->n_unix_fds_allocated = 0;
01108   message->unix_fd_counter_delta = 0;
01109 #endif
01110 
01111   if (!from_cache)
01112     _dbus_data_slot_list_init (&message->slot_list);
01113 
01114   if (from_cache)
01115     {
01116       _dbus_header_reinit (&message->header, message->byte_order);
01117       _dbus_string_set_length (&message->body, 0);
01118     }
01119   else
01120     {
01121       if (!_dbus_header_init (&message->header, message->byte_order))
01122         {
01123           dbus_free (message);
01124           return NULL;
01125         }
01126 
01127       if (!_dbus_string_init_preallocated (&message->body, 32))
01128         {
01129           _dbus_header_free (&message->header);
01130           dbus_free (message);
01131           return NULL;
01132         }
01133     }
01134 
01135   return message;
01136 }
01137 
01150 DBusMessage*
01151 dbus_message_new (int message_type)
01152 {
01153   DBusMessage *message;
01154 
01155   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01156 
01157   message = dbus_message_new_empty_header ();
01158   if (message == NULL)
01159     return NULL;
01160 
01161   if (!_dbus_header_create (&message->header,
01162                             message_type,
01163                             NULL, NULL, NULL, NULL, NULL))
01164     {
01165       dbus_message_unref (message);
01166       return NULL;
01167     }
01168 
01169   return message;
01170 }
01171 
01193 DBusMessage*
01194 dbus_message_new_method_call (const char *destination,
01195                               const char *path,
01196                               const char *interface,
01197                               const char *method)
01198 {
01199   DBusMessage *message;
01200 
01201   _dbus_return_val_if_fail (path != NULL, NULL);
01202   _dbus_return_val_if_fail (method != NULL, NULL);
01203   _dbus_return_val_if_fail (destination == NULL ||
01204                             _dbus_check_is_valid_bus_name (destination), NULL);
01205   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01206   _dbus_return_val_if_fail (interface == NULL ||
01207                             _dbus_check_is_valid_interface (interface), NULL);
01208   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01209 
01210   message = dbus_message_new_empty_header ();
01211   if (message == NULL)
01212     return NULL;
01213 
01214   if (!_dbus_header_create (&message->header,
01215                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01216                             destination, path, interface, method, NULL))
01217     {
01218       dbus_message_unref (message);
01219       return NULL;
01220     }
01221 
01222   return message;
01223 }
01224 
01232 DBusMessage*
01233 dbus_message_new_method_return (DBusMessage *method_call)
01234 {
01235   DBusMessage *message;
01236   const char *sender;
01237 
01238   _dbus_return_val_if_fail (method_call != NULL, NULL);
01239 
01240   sender = dbus_message_get_sender (method_call);
01241 
01242   /* sender is allowed to be null here in peer-to-peer case */
01243 
01244   message = dbus_message_new_empty_header ();
01245   if (message == NULL)
01246     return NULL;
01247 
01248   if (!_dbus_header_create (&message->header,
01249                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01250                             sender, NULL, NULL, NULL, NULL))
01251     {
01252       dbus_message_unref (message);
01253       return NULL;
01254     }
01255 
01256   dbus_message_set_no_reply (message, TRUE);
01257 
01258   if (!dbus_message_set_reply_serial (message,
01259                                       dbus_message_get_serial (method_call)))
01260     {
01261       dbus_message_unref (message);
01262       return NULL;
01263     }
01264 
01265   return message;
01266 }
01267 
01282 DBusMessage*
01283 dbus_message_new_signal (const char *path,
01284                          const char *interface,
01285                          const char *name)
01286 {
01287   DBusMessage *message;
01288 
01289   _dbus_return_val_if_fail (path != NULL, NULL);
01290   _dbus_return_val_if_fail (interface != NULL, NULL);
01291   _dbus_return_val_if_fail (name != NULL, NULL);
01292   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01293   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
01294   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01295 
01296   message = dbus_message_new_empty_header ();
01297   if (message == NULL)
01298     return NULL;
01299 
01300   if (!_dbus_header_create (&message->header,
01301                             DBUS_MESSAGE_TYPE_SIGNAL,
01302                             NULL, path, interface, name, NULL))
01303     {
01304       dbus_message_unref (message);
01305       return NULL;
01306     }
01307 
01308   dbus_message_set_no_reply (message, TRUE);
01309 
01310   return message;
01311 }
01312 
01327 DBusMessage*
01328 dbus_message_new_error (DBusMessage *reply_to,
01329                         const char  *error_name,
01330                         const char  *error_message)
01331 {
01332   DBusMessage *message;
01333   const char *sender;
01334   DBusMessageIter iter;
01335 
01336   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01337   _dbus_return_val_if_fail (error_name != NULL, NULL);
01338   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01339 
01340   sender = dbus_message_get_sender (reply_to);
01341 
01342   /* sender may be NULL for non-message-bus case or
01343    * when the message bus is dealing with an unregistered
01344    * connection.
01345    */
01346   message = dbus_message_new_empty_header ();
01347   if (message == NULL)
01348     return NULL;
01349 
01350   if (!_dbus_header_create (&message->header,
01351                             DBUS_MESSAGE_TYPE_ERROR,
01352                             sender, NULL, NULL, NULL, error_name))
01353     {
01354       dbus_message_unref (message);
01355       return NULL;
01356     }
01357 
01358   dbus_message_set_no_reply (message, TRUE);
01359 
01360   if (!dbus_message_set_reply_serial (message,
01361                                       dbus_message_get_serial (reply_to)))
01362     {
01363       dbus_message_unref (message);
01364       return NULL;
01365     }
01366 
01367   if (error_message != NULL)
01368     {
01369       dbus_message_iter_init_append (message, &iter);
01370       if (!dbus_message_iter_append_basic (&iter,
01371                                            DBUS_TYPE_STRING,
01372                                            &error_message))
01373         {
01374           dbus_message_unref (message);
01375           return NULL;
01376         }
01377     }
01378 
01379   return message;
01380 }
01381 
01398 DBusMessage*
01399 dbus_message_new_error_printf (DBusMessage *reply_to,
01400                                const char  *error_name,
01401                                const char  *error_format,
01402                                ...)
01403 {
01404   va_list args;
01405   DBusString str;
01406   DBusMessage *message;
01407 
01408   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01409   _dbus_return_val_if_fail (error_name != NULL, NULL);
01410   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01411 
01412   if (!_dbus_string_init (&str))
01413     return NULL;
01414 
01415   va_start (args, error_format);
01416 
01417   if (_dbus_string_append_printf_valist (&str, error_format, args))
01418     message = dbus_message_new_error (reply_to, error_name,
01419                                       _dbus_string_get_const_data (&str));
01420   else
01421     message = NULL;
01422 
01423   _dbus_string_free (&str);
01424 
01425   va_end (args);
01426 
01427   return message;
01428 }
01429 
01430 
01443 DBusMessage *
01444 dbus_message_copy (const DBusMessage *message)
01445 {
01446   DBusMessage *retval;
01447 
01448   _dbus_return_val_if_fail (message != NULL, NULL);
01449 
01450   retval = dbus_new0 (DBusMessage, 1);
01451   if (retval == NULL)
01452     return NULL;
01453 
01454   _dbus_atomic_inc (&retval->refcount);
01455   retval->byte_order = message->byte_order;
01456   retval->locked = FALSE;
01457 #ifndef DBUS_DISABLE_CHECKS
01458   retval->generation = message->generation;
01459 #endif
01460 
01461   if (!_dbus_header_copy (&message->header, &retval->header))
01462     {
01463       dbus_free (retval);
01464       return NULL;
01465     }
01466 
01467   if (!_dbus_string_init_preallocated (&retval->body,
01468                                        _dbus_string_get_length (&message->body)))
01469     {
01470       _dbus_header_free (&retval->header);
01471       dbus_free (retval);
01472       return NULL;
01473     }
01474 
01475   if (!_dbus_string_copy (&message->body, 0,
01476                           &retval->body, 0))
01477     goto failed_copy;
01478 
01479 #ifdef HAVE_UNIX_FD_PASSING
01480   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01481   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01482     goto failed_copy;
01483 
01484   retval->n_unix_fds_allocated = message->n_unix_fds;
01485 
01486   for (retval->n_unix_fds = 0;
01487        retval->n_unix_fds < message->n_unix_fds;
01488        retval->n_unix_fds++)
01489     {
01490       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01491 
01492       if (retval->unix_fds[retval->n_unix_fds] < 0)
01493         goto failed_copy;
01494     }
01495 
01496 #endif
01497 
01498   return retval;
01499 
01500  failed_copy:
01501   _dbus_header_free (&retval->header);
01502   _dbus_string_free (&retval->body);
01503 
01504 #ifdef HAVE_UNIX_FD_PASSING
01505   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01506   dbus_free(retval->unix_fds);
01507 #endif
01508 
01509   dbus_free (retval);
01510 
01511   return NULL;
01512 }
01513 
01514 
01522 DBusMessage *
01523 dbus_message_ref (DBusMessage *message)
01524 {
01525 #ifndef DBUS_DISABLE_ASSERT
01526   dbus_int32_t old_refcount;
01527 #endif
01528 
01529   _dbus_return_val_if_fail (message != NULL, NULL);
01530   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01531   _dbus_return_val_if_fail (!message->in_cache, NULL);
01532 
01533 #ifdef DBUS_DISABLE_ASSERT
01534   _dbus_atomic_inc (&message->refcount);
01535 #else
01536   old_refcount = _dbus_atomic_inc (&message->refcount);
01537   _dbus_assert (old_refcount >= 1);
01538 #endif
01539 
01540   return message;
01541 }
01542 
01550 void
01551 dbus_message_unref (DBusMessage *message)
01552 {
01553  dbus_int32_t old_refcount;
01554 
01555   _dbus_return_if_fail (message != NULL);
01556   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01557   _dbus_return_if_fail (!message->in_cache);
01558 
01559   old_refcount = _dbus_atomic_dec (&message->refcount);
01560 
01561   _dbus_assert (old_refcount >= 1);
01562 
01563   if (old_refcount == 1)
01564     {
01565       /* Calls application callbacks! */
01566       dbus_message_cache_or_finalize (message);
01567     }
01568 }
01569 
01580 int
01581 dbus_message_get_type (DBusMessage *message)
01582 {
01583   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01584 
01585   return _dbus_header_get_message_type (&message->header);
01586 }
01587 
01650 dbus_bool_t
01651 dbus_message_append_args (DBusMessage *message,
01652                           int          first_arg_type,
01653                           ...)
01654 {
01655   dbus_bool_t retval;
01656   va_list var_args;
01657 
01658   _dbus_return_val_if_fail (message != NULL, FALSE);
01659 
01660   va_start (var_args, first_arg_type);
01661   retval = dbus_message_append_args_valist (message,
01662                                             first_arg_type,
01663                                             var_args);
01664   va_end (var_args);
01665 
01666   return retval;
01667 }
01668 
01682 dbus_bool_t
01683 dbus_message_append_args_valist (DBusMessage *message,
01684                                  int          first_arg_type,
01685                                  va_list      var_args)
01686 {
01687   int type;
01688   DBusMessageIter iter;
01689 
01690   _dbus_return_val_if_fail (message != NULL, FALSE);
01691 
01692   type = first_arg_type;
01693 
01694   dbus_message_iter_init_append (message, &iter);
01695 
01696   while (type != DBUS_TYPE_INVALID)
01697     {
01698       if (dbus_type_is_basic (type))
01699         {
01700           const DBusBasicValue *value;
01701           value = va_arg (var_args, const DBusBasicValue*);
01702 
01703           if (!dbus_message_iter_append_basic (&iter,
01704                                                type,
01705                                                value))
01706             goto failed;
01707         }
01708       else if (type == DBUS_TYPE_ARRAY)
01709         {
01710           int element_type;
01711           DBusMessageIter array;
01712           char buf[2];
01713 
01714           element_type = va_arg (var_args, int);
01715               
01716           buf[0] = element_type;
01717           buf[1] = '\0';
01718           if (!dbus_message_iter_open_container (&iter,
01719                                                  DBUS_TYPE_ARRAY,
01720                                                  buf,
01721                                                  &array))
01722             goto failed;
01723 
01724           if (dbus_type_is_fixed (element_type) &&
01725               element_type != DBUS_TYPE_UNIX_FD)
01726             {
01727               const DBusBasicValue **value;
01728               int n_elements;
01729 
01730               value = va_arg (var_args, const DBusBasicValue**);
01731               n_elements = va_arg (var_args, int);
01732               
01733               if (!dbus_message_iter_append_fixed_array (&array,
01734                                                          element_type,
01735                                                          value,
01736                                                          n_elements)) {
01737                 dbus_message_iter_abandon_container (&iter, &array);
01738                 goto failed;
01739               }
01740             }
01741           else if (element_type == DBUS_TYPE_STRING ||
01742                    element_type == DBUS_TYPE_SIGNATURE ||
01743                    element_type == DBUS_TYPE_OBJECT_PATH)
01744             {
01745               const char ***value_p;
01746               const char **value;
01747               int n_elements;
01748               int i;
01749               
01750               value_p = va_arg (var_args, const char***);
01751               n_elements = va_arg (var_args, int);
01752 
01753               value = *value_p;
01754               
01755               i = 0;
01756               while (i < n_elements)
01757                 {
01758                   if (!dbus_message_iter_append_basic (&array,
01759                                                        element_type,
01760                                                        &value[i])) {
01761                     dbus_message_iter_abandon_container (&iter, &array);
01762                     goto failed;
01763                   }
01764                   ++i;
01765                 }
01766             }
01767           else
01768             {
01769               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01770                           _dbus_type_to_string (element_type),
01771                           _DBUS_FUNCTION_NAME);
01772               goto failed;
01773             }
01774 
01775           if (!dbus_message_iter_close_container (&iter, &array))
01776             goto failed;
01777         }
01778 #ifndef DBUS_DISABLE_CHECKS
01779       else
01780         {
01781           _dbus_warn ("type %s isn't supported yet in %s\n",
01782                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01783           goto failed;
01784         }
01785 #endif
01786 
01787       type = va_arg (var_args, int);
01788     }
01789 
01790   return TRUE;
01791 
01792  failed:
01793   return FALSE;
01794 }
01795 
01840 dbus_bool_t
01841 dbus_message_get_args (DBusMessage     *message,
01842                        DBusError       *error,
01843                        int              first_arg_type,
01844                        ...)
01845 {
01846   dbus_bool_t retval;
01847   va_list var_args;
01848 
01849   _dbus_return_val_if_fail (message != NULL, FALSE);
01850   _dbus_return_val_if_error_is_set (error, FALSE);
01851 
01852   va_start (var_args, first_arg_type);
01853   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01854   va_end (var_args);
01855 
01856   return retval;
01857 }
01858 
01869 dbus_bool_t
01870 dbus_message_get_args_valist (DBusMessage     *message,
01871                               DBusError       *error,
01872                               int              first_arg_type,
01873                               va_list          var_args)
01874 {
01875   DBusMessageIter iter;
01876 
01877   _dbus_return_val_if_fail (message != NULL, FALSE);
01878   _dbus_return_val_if_error_is_set (error, FALSE);
01879 
01880   dbus_message_iter_init (message, &iter);
01881   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01882 }
01883 
01884 static void
01885 _dbus_message_iter_init_common (DBusMessage         *message,
01886                                 DBusMessageRealIter *real,
01887                                 int                  iter_type)
01888 {
01889   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01890 
01891   /* Since the iterator will read or write who-knows-what from the
01892    * message, we need to get in the right byte order
01893    */
01894   ensure_byte_order (message);
01895   
01896   real->message = message;
01897   real->changed_stamp = message->changed_stamp;
01898   real->iter_type = iter_type;
01899   real->sig_refcount = 0;
01900 }
01901 
01924 dbus_bool_t
01925 dbus_message_iter_init (DBusMessage     *message,
01926                         DBusMessageIter *iter)
01927 {
01928   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01929   const DBusString *type_str;
01930   int type_pos;
01931 
01932   _dbus_return_val_if_fail (message != NULL, FALSE);
01933   _dbus_return_val_if_fail (iter != NULL, FALSE);
01934 
01935   get_const_signature (&message->header, &type_str, &type_pos);
01936 
01937   _dbus_message_iter_init_common (message, real,
01938                                   DBUS_MESSAGE_ITER_TYPE_READER);
01939 
01940   _dbus_type_reader_init (&real->u.reader,
01941                           message->byte_order,
01942                           type_str, type_pos,
01943                           &message->body,
01944                           0);
01945 
01946   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
01947 }
01948 
01955 dbus_bool_t
01956 dbus_message_iter_has_next (DBusMessageIter *iter)
01957 {
01958   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01959 
01960   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01961   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01962 
01963   return _dbus_type_reader_has_next (&real->u.reader);
01964 }
01965 
01974 dbus_bool_t
01975 dbus_message_iter_next (DBusMessageIter *iter)
01976 {
01977   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01978 
01979   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01980   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01981 
01982   return _dbus_type_reader_next (&real->u.reader);
01983 }
01984 
01999 int
02000 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02001 {
02002   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02003 
02004   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02005   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02006 
02007   return _dbus_type_reader_get_current_type (&real->u.reader);
02008 }
02009 
02018 int
02019 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02020 {
02021   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02022 
02023   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02024   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02025   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02026 
02027   return _dbus_type_reader_get_element_type (&real->u.reader);
02028 }
02029 
02055 void
02056 dbus_message_iter_recurse (DBusMessageIter  *iter,
02057                            DBusMessageIter  *sub)
02058 {
02059   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02060   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02061 
02062   _dbus_return_if_fail (_dbus_message_iter_check (real));
02063   _dbus_return_if_fail (sub != NULL);
02064 
02065   *real_sub = *real;
02066   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02067 }
02068 
02080 char *
02081 dbus_message_iter_get_signature (DBusMessageIter *iter)
02082 {
02083   const DBusString *sig;
02084   DBusString retstr;
02085   char *ret;
02086   int start, len;
02087   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02088 
02089   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02090 
02091   if (!_dbus_string_init (&retstr))
02092     return NULL;
02093 
02094   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02095                                    &start, &len);
02096   if (!_dbus_string_append_len (&retstr,
02097                                 _dbus_string_get_const_data (sig) + start,
02098                                 len))
02099     return NULL;
02100   if (!_dbus_string_steal_data (&retstr, &ret))
02101     return NULL;
02102   _dbus_string_free (&retstr);
02103   return ret;
02104 }
02105 
02153 void
02154 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02155                              void             *value)
02156 {
02157   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02158 
02159   _dbus_return_if_fail (_dbus_message_iter_check (real));
02160   _dbus_return_if_fail (value != NULL);
02161 
02162   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02163     {
02164 #ifdef HAVE_UNIX_FD_PASSING
02165       DBusBasicValue idx;
02166 
02167       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02168 
02169       if (idx.u32 >= real->message->n_unix_fds) {
02170         /* Hmm, we cannot really signal an error here, so let's make
02171            sure to return an invalid fd. */
02172         *((int*) value) = -1;
02173         return;
02174       }
02175 
02176       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02177 #else
02178       *((int*) value) = -1;
02179 #endif
02180     }
02181   else
02182     {
02183       _dbus_type_reader_read_basic (&real->u.reader,
02184                                     value);
02185     }
02186 }
02187 
02206 int
02207 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02208 {
02209   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02210 
02211   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02212 
02213   return _dbus_type_reader_get_array_length (&real->u.reader);
02214 }
02215 
02251 void
02252 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02253                                    void             *value,
02254                                    int              *n_elements)
02255 {
02256   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02257   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02258 
02259   _dbus_return_if_fail (_dbus_message_iter_check (real));
02260   _dbus_return_if_fail (value != NULL);
02261   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02262                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02263 
02264   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02265                                       value, n_elements);
02266 }
02267 
02279 void
02280 dbus_message_iter_init_append (DBusMessage     *message,
02281                                DBusMessageIter *iter)
02282 {
02283   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02284 
02285   _dbus_return_if_fail (message != NULL);
02286   _dbus_return_if_fail (iter != NULL);
02287 
02288   _dbus_message_iter_init_common (message, real,
02289                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02290 
02291   /* We create the signature string and point iterators at it "on demand"
02292    * when a value is actually appended. That means that init() never fails
02293    * due to OOM.
02294    */
02295   _dbus_type_writer_init_types_delayed (&real->u.writer,
02296                                         message->byte_order,
02297                                         &message->body,
02298                                         _dbus_string_get_length (&message->body));
02299 }
02300 
02309 static dbus_bool_t
02310 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02311 {
02312   DBusString *str;
02313   const DBusString *current_sig;
02314   int current_sig_pos;
02315 
02316   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02317 
02318   if (real->u.writer.type_str != NULL)
02319     {
02320       _dbus_assert (real->sig_refcount > 0);
02321       real->sig_refcount += 1;
02322       return TRUE;
02323     }
02324 
02325   str = dbus_new (DBusString, 1);
02326   if (str == NULL)
02327     return FALSE;
02328 
02329   if (!_dbus_header_get_field_raw (&real->message->header,
02330                                    DBUS_HEADER_FIELD_SIGNATURE,
02331                                    &current_sig, &current_sig_pos))
02332     current_sig = NULL;
02333 
02334   if (current_sig)
02335     {
02336       int current_len;
02337 
02338       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02339       current_sig_pos += 1; /* move on to sig data */
02340 
02341       if (!_dbus_string_init_preallocated (str, current_len + 4))
02342         {
02343           dbus_free (str);
02344           return FALSE;
02345         }
02346 
02347       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02348                                   str, 0))
02349         {
02350           _dbus_string_free (str);
02351           dbus_free (str);
02352           return FALSE;
02353         }
02354     }
02355   else
02356     {
02357       if (!_dbus_string_init_preallocated (str, 4))
02358         {
02359           dbus_free (str);
02360           return FALSE;
02361         }
02362     }
02363 
02364   real->sig_refcount = 1;
02365 
02366   _dbus_type_writer_add_types (&real->u.writer,
02367                                str, _dbus_string_get_length (str));
02368   return TRUE;
02369 }
02370 
02380 static dbus_bool_t
02381 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02382 {
02383   DBusString *str;
02384   const char *v_STRING;
02385   dbus_bool_t retval;
02386 
02387   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02388   _dbus_assert (real->u.writer.type_str != NULL);
02389   _dbus_assert (real->sig_refcount > 0);
02390 
02391   real->sig_refcount -= 1;
02392 
02393   if (real->sig_refcount > 0)
02394     return TRUE;
02395   _dbus_assert (real->sig_refcount == 0);
02396 
02397   retval = TRUE;
02398 
02399   str = real->u.writer.type_str;
02400 
02401   v_STRING = _dbus_string_get_const_data (str);
02402   if (!_dbus_header_set_field_basic (&real->message->header,
02403                                      DBUS_HEADER_FIELD_SIGNATURE,
02404                                      DBUS_TYPE_SIGNATURE,
02405                                      &v_STRING))
02406     retval = FALSE;
02407 
02408   _dbus_type_writer_remove_types (&real->u.writer);
02409   _dbus_string_free (str);
02410   dbus_free (str);
02411 
02412   return retval;
02413 }
02414 
02422 static void
02423 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02424 {
02425   DBusString *str;
02426 
02427   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02428   _dbus_assert (real->u.writer.type_str != NULL);
02429   _dbus_assert (real->sig_refcount > 0);
02430 
02431   real->sig_refcount -= 1;
02432 
02433   if (real->sig_refcount > 0)
02434     return;
02435   _dbus_assert (real->sig_refcount == 0);
02436 
02437   str = real->u.writer.type_str;
02438 
02439   _dbus_type_writer_remove_types (&real->u.writer);
02440   _dbus_string_free (str);
02441   dbus_free (str);
02442 }
02443 
02444 #ifndef DBUS_DISABLE_CHECKS
02445 static dbus_bool_t
02446 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02447 {
02448   if (!_dbus_message_iter_check (iter))
02449     return FALSE;
02450 
02451   if (iter->message->locked)
02452     {
02453       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02454       return FALSE;
02455     }
02456 
02457   return TRUE;
02458 }
02459 #endif /* DBUS_DISABLE_CHECKS */
02460 
02461 #ifdef HAVE_UNIX_FD_PASSING
02462 static int *
02463 expand_fd_array(DBusMessage *m,
02464                 unsigned     n)
02465 {
02466   _dbus_assert(m);
02467 
02468   /* This makes space for adding n new fds to the array and returns a
02469      pointer to the place were the first fd should be put. */
02470 
02471   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02472     {
02473       unsigned k;
02474       int *p;
02475 
02476       /* Make twice as much space as necessary */
02477       k = (m->n_unix_fds + n) * 2;
02478 
02479       /* Allocate at least four */
02480       if (k < 4)
02481         k = 4;
02482 
02483       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02484       if (p == NULL)
02485         return NULL;
02486 
02487       m->unix_fds = p;
02488       m->n_unix_fds_allocated = k;
02489     }
02490 
02491   return m->unix_fds + m->n_unix_fds;
02492 }
02493 #endif
02494 
02514 dbus_bool_t
02515 dbus_message_iter_append_basic (DBusMessageIter *iter,
02516                                 int              type,
02517                                 const void      *value)
02518 {
02519   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02520   dbus_bool_t ret;
02521 
02522   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02523   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02524   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02525   _dbus_return_val_if_fail (value != NULL, FALSE);
02526 
02527 #ifndef DBUS_DISABLE_CHECKS
02528   switch (type)
02529     {
02530       const char * const *string_p;
02531       const dbus_bool_t *bool_p;
02532 
02533       case DBUS_TYPE_STRING:
02534         string_p = value;
02535         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02536         break;
02537 
02538       case DBUS_TYPE_OBJECT_PATH:
02539         string_p = value;
02540         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02541         break;
02542 
02543       case DBUS_TYPE_SIGNATURE:
02544         string_p = value;
02545         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02546         break;
02547 
02548       case DBUS_TYPE_BOOLEAN:
02549         bool_p = value;
02550         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02551         break;
02552 
02553       default:
02554           {
02555             /* nothing to check, all possible values are allowed */
02556           }
02557     }
02558 #endif
02559 
02560   if (!_dbus_message_iter_open_signature (real))
02561     return FALSE;
02562 
02563   if (type == DBUS_TYPE_UNIX_FD)
02564     {
02565 #ifdef HAVE_UNIX_FD_PASSING
02566       int *fds;
02567       dbus_uint32_t u;
02568 
02569       /* First step, include the fd in the fd list of this message */
02570       if (!(fds = expand_fd_array(real->message, 1)))
02571         return FALSE;
02572 
02573       *fds = _dbus_dup(*(int*) value, NULL);
02574       if (*fds < 0)
02575         return FALSE;
02576 
02577       u = real->message->n_unix_fds;
02578 
02579       /* Second step, write the index to the fd */
02580       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02581         _dbus_close(*fds, NULL);
02582         return FALSE;
02583       }
02584 
02585       real->message->n_unix_fds += 1;
02586       u += 1;
02587 
02588       /* Final step, update the header accordingly */
02589       ret = _dbus_header_set_field_basic (&real->message->header,
02590                                           DBUS_HEADER_FIELD_UNIX_FDS,
02591                                           DBUS_TYPE_UINT32,
02592                                           &u);
02593 
02594       /* If any of these operations fail the message is
02595          hosed. However, no memory or fds should be leaked since what
02596          has been added to message has been added to the message, and
02597          can hence be accounted for when the message is being
02598          freed. */
02599 #else
02600       ret = FALSE;
02601 #endif
02602     }
02603   else
02604     {
02605       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02606     }
02607 
02608   if (!_dbus_message_iter_close_signature (real))
02609     ret = FALSE;
02610 
02611   return ret;
02612 }
02613 
02649 dbus_bool_t
02650 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02651                                       int              element_type,
02652                                       const void      *value,
02653                                       int              n_elements)
02654 {
02655   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02656   dbus_bool_t ret;
02657 
02658   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02659   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02660   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02661   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02662   _dbus_return_val_if_fail (value != NULL, FALSE);
02663   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02664   _dbus_return_val_if_fail (n_elements <=
02665                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02666                             FALSE);
02667 
02668 #ifndef DBUS_DISABLE_CHECKS
02669   if (element_type == DBUS_TYPE_BOOLEAN)
02670     {
02671       const dbus_bool_t * const *bools = value;
02672       int i;
02673 
02674       for (i = 0; i < n_elements; i++)
02675         {
02676           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02677         }
02678     }
02679 #endif
02680 
02681   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02682 
02683   return ret;
02684 }
02685 
02707 dbus_bool_t
02708 dbus_message_iter_open_container (DBusMessageIter *iter,
02709                                   int              type,
02710                                   const char      *contained_signature,
02711                                   DBusMessageIter *sub)
02712 {
02713   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02714   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02715   DBusString contained_str;
02716 
02717   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02718   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02719   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02720   _dbus_return_val_if_fail (sub != NULL, FALSE);
02721   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02722                              contained_signature == NULL) ||
02723                             (type == DBUS_TYPE_DICT_ENTRY &&
02724                              contained_signature == NULL) ||
02725                             (type == DBUS_TYPE_VARIANT &&
02726                              contained_signature != NULL) ||
02727                             (type == DBUS_TYPE_ARRAY &&
02728                              contained_signature != NULL), FALSE);
02729   
02730   /* this would fail if the contained_signature is a dict entry, since
02731    * dict entries are invalid signatures standalone (they must be in
02732    * an array)
02733    */
02734   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02735                             (contained_signature == NULL ||
02736                              _dbus_check_is_valid_signature (contained_signature)),
02737                             FALSE);
02738 
02739   if (!_dbus_message_iter_open_signature (real))
02740     return FALSE;
02741 
02742   *real_sub = *real;
02743 
02744   if (contained_signature != NULL)
02745     {
02746       _dbus_string_init_const (&contained_str, contained_signature);
02747 
02748       return _dbus_type_writer_recurse (&real->u.writer,
02749                                         type,
02750                                         &contained_str, 0,
02751                                         &real_sub->u.writer);
02752     }
02753   else
02754     {
02755       return _dbus_type_writer_recurse (&real->u.writer,
02756                                         type,
02757                                         NULL, 0,
02758                                         &real_sub->u.writer);
02759     } 
02760 }
02761 
02762 
02776 dbus_bool_t
02777 dbus_message_iter_close_container (DBusMessageIter *iter,
02778                                    DBusMessageIter *sub)
02779 {
02780   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02781   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02782   dbus_bool_t ret;
02783 
02784   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02785   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02786   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02787   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02788 
02789   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02790                                      &real_sub->u.writer);
02791 
02792   if (!_dbus_message_iter_close_signature (real))
02793     ret = FALSE;
02794 
02795   return ret;
02796 }
02797 
02809 void
02810 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02811                                      DBusMessageIter *sub)
02812 {
02813   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02814   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02815 
02816   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02817   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02818   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02819   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02820 
02821   _dbus_message_iter_abandon_signature (real);
02822 }
02823 
02840 void
02841 dbus_message_set_no_reply (DBusMessage *message,
02842                            dbus_bool_t  no_reply)
02843 {
02844   _dbus_return_if_fail (message != NULL);
02845   _dbus_return_if_fail (!message->locked);
02846 
02847   _dbus_header_toggle_flag (&message->header,
02848                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02849                             no_reply);
02850 }
02851 
02859 dbus_bool_t
02860 dbus_message_get_no_reply (DBusMessage *message)
02861 {
02862   _dbus_return_val_if_fail (message != NULL, FALSE);
02863 
02864   return _dbus_header_get_flag (&message->header,
02865                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02866 }
02867 
02882 void
02883 dbus_message_set_auto_start (DBusMessage *message,
02884                              dbus_bool_t  auto_start)
02885 {
02886   _dbus_return_if_fail (message != NULL);
02887   _dbus_return_if_fail (!message->locked);
02888 
02889   _dbus_header_toggle_flag (&message->header,
02890                             DBUS_HEADER_FLAG_NO_AUTO_START,
02891                             !auto_start);
02892 }
02893 
02901 dbus_bool_t
02902 dbus_message_get_auto_start (DBusMessage *message)
02903 {
02904   _dbus_return_val_if_fail (message != NULL, FALSE);
02905 
02906   return !_dbus_header_get_flag (&message->header,
02907                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02908 }
02909 
02910 
02923 dbus_bool_t
02924 dbus_message_set_path (DBusMessage   *message,
02925                        const char    *object_path)
02926 {
02927   _dbus_return_val_if_fail (message != NULL, FALSE);
02928   _dbus_return_val_if_fail (!message->locked, FALSE);
02929   _dbus_return_val_if_fail (object_path == NULL ||
02930                             _dbus_check_is_valid_path (object_path),
02931                             FALSE);
02932 
02933   return set_or_delete_string_field (message,
02934                                      DBUS_HEADER_FIELD_PATH,
02935                                      DBUS_TYPE_OBJECT_PATH,
02936                                      object_path);
02937 }
02938 
02952 const char*
02953 dbus_message_get_path (DBusMessage   *message)
02954 {
02955   const char *v;
02956 
02957   _dbus_return_val_if_fail (message != NULL, NULL);
02958 
02959   v = NULL; /* in case field doesn't exist */
02960   _dbus_header_get_field_basic (&message->header,
02961                                 DBUS_HEADER_FIELD_PATH,
02962                                 DBUS_TYPE_OBJECT_PATH,
02963                                 (void *) &v);
02964   return v;
02965 }
02966 
02976 dbus_bool_t
02977 dbus_message_has_path (DBusMessage   *message,
02978                        const char    *path)
02979 {
02980   const char *msg_path;
02981   msg_path = dbus_message_get_path (message);
02982   
02983   if (msg_path == NULL)
02984     {
02985       if (path == NULL)
02986         return TRUE;
02987       else
02988         return FALSE;
02989     }
02990 
02991   if (path == NULL)
02992     return FALSE;
02993    
02994   if (strcmp (msg_path, path) == 0)
02995     return TRUE;
02996 
02997   return FALSE;
02998 }
02999 
03020 dbus_bool_t
03021 dbus_message_get_path_decomposed (DBusMessage   *message,
03022                                   char        ***path)
03023 {
03024   const char *v;
03025 
03026   _dbus_return_val_if_fail (message != NULL, FALSE);
03027   _dbus_return_val_if_fail (path != NULL, FALSE);
03028 
03029   *path = NULL;
03030 
03031   v = dbus_message_get_path (message);
03032   if (v != NULL)
03033     {
03034       if (!_dbus_decompose_path (v, strlen (v),
03035                                  path, NULL))
03036         return FALSE;
03037     }
03038   return TRUE;
03039 }
03040 
03054 dbus_bool_t
03055 dbus_message_set_interface (DBusMessage  *message,
03056                             const char   *interface)
03057 {
03058   _dbus_return_val_if_fail (message != NULL, FALSE);
03059   _dbus_return_val_if_fail (!message->locked, FALSE);
03060   _dbus_return_val_if_fail (interface == NULL ||
03061                             _dbus_check_is_valid_interface (interface),
03062                             FALSE);
03063 
03064   return set_or_delete_string_field (message,
03065                                      DBUS_HEADER_FIELD_INTERFACE,
03066                                      DBUS_TYPE_STRING,
03067                                      interface);
03068 }
03069 
03083 const char*
03084 dbus_message_get_interface (DBusMessage *message)
03085 {
03086   const char *v;
03087 
03088   _dbus_return_val_if_fail (message != NULL, NULL);
03089 
03090   v = NULL; /* in case field doesn't exist */
03091   _dbus_header_get_field_basic (&message->header,
03092                                 DBUS_HEADER_FIELD_INTERFACE,
03093                                 DBUS_TYPE_STRING,
03094                                 (void *) &v);
03095   return v;
03096 }
03097 
03105 dbus_bool_t
03106 dbus_message_has_interface (DBusMessage   *message,
03107                             const char    *interface)
03108 {
03109   const char *msg_interface;
03110   msg_interface = dbus_message_get_interface (message);
03111    
03112   if (msg_interface == NULL)
03113     {
03114       if (interface == NULL)
03115         return TRUE;
03116       else
03117         return FALSE;
03118     }
03119 
03120   if (interface == NULL)
03121     return FALSE;
03122      
03123   if (strcmp (msg_interface, interface) == 0)
03124     return TRUE;
03125 
03126   return FALSE;
03127 
03128 }
03129 
03142 dbus_bool_t
03143 dbus_message_set_member (DBusMessage  *message,
03144                          const char   *member)
03145 {
03146   _dbus_return_val_if_fail (message != NULL, FALSE);
03147   _dbus_return_val_if_fail (!message->locked, FALSE);
03148   _dbus_return_val_if_fail (member == NULL ||
03149                             _dbus_check_is_valid_member (member),
03150                             FALSE);
03151 
03152   return set_or_delete_string_field (message,
03153                                      DBUS_HEADER_FIELD_MEMBER,
03154                                      DBUS_TYPE_STRING,
03155                                      member);
03156 }
03157 
03169 const char*
03170 dbus_message_get_member (DBusMessage *message)
03171 {
03172   const char *v;
03173 
03174   _dbus_return_val_if_fail (message != NULL, NULL);
03175 
03176   v = NULL; /* in case field doesn't exist */
03177   _dbus_header_get_field_basic (&message->header,
03178                                 DBUS_HEADER_FIELD_MEMBER,
03179                                 DBUS_TYPE_STRING,
03180                                 (void *) &v);
03181   return v;
03182 }
03183 
03191 dbus_bool_t
03192 dbus_message_has_member (DBusMessage   *message,
03193                          const char    *member)
03194 {
03195   const char *msg_member;
03196   msg_member = dbus_message_get_member (message);
03197  
03198   if (msg_member == NULL)
03199     {
03200       if (member == NULL)
03201         return TRUE;
03202       else
03203         return FALSE;
03204     }
03205 
03206   if (member == NULL)
03207     return FALSE;
03208     
03209   if (strcmp (msg_member, member) == 0)
03210     return TRUE;
03211 
03212   return FALSE;
03213 
03214 }
03215 
03227 dbus_bool_t
03228 dbus_message_set_error_name (DBusMessage  *message,
03229                              const char   *error_name)
03230 {
03231   _dbus_return_val_if_fail (message != NULL, FALSE);
03232   _dbus_return_val_if_fail (!message->locked, FALSE);
03233   _dbus_return_val_if_fail (error_name == NULL ||
03234                             _dbus_check_is_valid_error_name (error_name),
03235                             FALSE);
03236 
03237   return set_or_delete_string_field (message,
03238                                      DBUS_HEADER_FIELD_ERROR_NAME,
03239                                      DBUS_TYPE_STRING,
03240                                      error_name);
03241 }
03242 
03253 const char*
03254 dbus_message_get_error_name (DBusMessage *message)
03255 {
03256   const char *v;
03257 
03258   _dbus_return_val_if_fail (message != NULL, NULL);
03259 
03260   v = NULL; /* in case field doesn't exist */
03261   _dbus_header_get_field_basic (&message->header,
03262                                 DBUS_HEADER_FIELD_ERROR_NAME,
03263                                 DBUS_TYPE_STRING,
03264                                 (void *) &v);
03265   return v;
03266 }
03267 
03281 dbus_bool_t
03282 dbus_message_set_destination (DBusMessage  *message,
03283                               const char   *destination)
03284 {
03285   _dbus_return_val_if_fail (message != NULL, FALSE);
03286   _dbus_return_val_if_fail (!message->locked, FALSE);
03287   _dbus_return_val_if_fail (destination == NULL ||
03288                             _dbus_check_is_valid_bus_name (destination),
03289                             FALSE);
03290 
03291   return set_or_delete_string_field (message,
03292                                      DBUS_HEADER_FIELD_DESTINATION,
03293                                      DBUS_TYPE_STRING,
03294                                      destination);
03295 }
03296 
03306 const char*
03307 dbus_message_get_destination (DBusMessage *message)
03308 {
03309   const char *v;
03310 
03311   _dbus_return_val_if_fail (message != NULL, NULL);
03312 
03313   v = NULL; /* in case field doesn't exist */
03314   _dbus_header_get_field_basic (&message->header,
03315                                 DBUS_HEADER_FIELD_DESTINATION,
03316                                 DBUS_TYPE_STRING,
03317                                 (void *) &v);
03318   return v;
03319 }
03320 
03335 dbus_bool_t
03336 dbus_message_set_sender (DBusMessage  *message,
03337                          const char   *sender)
03338 {
03339   _dbus_return_val_if_fail (message != NULL, FALSE);
03340   _dbus_return_val_if_fail (!message->locked, FALSE);
03341   _dbus_return_val_if_fail (sender == NULL ||
03342                             _dbus_check_is_valid_bus_name (sender),
03343                             FALSE);
03344 
03345   return set_or_delete_string_field (message,
03346                                      DBUS_HEADER_FIELD_SENDER,
03347                                      DBUS_TYPE_STRING,
03348                                      sender);
03349 }
03350 
03366 const char*
03367 dbus_message_get_sender (DBusMessage *message)
03368 {
03369   const char *v;
03370 
03371   _dbus_return_val_if_fail (message != NULL, NULL);
03372 
03373   v = NULL; /* in case field doesn't exist */
03374   _dbus_header_get_field_basic (&message->header,
03375                                 DBUS_HEADER_FIELD_SENDER,
03376                                 DBUS_TYPE_STRING,
03377                                 (void *) &v);
03378   return v;
03379 }
03380 
03399 const char*
03400 dbus_message_get_signature (DBusMessage *message)
03401 {
03402   const DBusString *type_str;
03403   int type_pos;
03404 
03405   _dbus_return_val_if_fail (message != NULL, NULL);
03406 
03407   get_const_signature (&message->header, &type_str, &type_pos);
03408 
03409   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03410 }
03411 
03412 static dbus_bool_t
03413 _dbus_message_has_type_interface_member (DBusMessage *message,
03414                                          int          type,
03415                                          const char  *interface,
03416                                          const char  *member)
03417 {
03418   const char *n;
03419 
03420   _dbus_assert (message != NULL);
03421   _dbus_assert (interface != NULL);
03422   _dbus_assert (member != NULL);
03423 
03424   if (dbus_message_get_type (message) != type)
03425     return FALSE;
03426 
03427   /* Optimize by checking the short member name first
03428    * instead of the longer interface name
03429    */
03430 
03431   n = dbus_message_get_member (message);
03432 
03433   if (n && strcmp (n, member) == 0)
03434     {
03435       n = dbus_message_get_interface (message);
03436 
03437       if (n == NULL || strcmp (n, interface) == 0)
03438         return TRUE;
03439     }
03440 
03441   return FALSE;
03442 }
03443 
03458 dbus_bool_t
03459 dbus_message_is_method_call (DBusMessage *message,
03460                              const char  *interface,
03461                              const char  *method)
03462 {
03463   _dbus_return_val_if_fail (message != NULL, FALSE);
03464   _dbus_return_val_if_fail (interface != NULL, FALSE);
03465   _dbus_return_val_if_fail (method != NULL, FALSE);
03466   /* don't check that interface/method are valid since it would be
03467    * expensive, and not catch many common errors
03468    */
03469 
03470   return _dbus_message_has_type_interface_member (message,
03471                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03472                                                   interface, method);
03473 }
03474 
03486 dbus_bool_t
03487 dbus_message_is_signal (DBusMessage *message,
03488                         const char  *interface,
03489                         const char  *signal_name)
03490 {
03491   _dbus_return_val_if_fail (message != NULL, FALSE);
03492   _dbus_return_val_if_fail (interface != NULL, FALSE);
03493   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03494   /* don't check that interface/name are valid since it would be
03495    * expensive, and not catch many common errors
03496    */
03497 
03498   return _dbus_message_has_type_interface_member (message,
03499                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03500                                                   interface, signal_name);
03501 }
03502 
03513 dbus_bool_t
03514 dbus_message_is_error (DBusMessage *message,
03515                        const char  *error_name)
03516 {
03517   const char *n;
03518 
03519   _dbus_return_val_if_fail (message != NULL, FALSE);
03520   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03521   /* don't check that error_name is valid since it would be expensive,
03522    * and not catch many common errors
03523    */
03524 
03525   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03526     return FALSE;
03527 
03528   n = dbus_message_get_error_name (message);
03529 
03530   if (n && strcmp (n, error_name) == 0)
03531     return TRUE;
03532   else
03533     return FALSE;
03534 }
03535 
03546 dbus_bool_t
03547 dbus_message_has_destination (DBusMessage  *message,
03548                               const char   *name)
03549 {
03550   const char *s;
03551 
03552   _dbus_return_val_if_fail (message != NULL, FALSE);
03553   _dbus_return_val_if_fail (name != NULL, FALSE);
03554   /* don't check that name is valid since it would be expensive, and
03555    * not catch many common errors
03556    */
03557 
03558   s = dbus_message_get_destination (message);
03559 
03560   if (s && strcmp (s, name) == 0)
03561     return TRUE;
03562   else
03563     return FALSE;
03564 }
03565 
03581 dbus_bool_t
03582 dbus_message_has_sender (DBusMessage  *message,
03583                          const char   *name)
03584 {
03585   const char *s;
03586 
03587   _dbus_return_val_if_fail (message != NULL, FALSE);
03588   _dbus_return_val_if_fail (name != NULL, FALSE);
03589   /* don't check that name is valid since it would be expensive, and
03590    * not catch many common errors
03591    */
03592 
03593   s = dbus_message_get_sender (message);
03594 
03595   if (s && strcmp (s, name) == 0)
03596     return TRUE;
03597   else
03598     return FALSE;
03599 }
03600 
03610 dbus_bool_t
03611 dbus_message_has_signature (DBusMessage   *message,
03612                             const char    *signature)
03613 {
03614   const char *s;
03615 
03616   _dbus_return_val_if_fail (message != NULL, FALSE);
03617   _dbus_return_val_if_fail (signature != NULL, FALSE);
03618   /* don't check that signature is valid since it would be expensive,
03619    * and not catch many common errors
03620    */
03621 
03622   s = dbus_message_get_signature (message);
03623 
03624   if (s && strcmp (s, signature) == 0)
03625     return TRUE;
03626   else
03627     return FALSE;
03628 }
03629 
03652 dbus_bool_t
03653 dbus_set_error_from_message (DBusError   *error,
03654                              DBusMessage *message)
03655 {
03656   const char *str;
03657 
03658   _dbus_return_val_if_fail (message != NULL, FALSE);
03659   _dbus_return_val_if_error_is_set (error, FALSE);
03660 
03661   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03662     return FALSE;
03663 
03664   str = NULL;
03665   dbus_message_get_args (message, NULL,
03666                          DBUS_TYPE_STRING, &str,
03667                          DBUS_TYPE_INVALID);
03668 
03669   dbus_set_error (error, dbus_message_get_error_name (message),
03670                   str ? "%s" : NULL, str);
03671 
03672   return TRUE;
03673 }
03674 
03681 dbus_bool_t
03682 dbus_message_contains_unix_fds(DBusMessage *message)
03683 {
03684 #ifdef HAVE_UNIX_FD_PASSING
03685   _dbus_assert(message);
03686 
03687   return message->n_unix_fds > 0;
03688 #else
03689   return FALSE;
03690 #endif
03691 }
03692 
03711 #define INITIAL_LOADER_DATA_LEN 32
03712 
03719 DBusMessageLoader*
03720 _dbus_message_loader_new (void)
03721 {
03722   DBusMessageLoader *loader;
03723 
03724   loader = dbus_new0 (DBusMessageLoader, 1);
03725   if (loader == NULL)
03726     return NULL;
03727   
03728   loader->refcount = 1;
03729 
03730   loader->corrupted = FALSE;
03731   loader->corruption_reason = DBUS_VALID;
03732 
03733   /* this can be configured by the app, but defaults to the protocol max */
03734   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03735 
03736   /* We set a very relatively conservative default here since due to how
03737   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03738   number of unix fds we want to receive in advance. A
03739   try-and-reallocate loop is not possible. */
03740   loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
03741 
03742   if (!_dbus_string_init (&loader->data))
03743     {
03744       dbus_free (loader);
03745       return NULL;
03746     }
03747 
03748   /* preallocate the buffer for speed, ignore failure */
03749   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03750   _dbus_string_set_length (&loader->data, 0);
03751 
03752 #ifdef HAVE_UNIX_FD_PASSING
03753   loader->unix_fds = NULL;
03754   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03755   loader->unix_fds_outstanding = FALSE;
03756 #endif
03757 
03758   return loader;
03759 }
03760 
03767 DBusMessageLoader *
03768 _dbus_message_loader_ref (DBusMessageLoader *loader)
03769 {
03770   loader->refcount += 1;
03771 
03772   return loader;
03773 }
03774 
03781 void
03782 _dbus_message_loader_unref (DBusMessageLoader *loader)
03783 {
03784   loader->refcount -= 1;
03785   if (loader->refcount == 0)
03786     {
03787 #ifdef HAVE_UNIX_FD_PASSING
03788       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
03789       dbus_free(loader->unix_fds);
03790 #endif
03791       _dbus_list_foreach (&loader->messages,
03792                           (DBusForeachFunction) dbus_message_unref,
03793                           NULL);
03794       _dbus_list_clear (&loader->messages);
03795       _dbus_string_free (&loader->data);
03796       dbus_free (loader);
03797     }
03798 }
03799 
03818 void
03819 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03820                                  DBusString        **buffer)
03821 {
03822   _dbus_assert (!loader->buffer_outstanding);
03823 
03824   *buffer = &loader->data;
03825 
03826   loader->buffer_outstanding = TRUE;
03827 }
03828 
03839 void
03840 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03841                                     DBusString         *buffer,
03842                                     int                 bytes_read)
03843 {
03844   _dbus_assert (loader->buffer_outstanding);
03845   _dbus_assert (buffer == &loader->data);
03846 
03847   loader->buffer_outstanding = FALSE;
03848 }
03849 
03860 dbus_bool_t
03861 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
03862                                   int               **fds,
03863                                   unsigned           *max_n_fds)
03864 {
03865 #ifdef HAVE_UNIX_FD_PASSING
03866   _dbus_assert (!loader->unix_fds_outstanding);
03867 
03868   /* Allocate space where we can put the fds we read. We allocate
03869      space for max_message_unix_fds since this is an
03870      upper limit how many fds can be received within a single
03871      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
03872      we are allocating the maximum possible array size right from the
03873      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
03874      there is no better way. */
03875 
03876   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
03877     {
03878       int *a = dbus_realloc(loader->unix_fds,
03879                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
03880 
03881       if (!a)
03882         return FALSE;
03883 
03884       loader->unix_fds = a;
03885       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
03886     }
03887 
03888   *fds = loader->unix_fds + loader->n_unix_fds;
03889   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
03890 
03891   loader->unix_fds_outstanding = TRUE;
03892   return TRUE;
03893 #else
03894   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03895   return FALSE;
03896 #endif
03897 }
03898 
03909 void
03910 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
03911                                      int                *fds,
03912                                      unsigned            n_fds)
03913 {
03914 #ifdef HAVE_UNIX_FD_PASSING
03915   _dbus_assert(loader->unix_fds_outstanding);
03916   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
03917   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
03918 
03919   loader->n_unix_fds += n_fds;
03920   loader->unix_fds_outstanding = FALSE;
03921 
03922   if (n_fds && loader->unix_fds_change)
03923     loader->unix_fds_change (loader->unix_fds_change_data);
03924 #else
03925   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03926 #endif
03927 }
03928 
03929 /*
03930  * FIXME when we move the header out of the buffer, that memmoves all
03931  * buffered messages. Kind of crappy.
03932  *
03933  * Also we copy the header and body, which is kind of crappy.  To
03934  * avoid this, we have to allow header and body to be in a single
03935  * memory block, which is good for messages we read and bad for
03936  * messages we are creating. But we could move_len() the buffer into
03937  * this single memory block, and move_len() will just swap the buffers
03938  * if you're moving the entire buffer replacing the dest string.
03939  *
03940  * We could also have the message loader tell the transport how many
03941  * bytes to read; so it would first ask for some arbitrary number like
03942  * 256, then if the message was incomplete it would use the
03943  * header/body len to ask for exactly the size of the message (or
03944  * blocks the size of a typical kernel buffer for the socket). That
03945  * way we don't get trailing bytes in the buffer that have to be
03946  * memmoved. Though I suppose we also don't have a chance of reading a
03947  * bunch of small messages at once, so the optimization may be stupid.
03948  *
03949  * Another approach would be to keep a "start" index into
03950  * loader->data and only delete it occasionally, instead of after
03951  * each message is loaded.
03952  *
03953  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03954  */
03955 static dbus_bool_t
03956 load_message (DBusMessageLoader *loader,
03957               DBusMessage       *message,
03958               int                byte_order,
03959               int                fields_array_len,
03960               int                header_len,
03961               int                body_len)
03962 {
03963   dbus_bool_t oom;
03964   DBusValidity validity;
03965   const DBusString *type_str;
03966   int type_pos;
03967   DBusValidationMode mode;
03968   dbus_uint32_t n_unix_fds = 0;
03969 
03970   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03971   
03972   oom = FALSE;
03973 
03974 #if 0
03975   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03976 #endif
03977 
03978   /* 1. VALIDATE AND COPY OVER HEADER */
03979   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03980   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03981 
03982   if (!_dbus_header_load (&message->header,
03983                           mode,
03984                           &validity,
03985                           byte_order,
03986                           fields_array_len,
03987                           header_len,
03988                           body_len,
03989                           &loader->data, 0,
03990                           _dbus_string_get_length (&loader->data)))
03991     {
03992       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03993 
03994       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03995          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03996       _dbus_assert (validity != DBUS_VALID);
03997 
03998       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03999         oom = TRUE;
04000       else
04001         {
04002           loader->corrupted = TRUE;
04003           loader->corruption_reason = validity;
04004         }
04005       goto failed;
04006     }
04007 
04008   _dbus_assert (validity == DBUS_VALID);
04009 
04010   message->byte_order = byte_order;
04011 
04012   /* 2. VALIDATE BODY */
04013   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04014     {
04015       get_const_signature (&message->header, &type_str, &type_pos);
04016       
04017       /* Because the bytes_remaining arg is NULL, this validates that the
04018        * body is the right length
04019        */
04020       validity = _dbus_validate_body_with_reason (type_str,
04021                                                   type_pos,
04022                                                   byte_order,
04023                                                   NULL,
04024                                                   &loader->data,
04025                                                   header_len,
04026                                                   body_len);
04027       if (validity != DBUS_VALID)
04028         {
04029           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04030 
04031           loader->corrupted = TRUE;
04032           loader->corruption_reason = validity;
04033           
04034           goto failed;
04035         }
04036     }
04037 
04038   /* 3. COPY OVER UNIX FDS */
04039   _dbus_header_get_field_basic(&message->header,
04040                                DBUS_HEADER_FIELD_UNIX_FDS,
04041                                DBUS_TYPE_UINT32,
04042                                &n_unix_fds);
04043 
04044 #ifdef HAVE_UNIX_FD_PASSING
04045 
04046   if (n_unix_fds > loader->n_unix_fds)
04047     {
04048       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04049                     n_unix_fds, loader->n_unix_fds);
04050 
04051       loader->corrupted = TRUE;
04052       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04053       goto failed;
04054     }
04055 
04056   /* If this was a recycled message there might still be
04057      some memory allocated for the fds */
04058   dbus_free(message->unix_fds);
04059 
04060   if (n_unix_fds > 0)
04061     {
04062       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04063       if (message->unix_fds == NULL)
04064         {
04065           _dbus_verbose ("Failed to allocate file descriptor array\n");
04066           oom = TRUE;
04067           goto failed;
04068         }
04069 
04070       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04071       loader->n_unix_fds -= n_unix_fds;
04072       memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
04073 
04074       if (loader->unix_fds_change)
04075         loader->unix_fds_change (loader->unix_fds_change_data);
04076     }
04077   else
04078     message->unix_fds = NULL;
04079 
04080 #else
04081 
04082   if (n_unix_fds > 0)
04083     {
04084       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04085                      "but that's not supported on our platform, disconnecting.\n");
04086 
04087       loader->corrupted = TRUE;
04088       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04089       goto failed;
04090     }
04091 
04092 #endif
04093 
04094   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04095 
04096   if (!_dbus_list_append (&loader->messages, message))
04097     {
04098       _dbus_verbose ("Failed to append new message to loader queue\n");
04099       oom = TRUE;
04100       goto failed;
04101     }
04102 
04103   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04104   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04105                 (header_len + body_len));
04106 
04107   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04108     {
04109       _dbus_verbose ("Failed to move body into new message\n");
04110       oom = TRUE;
04111       goto failed;
04112     }
04113 
04114   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04115 
04116   /* don't waste more than 2k of memory */
04117   _dbus_string_compact (&loader->data, 2048);
04118 
04119   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04120   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04121 
04122   _dbus_verbose ("Loaded message %p\n", message);
04123 
04124   _dbus_assert (!oom);
04125   _dbus_assert (!loader->corrupted);
04126   _dbus_assert (loader->messages != NULL);
04127   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04128 
04129   return TRUE;
04130 
04131  failed:
04132 
04133   /* Clean up */
04134 
04135   /* does nothing if the message isn't in the list */
04136   _dbus_list_remove_last (&loader->messages, message);
04137   
04138   if (oom)
04139     _dbus_assert (!loader->corrupted);
04140   else
04141     _dbus_assert (loader->corrupted);
04142 
04143   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04144 
04145   return FALSE;
04146 }
04147 
04162 dbus_bool_t
04163 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04164 {
04165   while (!loader->corrupted &&
04166          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04167     {
04168       DBusValidity validity;
04169       int byte_order, fields_array_len, header_len, body_len;
04170 
04171       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04172                                                &validity,
04173                                                &byte_order,
04174                                                &fields_array_len,
04175                                                &header_len,
04176                                                &body_len,
04177                                                &loader->data, 0,
04178                                                _dbus_string_get_length (&loader->data)))
04179         {
04180           DBusMessage *message;
04181 
04182           _dbus_assert (validity == DBUS_VALID);
04183 
04184           message = dbus_message_new_empty_header ();
04185           if (message == NULL)
04186             return FALSE;
04187 
04188           if (!load_message (loader, message,
04189                              byte_order, fields_array_len,
04190                              header_len, body_len))
04191             {
04192               dbus_message_unref (message);
04193               /* load_message() returns false if corrupted or OOM; if
04194                * corrupted then return TRUE for not OOM
04195                */
04196               return loader->corrupted;
04197             }
04198 
04199           _dbus_assert (loader->messages != NULL);
04200           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04201         }
04202       else
04203         {
04204           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04205                          validity);
04206           if (validity != DBUS_VALID)
04207             {
04208               loader->corrupted = TRUE;
04209               loader->corruption_reason = validity;
04210             }
04211           return TRUE;
04212         }
04213     }
04214 
04215   return TRUE;
04216 }
04217 
04225 DBusMessage*
04226 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04227 {
04228   if (loader->messages)
04229     return loader->messages->data;
04230   else
04231     return NULL;
04232 }
04233 
04242 DBusMessage*
04243 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04244 {
04245   return _dbus_list_pop_first (&loader->messages);
04246 }
04247 
04256 DBusList*
04257 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04258 {
04259   return _dbus_list_pop_first_link (&loader->messages);
04260 }
04261 
04268 void
04269 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04270                                            DBusList           *link)
04271 {
04272   _dbus_list_prepend_link (&loader->messages, link);
04273 }
04274 
04284 dbus_bool_t
04285 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04286 {
04287   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04288                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04289   return loader->corrupted;
04290 }
04291 
04298 DBusValidity
04299 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04300 {
04301   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04302                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04303 
04304   return loader->corruption_reason;
04305 }
04306 
04313 void
04314 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04315                                            long                size)
04316 {
04317   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04318     {
04319       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04320                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04321       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04322     }
04323   loader->max_message_size = size;
04324 }
04325 
04332 long
04333 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04334 {
04335   return loader->max_message_size;
04336 }
04337 
04344 void
04345 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04346                                                long                n)
04347 {
04348   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04349     {
04350       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04351                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04352       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04353     }
04354   loader->max_message_unix_fds = n;
04355 }
04356 
04363 long
04364 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04365 {
04366   return loader->max_message_unix_fds;
04367 }
04368 
04369 static DBusDataSlotAllocator slot_allocator;
04370 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
04371 
04377 int
04378 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
04379 {
04380 #ifdef HAVE_UNIX_FD_PASSING
04381   return loader->n_unix_fds;
04382 #else
04383   return 0;
04384 #endif
04385 }
04386 
04395 void
04396 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
04397                                                void (* callback) (void *),
04398                                                void *data)
04399 {
04400 #ifdef HAVE_UNIX_FD_PASSING
04401   loader->unix_fds_change = callback;
04402   loader->unix_fds_change_data = data;
04403 #endif
04404 }
04405 
04420 dbus_bool_t
04421 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04422 {
04423   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04424                                           &_DBUS_LOCK_NAME (message_slots),
04425                                           slot_p);
04426 }
04427 
04439 void
04440 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04441 {
04442   _dbus_return_if_fail (*slot_p >= 0);
04443 
04444   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04445 }
04446 
04460 dbus_bool_t
04461 dbus_message_set_data (DBusMessage     *message,
04462                        dbus_int32_t     slot,
04463                        void            *data,
04464                        DBusFreeFunction free_data_func)
04465 {
04466   DBusFreeFunction old_free_func;
04467   void *old_data;
04468   dbus_bool_t retval;
04469 
04470   _dbus_return_val_if_fail (message != NULL, FALSE);
04471   _dbus_return_val_if_fail (slot >= 0, FALSE);
04472 
04473   retval = _dbus_data_slot_list_set (&slot_allocator,
04474                                      &message->slot_list,
04475                                      slot, data, free_data_func,
04476                                      &old_free_func, &old_data);
04477 
04478   if (retval)
04479     {
04480       /* Do the actual free outside the message lock */
04481       if (old_free_func)
04482         (* old_free_func) (old_data);
04483     }
04484 
04485   return retval;
04486 }
04487 
04496 void*
04497 dbus_message_get_data (DBusMessage   *message,
04498                        dbus_int32_t   slot)
04499 {
04500   void *res;
04501 
04502   _dbus_return_val_if_fail (message != NULL, NULL);
04503 
04504   res = _dbus_data_slot_list_get (&slot_allocator,
04505                                   &message->slot_list,
04506                                   slot);
04507 
04508   return res;
04509 }
04510 
04524 int
04525 dbus_message_type_from_string (const char *type_str)
04526 {
04527   if (strcmp (type_str, "method_call") == 0)
04528     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04529   if (strcmp (type_str, "method_return") == 0)
04530     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04531   else if (strcmp (type_str, "signal") == 0)
04532     return DBUS_MESSAGE_TYPE_SIGNAL;
04533   else if (strcmp (type_str, "error") == 0)
04534     return DBUS_MESSAGE_TYPE_ERROR;
04535   else
04536     return DBUS_MESSAGE_TYPE_INVALID;
04537 }
04538 
04552 const char *
04553 dbus_message_type_to_string (int type)
04554 {
04555   switch (type)
04556     {
04557     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04558       return "method_call";
04559     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04560       return "method_return";
04561     case DBUS_MESSAGE_TYPE_SIGNAL:
04562       return "signal";
04563     case DBUS_MESSAGE_TYPE_ERROR:
04564       return "error";
04565     default:
04566       return "invalid";
04567     }
04568 }
04569 
04582 dbus_bool_t
04583 dbus_message_marshal (DBusMessage  *msg,
04584                       char        **marshalled_data_p,
04585                       int          *len_p)
04586 {
04587   DBusString tmp;
04588   dbus_bool_t was_locked;
04589 
04590   _dbus_return_val_if_fail (msg != NULL, FALSE);
04591   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04592   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04593   
04594   if (!_dbus_string_init (&tmp))
04595     return FALSE;
04596 
04597   /* Ensure the message is locked, to ensure the length header is filled in. */
04598   was_locked = msg->locked;
04599 
04600   if (!was_locked)
04601     dbus_message_lock (msg);
04602 
04603   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04604     goto fail;
04605 
04606   *len_p = _dbus_string_get_length (&tmp);
04607 
04608   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04609     goto fail;
04610 
04611   *len_p = _dbus_string_get_length (&tmp);
04612 
04613   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04614     goto fail;
04615 
04616   _dbus_string_free (&tmp);
04617 
04618   if (!was_locked)
04619     msg->locked = FALSE;
04620 
04621   return TRUE;
04622 
04623  fail:
04624   _dbus_string_free (&tmp);
04625 
04626   if (!was_locked)
04627     msg->locked = FALSE;
04628 
04629   return FALSE;
04630 }
04631 
04644 DBusMessage *
04645 dbus_message_demarshal (const char *str,
04646                         int         len,
04647                         DBusError  *error)
04648 {
04649   DBusMessageLoader *loader;
04650   DBusString *buffer;
04651   DBusMessage *msg;
04652 
04653   _dbus_return_val_if_fail (str != NULL, NULL);
04654 
04655   loader = _dbus_message_loader_new ();
04656 
04657   if (loader == NULL)
04658     return NULL;
04659 
04660   _dbus_message_loader_get_buffer (loader, &buffer);
04661   _dbus_string_append_len (buffer, str, len);
04662   _dbus_message_loader_return_buffer (loader, buffer, len);
04663 
04664   if (!_dbus_message_loader_queue_messages (loader))
04665     goto fail_oom;
04666 
04667   if (_dbus_message_loader_get_is_corrupted (loader))
04668     goto fail_corrupt;
04669 
04670   msg = _dbus_message_loader_pop_message (loader);
04671 
04672   if (!msg)
04673     goto fail_oom;
04674 
04675   _dbus_message_loader_unref (loader);
04676   return msg;
04677 
04678  fail_corrupt:
04679   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04680                   _dbus_validity_to_error_message (loader->corruption_reason));
04681   _dbus_message_loader_unref (loader);
04682   return NULL;
04683 
04684  fail_oom:
04685   _DBUS_SET_OOM (error);
04686   _dbus_message_loader_unref (loader);
04687   return NULL;
04688 }
04689 
04703 int 
04704 dbus_message_demarshal_bytes_needed(const char *buf, 
04705                                     int         len)
04706 {
04707   DBusString str;
04708   int byte_order, fields_array_len, header_len, body_len;
04709   DBusValidity validity = DBUS_VALID;
04710   int have_message;
04711 
04712   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04713     return 0;
04714 
04715   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04716     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04717   _dbus_string_init_const_len (&str, buf, len);
04718   
04719   validity = DBUS_VALID;
04720   have_message
04721     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04722                                           &validity, &byte_order,
04723                                           &fields_array_len,
04724                                           &header_len,
04725                                           &body_len,
04726                                           &str, 0,
04727                                           len);
04728   _dbus_string_free (&str);
04729 
04730   if (validity == DBUS_VALID)
04731     {
04732       _dbus_assert (have_message || (header_len + body_len) > len);
04733       return header_len + body_len;
04734     }
04735   else
04736     {
04737       return -1; /* broken! */
04738     }
04739 }
04740 
04743 /* tests in dbus-message-util.c */