• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-validate.h"
00029 #include "dbus-marshal-byteswap.h"
00030 #include "dbus-marshal-header.h"
00031 #include "dbus-signature.h"
00032 #include "dbus-message-private.h"
00033 #include "dbus-object-tree.h"
00034 #include "dbus-memory.h"
00035 #include "dbus-list.h"
00036 #include "dbus-threads-internal.h"
00037 #ifdef HAVE_UNIX_FD_PASSING
00038 #include "dbus-sysdeps-unix.h"
00039 #endif
00040 
00041 #include <string.h>
00042 
00043 static void dbus_message_finalize (DBusMessage *message);
00044 
00055 /* Not thread locked, but strictly const/read-only so should be OK
00056  */
00058 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
00059 
00060 /* these have wacky values to help trap uninitialized iterators;
00061  * but has to fit in 3 bits
00062  */
00063 enum {
00064   DBUS_MESSAGE_ITER_TYPE_READER = 3,
00065   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
00066 };
00067 
00069 typedef struct DBusMessageRealIter DBusMessageRealIter;
00070 
00076 struct DBusMessageRealIter
00077 {
00078   DBusMessage *message; 
00079   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 
00080   dbus_uint32_t iter_type : 3;      
00081   dbus_uint32_t sig_refcount : 8;   
00082   union
00083   {
00084     DBusTypeWriter writer; 
00085     DBusTypeReader reader; 
00086   } u; 
00087 };
00088 
00089 static void
00090 get_const_signature (DBusHeader        *header,
00091                      const DBusString **type_str_p,
00092                      int               *type_pos_p)
00093 {
00094   if (_dbus_header_get_field_raw (header,
00095                                   DBUS_HEADER_FIELD_SIGNATURE,
00096                                   type_str_p,
00097                                   type_pos_p))
00098     {
00099       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00100     }
00101   else
00102     {
00103       *type_str_p = &_dbus_empty_signature_str;
00104       *type_pos_p = 0;
00105     }
00106 }
00107 
00113 static void
00114 _dbus_message_byteswap (DBusMessage *message)
00115 {
00116   const DBusString *type_str;
00117   int type_pos;
00118   
00119   if (message->byte_order == DBUS_COMPILER_BYTE_ORDER)
00120     return;
00121 
00122   _dbus_verbose ("Swapping message into compiler byte order\n");
00123   
00124   get_const_signature (&message->header, &type_str, &type_pos);
00125   
00126   _dbus_marshal_byteswap (type_str, type_pos,
00127                           message->byte_order,
00128                           DBUS_COMPILER_BYTE_ORDER,
00129                           &message->body, 0);
00130 
00131   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00132   
00133   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00134 }
00135 
00142 #define ensure_byte_order(message)                      \
00143  if (message->byte_order != DBUS_COMPILER_BYTE_ORDER)   \
00144    _dbus_message_byteswap (message)
00145 
00156 void
00157 _dbus_message_get_network_data (DBusMessage          *message,
00158                                 const DBusString    **header,
00159                                 const DBusString    **body)
00160 {
00161   _dbus_assert (message->locked);
00162 
00163   *header = &message->header.data;
00164   *body = &message->body;
00165 }
00166 
00176 void _dbus_message_get_unix_fds(DBusMessage *message,
00177                                 const int  **fds,
00178                                 unsigned    *n_fds)
00179 {
00180   _dbus_assert (message->locked);
00181 
00182 #ifdef HAVE_UNIX_FD_PASSING
00183   *fds = message->unix_fds;
00184   *n_fds = message->n_unix_fds;
00185 #else
00186   *fds = NULL;
00187   *n_fds = 0;
00188 #endif
00189 }
00190 
00202 void 
00203 dbus_message_set_serial (DBusMessage   *message,
00204                          dbus_uint32_t  serial)
00205 {
00206   _dbus_return_if_fail (message != NULL);
00207   _dbus_return_if_fail (!message->locked);
00208 
00209   _dbus_header_set_serial (&message->header, serial);
00210 }
00211 
00228 void
00229 _dbus_message_add_counter_link (DBusMessage  *message,
00230                                 DBusList     *link)
00231 {
00232   /* right now we don't recompute the delta when message
00233    * size changes, and that's OK for current purposes
00234    * I think, but could be important to change later.
00235    * Do recompute it whenever there are no outstanding counters,
00236    * since it's basically free.
00237    */
00238   if (message->counters == NULL)
00239     {
00240       message->size_counter_delta =
00241         _dbus_string_get_length (&message->header.data) +
00242         _dbus_string_get_length (&message->body);
00243 
00244 #ifdef HAVE_UNIX_FD_PASSING
00245       message->unix_fd_counter_delta = message->n_unix_fds;
00246 #endif
00247 
00248 #if 0
00249       _dbus_verbose ("message has size %ld\n",
00250                      message->size_counter_delta);
00251 #endif
00252     }
00253 
00254   _dbus_list_append_link (&message->counters, link);
00255 
00256   _dbus_counter_adjust_size (link->data, message->size_counter_delta);
00257 
00258 #ifdef HAVE_UNIX_FD_PASSING
00259   _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
00260 #endif
00261 }
00262 
00277 dbus_bool_t
00278 _dbus_message_add_counter (DBusMessage *message,
00279                            DBusCounter *counter)
00280 {
00281   DBusList *link;
00282 
00283   link = _dbus_list_alloc_link (counter);
00284   if (link == NULL)
00285     return FALSE;
00286 
00287   _dbus_counter_ref (counter);
00288   _dbus_message_add_counter_link (message, link);
00289 
00290   return TRUE;
00291 }
00292 
00301 void
00302 _dbus_message_remove_counter (DBusMessage  *message,
00303                               DBusCounter  *counter,
00304                               DBusList    **link_return)
00305 {
00306   DBusList *link;
00307 
00308   link = _dbus_list_find_last (&message->counters,
00309                                counter);
00310   _dbus_assert (link != NULL);
00311 
00312   _dbus_list_unlink (&message->counters,
00313                      link);
00314   if (link_return)
00315     *link_return = link;
00316   else
00317     _dbus_list_free_link (link);
00318 
00319   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00320 
00321 #ifdef HAVE_UNIX_FD_PASSING
00322   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00323 #endif
00324 
00325   _dbus_counter_notify (counter);
00326   _dbus_counter_unref (counter);
00327 }
00328 
00339 void
00340 dbus_message_lock (DBusMessage  *message)
00341 {
00342   if (!message->locked)
00343     {
00344       _dbus_header_update_lengths (&message->header,
00345                                    _dbus_string_get_length (&message->body));
00346 
00347       /* must have a signature if you have a body */
00348       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00349                     dbus_message_get_signature (message) != NULL);
00350 
00351       message->locked = TRUE;
00352     }
00353 }
00354 
00355 static dbus_bool_t
00356 set_or_delete_string_field (DBusMessage *message,
00357                             int          field,
00358                             int          typecode,
00359                             const char  *value)
00360 {
00361   if (value == NULL)
00362     return _dbus_header_delete_field (&message->header, field);
00363   else
00364     return _dbus_header_set_field_basic (&message->header,
00365                                          field,
00366                                          typecode,
00367                                          &value);
00368 }
00369 
00370 #if 0
00371 /* Probably we don't need to use this */
00395 static dbus_bool_t
00396 _dbus_message_set_signature (DBusMessage *message,
00397                              const char  *signature)
00398 {
00399   _dbus_return_val_if_fail (message != NULL, FALSE);
00400   _dbus_return_val_if_fail (!message->locked, FALSE);
00401   _dbus_return_val_if_fail (signature == NULL ||
00402                             _dbus_check_is_valid_signature (signature));
00403   /* can't delete the signature if you have a message body */
00404   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00405                             signature != NULL);
00406 
00407   return set_or_delete_string_field (message,
00408                                      DBUS_HEADER_FIELD_SIGNATURE,
00409                                      DBUS_TYPE_SIGNATURE,
00410                                      signature);
00411 }
00412 #endif
00413 
00414 /* Message Cache
00415  *
00416  * We cache some DBusMessage to reduce the overhead of allocating
00417  * them.  In my profiling this consistently made about an 8%
00418  * difference.  It avoids the malloc for the message, the malloc for
00419  * the slot list, the malloc for the header string and body string,
00420  * and the associated free() calls. It does introduce another global
00421  * lock which could be a performance issue in certain cases.
00422  *
00423  * For the echo client/server the round trip time goes from around
00424  * .000077 to .000069 with the message cache on my laptop. The sysprof
00425  * change is as follows (numbers are cumulative percentage):
00426  *
00427  *  with message cache implemented as array as it is now (0.000069 per):
00428  *    new_empty_header           1.46
00429  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00430  *      mutex_unlock             0.25
00431  *      self                     0.41
00432  *    unref                      2.24
00433  *      self                     0.68
00434  *      list_clear               0.43
00435  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00436  *      mutex_unlock             0.25
00437  *
00438  *  with message cache implemented as list (0.000070 per roundtrip):
00439  *    new_empty_header           2.72
00440  *      list_pop_first           1.88
00441  *    unref                      3.3
00442  *      list_prepend             1.63
00443  *
00444  * without cache (0.000077 per roundtrip):
00445  *    new_empty_header           6.7
00446  *      string_init_preallocated 3.43
00447  *        dbus_malloc            2.43
00448  *      dbus_malloc0             2.59
00449  *
00450  *    unref                      4.02
00451  *      string_free              1.82
00452  *        dbus_free              1.63
00453  *      dbus_free                0.71
00454  *
00455  * If you implement the message_cache with a list, the primary reason
00456  * it's slower is that you add another thread lock (on the DBusList
00457  * mempool).
00458  */
00459 
00461 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00462 
00464 #define MAX_MESSAGE_CACHE_SIZE    5
00465 
00466 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00467 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00468 static int message_cache_count = 0;
00469 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00470 
00471 static void
00472 dbus_message_cache_shutdown (void *data)
00473 {
00474   int i;
00475 
00476   _DBUS_LOCK (message_cache);
00477 
00478   i = 0;
00479   while (i < MAX_MESSAGE_CACHE_SIZE)
00480     {
00481       if (message_cache[i])
00482         dbus_message_finalize (message_cache[i]);
00483 
00484       ++i;
00485     }
00486 
00487   message_cache_count = 0;
00488   message_cache_shutdown_registered = FALSE;
00489 
00490   _DBUS_UNLOCK (message_cache);
00491 }
00492 
00500 static DBusMessage*
00501 dbus_message_get_cached (void)
00502 {
00503   DBusMessage *message;
00504   int i;
00505 
00506   message = NULL;
00507 
00508   _DBUS_LOCK (message_cache);
00509 
00510   _dbus_assert (message_cache_count >= 0);
00511 
00512   if (message_cache_count == 0)
00513     {
00514       _DBUS_UNLOCK (message_cache);
00515       return NULL;
00516     }
00517 
00518   /* This is not necessarily true unless count > 0, and
00519    * message_cache is uninitialized until the shutdown is
00520    * registered
00521    */
00522   _dbus_assert (message_cache_shutdown_registered);
00523 
00524   i = 0;
00525   while (i < MAX_MESSAGE_CACHE_SIZE)
00526     {
00527       if (message_cache[i])
00528         {
00529           message = message_cache[i];
00530           message_cache[i] = NULL;
00531           message_cache_count -= 1;
00532           break;
00533         }
00534       ++i;
00535     }
00536   _dbus_assert (message_cache_count >= 0);
00537   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00538   _dbus_assert (message != NULL);
00539 
00540   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00541 
00542   _dbus_assert (message->counters == NULL);
00543   
00544   _DBUS_UNLOCK (message_cache);
00545 
00546   return message;
00547 }
00548 
00549 #ifdef HAVE_UNIX_FD_PASSING
00550 static void
00551 close_unix_fds(int *fds, unsigned *n_fds)
00552 {
00553   DBusError e;
00554   int i;
00555 
00556   if (*n_fds <= 0)
00557     return;
00558 
00559   dbus_error_init(&e);
00560 
00561   for (i = 0; i < *n_fds; i++)
00562     {
00563       if (!_dbus_close(fds[i], &e))
00564         {
00565           _dbus_warn("Failed to close file descriptor: %s\n", e.message);
00566           dbus_error_free(&e);
00567         }
00568     }
00569 
00570   *n_fds = 0;
00571 
00572   /* We don't free the array here, in case we can recycle it later */
00573 }
00574 #endif
00575 
00576 static void
00577 free_counter (void *element,
00578               void *data)
00579 {
00580   DBusCounter *counter = element;
00581   DBusMessage *message = data;
00582 
00583   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00584 #ifdef HAVE_UNIX_FD_PASSING
00585   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00586 #endif
00587 
00588   _dbus_counter_notify (counter);
00589   _dbus_counter_unref (counter);
00590 }
00591 
00597 static void
00598 dbus_message_cache_or_finalize (DBusMessage *message)
00599 {
00600   dbus_bool_t was_cached;
00601   int i;
00602 
00603   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00604 
00605   /* This calls application code and has to be done first thing
00606    * without holding the lock
00607    */
00608   _dbus_data_slot_list_clear (&message->slot_list);
00609 
00610   _dbus_list_foreach (&message->counters,
00611                       free_counter, message);
00612   _dbus_list_clear (&message->counters);
00613 
00614 #ifdef HAVE_UNIX_FD_PASSING
00615   close_unix_fds(message->unix_fds, &message->n_unix_fds);
00616 #endif
00617 
00618   was_cached = FALSE;
00619 
00620   _DBUS_LOCK (message_cache);
00621 
00622   if (!message_cache_shutdown_registered)
00623     {
00624       _dbus_assert (message_cache_count == 0);
00625 
00626       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00627         goto out;
00628 
00629       i = 0;
00630       while (i < MAX_MESSAGE_CACHE_SIZE)
00631         {
00632           message_cache[i] = NULL;
00633           ++i;
00634         }
00635 
00636       message_cache_shutdown_registered = TRUE;
00637     }
00638 
00639   _dbus_assert (message_cache_count >= 0);
00640 
00641   if ((_dbus_string_get_length (&message->header.data) +
00642        _dbus_string_get_length (&message->body)) >
00643       MAX_MESSAGE_SIZE_TO_CACHE)
00644     goto out;
00645 
00646   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00647     goto out;
00648 
00649   /* Find empty slot */
00650   i = 0;
00651   while (message_cache[i] != NULL)
00652     ++i;
00653 
00654   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00655 
00656   _dbus_assert (message_cache[i] == NULL);
00657   message_cache[i] = message;
00658   message_cache_count += 1;
00659   was_cached = TRUE;
00660 #ifndef DBUS_DISABLE_CHECKS
00661   message->in_cache = TRUE;
00662 #endif
00663 
00664  out:
00665   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00666 
00667   _DBUS_UNLOCK (message_cache);
00668   
00669   if (!was_cached)
00670     dbus_message_finalize (message);
00671 }
00672 
00673 #ifndef DBUS_DISABLE_CHECKS
00674 static dbus_bool_t
00675 _dbus_message_iter_check (DBusMessageRealIter *iter)
00676 {
00677   if (iter == NULL)
00678     {
00679       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00680       return FALSE;
00681     }
00682 
00683   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00684     {
00685       if (iter->u.reader.byte_order != iter->message->byte_order)
00686         {
00687           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00688           return FALSE;
00689         }
00690       /* because we swap the message into compiler order when you init an iter */
00691       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00692     }
00693   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00694     {
00695       if (iter->u.writer.byte_order != iter->message->byte_order)
00696         {
00697           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00698           return FALSE;
00699         }
00700       /* because we swap the message into compiler order when you init an iter */
00701       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00702     }
00703   else
00704     {
00705       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00706       return FALSE;
00707     }
00708 
00709   if (iter->changed_stamp != iter->message->changed_stamp)
00710     {
00711       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00712       return FALSE;
00713     }
00714 
00715   return TRUE;
00716 }
00717 #endif /* DBUS_DISABLE_CHECKS */
00718 
00733 dbus_bool_t
00734 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00735                                     DBusError       *error,
00736                                     int              first_arg_type,
00737                                     va_list          var_args)
00738 {
00739   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00740   int spec_type, msg_type, i;
00741   dbus_bool_t retval;
00742 
00743   _dbus_assert (_dbus_message_iter_check (real));
00744 
00745   retval = FALSE;
00746 
00747   spec_type = first_arg_type;
00748   i = 0;
00749 
00750   while (spec_type != DBUS_TYPE_INVALID)
00751     {
00752       msg_type = dbus_message_iter_get_arg_type (iter);
00753 
00754       if (msg_type != spec_type)
00755         {
00756           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00757                           "Argument %d is specified to be of type \"%s\", but "
00758                           "is actually of type \"%s\"\n", i,
00759                           _dbus_type_to_string (spec_type),
00760                           _dbus_type_to_string (msg_type));
00761 
00762           goto out;
00763         }
00764 
00765       if (spec_type == DBUS_TYPE_UNIX_FD)
00766         {
00767 #ifdef HAVE_UNIX_FD_PASSING
00768           DBusBasicValue idx;
00769           int *pfd, nfd;
00770 
00771           pfd = va_arg (var_args, int*);
00772           _dbus_assert(pfd);
00773 
00774           _dbus_type_reader_read_basic(&real->u.reader, &idx);
00775 
00776           if (idx.u32 >= real->message->n_unix_fds)
00777             {
00778               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
00779                               "Message refers to file descriptor at index %i,"
00780                               "but has only %i descriptors attached.\n",
00781                               idx.u32,
00782                               real->message->n_unix_fds);
00783               goto out;
00784             }
00785 
00786           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
00787             goto out;
00788 
00789           *pfd = nfd;
00790 #else
00791           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00792                           "Platform does not support file desciptor passing.\n");
00793           goto out;
00794 #endif
00795         }
00796       else if (dbus_type_is_basic (spec_type))
00797         {
00798           DBusBasicValue *ptr;
00799 
00800           ptr = va_arg (var_args, DBusBasicValue*);
00801 
00802           _dbus_assert (ptr != NULL);
00803 
00804           _dbus_type_reader_read_basic (&real->u.reader,
00805                                         ptr);
00806         }
00807       else if (spec_type == DBUS_TYPE_ARRAY)
00808         {
00809           int element_type;
00810           int spec_element_type;
00811           const DBusBasicValue **ptr;
00812           int *n_elements_p;
00813           DBusTypeReader array;
00814 
00815           spec_element_type = va_arg (var_args, int);
00816           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00817 
00818           if (spec_element_type != element_type)
00819             {
00820               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00821                               "Argument %d is specified to be an array of \"%s\", but "
00822                               "is actually an array of \"%s\"\n",
00823                               i,
00824                               _dbus_type_to_string (spec_element_type),
00825                               _dbus_type_to_string (element_type));
00826 
00827               goto out;
00828             }
00829 
00830           if (dbus_type_is_fixed (spec_element_type) &&
00831               element_type != DBUS_TYPE_UNIX_FD)
00832             {
00833               ptr = va_arg (var_args, const DBusBasicValue**);
00834               n_elements_p = va_arg (var_args, int*);
00835 
00836               _dbus_assert (ptr != NULL);
00837               _dbus_assert (n_elements_p != NULL);
00838 
00839               _dbus_type_reader_recurse (&real->u.reader, &array);
00840 
00841               _dbus_type_reader_read_fixed_multi (&array,
00842                                                   (void *) ptr, n_elements_p);
00843             }
00844           else if (spec_element_type == DBUS_TYPE_STRING ||
00845                    spec_element_type == DBUS_TYPE_SIGNATURE ||
00846                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
00847             {
00848               char ***str_array_p;
00849               int n_elements;
00850               char **str_array;
00851 
00852               str_array_p = va_arg (var_args, char***);
00853               n_elements_p = va_arg (var_args, int*);
00854 
00855               _dbus_assert (str_array_p != NULL);
00856               _dbus_assert (n_elements_p != NULL);
00857 
00858               /* Count elements in the array */
00859               _dbus_type_reader_recurse (&real->u.reader, &array);
00860 
00861               n_elements = 0;
00862               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00863                 {
00864                   ++n_elements;
00865                   _dbus_type_reader_next (&array);
00866                 }
00867 
00868               str_array = dbus_new0 (char*, n_elements + 1);
00869               if (str_array == NULL)
00870                 {
00871                   _DBUS_SET_OOM (error);
00872                   goto out;
00873                 }
00874 
00875               /* Now go through and dup each string */
00876               _dbus_type_reader_recurse (&real->u.reader, &array);
00877 
00878               i = 0;
00879               while (i < n_elements)
00880                 {
00881                   const char *s;
00882                   _dbus_type_reader_read_basic (&array,
00883                                                 (void *) &s);
00884                   
00885                   str_array[i] = _dbus_strdup (s);
00886                   if (str_array[i] == NULL)
00887                     {
00888                       dbus_free_string_array (str_array);
00889                       _DBUS_SET_OOM (error);
00890                       goto out;
00891                     }
00892                   
00893                   ++i;
00894                   
00895                   if (!_dbus_type_reader_next (&array))
00896                     _dbus_assert (i == n_elements);
00897                 }
00898 
00899               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00900               _dbus_assert (i == n_elements);
00901               _dbus_assert (str_array[i] == NULL);
00902 
00903               *str_array_p = str_array;
00904               *n_elements_p = n_elements;
00905             }
00906 #ifndef DBUS_DISABLE_CHECKS
00907           else
00908             {
00909               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00910                           _DBUS_FUNCTION_NAME);
00911               goto out;
00912             }
00913 #endif
00914         }
00915 #ifndef DBUS_DISABLE_CHECKS
00916       else
00917         {
00918           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00919                       _DBUS_FUNCTION_NAME);
00920           goto out;
00921         }
00922 #endif
00923 
00924       spec_type = va_arg (var_args, int);
00925       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00926         {
00927           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00928                           "Message has only %d arguments, but more were expected", i);
00929           goto out;
00930         }
00931 
00932       i++;
00933     }
00934 
00935   retval = TRUE;
00936 
00937  out:
00938 
00939   return retval;
00940 }
00941 
01000 dbus_uint32_t
01001 dbus_message_get_serial (DBusMessage *message)
01002 {
01003   _dbus_return_val_if_fail (message != NULL, 0);
01004 
01005   return _dbus_header_get_serial (&message->header);
01006 }
01007 
01016 dbus_bool_t
01017 dbus_message_set_reply_serial (DBusMessage   *message,
01018                                dbus_uint32_t  reply_serial)
01019 {
01020   _dbus_return_val_if_fail (message != NULL, FALSE);
01021   _dbus_return_val_if_fail (!message->locked, FALSE);
01022   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01023 
01024   return _dbus_header_set_field_basic (&message->header,
01025                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01026                                        DBUS_TYPE_UINT32,
01027                                        &reply_serial);
01028 }
01029 
01036 dbus_uint32_t
01037 dbus_message_get_reply_serial  (DBusMessage *message)
01038 {
01039   dbus_uint32_t v_UINT32;
01040 
01041   _dbus_return_val_if_fail (message != NULL, 0);
01042 
01043   if (_dbus_header_get_field_basic (&message->header,
01044                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01045                                     DBUS_TYPE_UINT32,
01046                                     &v_UINT32))
01047     return v_UINT32;
01048   else
01049     return 0;
01050 }
01051 
01052 static void
01053 dbus_message_finalize (DBusMessage *message)
01054 {
01055   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01056 
01057   /* This calls application callbacks! */
01058   _dbus_data_slot_list_free (&message->slot_list);
01059 
01060   _dbus_list_foreach (&message->counters,
01061                       free_counter, message);
01062   _dbus_list_clear (&message->counters);
01063 
01064   _dbus_header_free (&message->header);
01065   _dbus_string_free (&message->body);
01066 
01067 #ifdef HAVE_UNIX_FD_PASSING
01068   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01069   dbus_free(message->unix_fds);
01070 #endif
01071 
01072   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01073 
01074   dbus_free (message);
01075 }
01076 
01077 static DBusMessage*
01078 dbus_message_new_empty_header (void)
01079 {
01080   DBusMessage *message;
01081   dbus_bool_t from_cache;
01082 
01083   message = dbus_message_get_cached ();
01084 
01085   if (message != NULL)
01086     {
01087       from_cache = TRUE;
01088     }
01089   else
01090     {
01091       from_cache = FALSE;
01092       message = dbus_new0 (DBusMessage, 1);
01093       if (message == NULL)
01094         return NULL;
01095 #ifndef DBUS_DISABLE_CHECKS
01096       message->generation = _dbus_current_generation;
01097 #endif
01098 
01099 #ifdef HAVE_UNIX_FD_PASSING
01100       message->unix_fds = NULL;
01101       message->n_unix_fds_allocated = 0;
01102 #endif
01103     }
01104 
01105   _dbus_atomic_inc (&message->refcount);
01106 
01107   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
01108   message->locked = FALSE;
01109 #ifndef DBUS_DISABLE_CHECKS
01110   message->in_cache = FALSE;
01111 #endif
01112   message->counters = NULL;
01113   message->size_counter_delta = 0;
01114   message->changed_stamp = 0;
01115 
01116 #ifdef HAVE_UNIX_FD_PASSING
01117   message->n_unix_fds = 0;
01118   message->n_unix_fds_allocated = 0;
01119   message->unix_fd_counter_delta = 0;
01120 #endif
01121 
01122   if (!from_cache)
01123     _dbus_data_slot_list_init (&message->slot_list);
01124 
01125   if (from_cache)
01126     {
01127       _dbus_header_reinit (&message->header, message->byte_order);
01128       _dbus_string_set_length (&message->body, 0);
01129     }
01130   else
01131     {
01132       if (!_dbus_header_init (&message->header, message->byte_order))
01133         {
01134           dbus_free (message);
01135           return NULL;
01136         }
01137 
01138       if (!_dbus_string_init_preallocated (&message->body, 32))
01139         {
01140           _dbus_header_free (&message->header);
01141           dbus_free (message);
01142           return NULL;
01143         }
01144     }
01145 
01146   return message;
01147 }
01148 
01161 DBusMessage*
01162 dbus_message_new (int message_type)
01163 {
01164   DBusMessage *message;
01165 
01166   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01167 
01168   message = dbus_message_new_empty_header ();
01169   if (message == NULL)
01170     return NULL;
01171 
01172   if (!_dbus_header_create (&message->header,
01173                             message_type,
01174                             NULL, NULL, NULL, NULL, NULL))
01175     {
01176       dbus_message_unref (message);
01177       return NULL;
01178     }
01179 
01180   return message;
01181 }
01182 
01204 DBusMessage*
01205 dbus_message_new_method_call (const char *destination,
01206                               const char *path,
01207                               const char *interface,
01208                               const char *method)
01209 {
01210   DBusMessage *message;
01211 
01212   _dbus_return_val_if_fail (path != NULL, NULL);
01213   _dbus_return_val_if_fail (method != NULL, NULL);
01214   _dbus_return_val_if_fail (destination == NULL ||
01215                             _dbus_check_is_valid_bus_name (destination), NULL);
01216   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01217   _dbus_return_val_if_fail (interface == NULL ||
01218                             _dbus_check_is_valid_interface (interface), NULL);
01219   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01220 
01221   message = dbus_message_new_empty_header ();
01222   if (message == NULL)
01223     return NULL;
01224 
01225   if (!_dbus_header_create (&message->header,
01226                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01227                             destination, path, interface, method, NULL))
01228     {
01229       dbus_message_unref (message);
01230       return NULL;
01231     }
01232 
01233   return message;
01234 }
01235 
01243 DBusMessage*
01244 dbus_message_new_method_return (DBusMessage *method_call)
01245 {
01246   DBusMessage *message;
01247   const char *sender;
01248 
01249   _dbus_return_val_if_fail (method_call != NULL, NULL);
01250 
01251   sender = dbus_message_get_sender (method_call);
01252 
01253   /* sender is allowed to be null here in peer-to-peer case */
01254 
01255   message = dbus_message_new_empty_header ();
01256   if (message == NULL)
01257     return NULL;
01258 
01259   if (!_dbus_header_create (&message->header,
01260                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01261                             sender, NULL, NULL, NULL, NULL))
01262     {
01263       dbus_message_unref (message);
01264       return NULL;
01265     }
01266 
01267   dbus_message_set_no_reply (message, TRUE);
01268 
01269   if (!dbus_message_set_reply_serial (message,
01270                                       dbus_message_get_serial (method_call)))
01271     {
01272       dbus_message_unref (message);
01273       return NULL;
01274     }
01275 
01276   return message;
01277 }
01278 
01293 DBusMessage*
01294 dbus_message_new_signal (const char *path,
01295                          const char *interface,
01296                          const char *name)
01297 {
01298   DBusMessage *message;
01299 
01300   _dbus_return_val_if_fail (path != NULL, NULL);
01301   _dbus_return_val_if_fail (interface != NULL, NULL);
01302   _dbus_return_val_if_fail (name != NULL, NULL);
01303   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01304   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
01305   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01306 
01307   message = dbus_message_new_empty_header ();
01308   if (message == NULL)
01309     return NULL;
01310 
01311   if (!_dbus_header_create (&message->header,
01312                             DBUS_MESSAGE_TYPE_SIGNAL,
01313                             NULL, path, interface, name, NULL))
01314     {
01315       dbus_message_unref (message);
01316       return NULL;
01317     }
01318 
01319   dbus_message_set_no_reply (message, TRUE);
01320 
01321   return message;
01322 }
01323 
01338 DBusMessage*
01339 dbus_message_new_error (DBusMessage *reply_to,
01340                         const char  *error_name,
01341                         const char  *error_message)
01342 {
01343   DBusMessage *message;
01344   const char *sender;
01345   DBusMessageIter iter;
01346 
01347   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01348   _dbus_return_val_if_fail (error_name != NULL, NULL);
01349   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01350 
01351   sender = dbus_message_get_sender (reply_to);
01352 
01353   /* sender may be NULL for non-message-bus case or
01354    * when the message bus is dealing with an unregistered
01355    * connection.
01356    */
01357   message = dbus_message_new_empty_header ();
01358   if (message == NULL)
01359     return NULL;
01360 
01361   if (!_dbus_header_create (&message->header,
01362                             DBUS_MESSAGE_TYPE_ERROR,
01363                             sender, NULL, NULL, NULL, error_name))
01364     {
01365       dbus_message_unref (message);
01366       return NULL;
01367     }
01368 
01369   dbus_message_set_no_reply (message, TRUE);
01370 
01371   if (!dbus_message_set_reply_serial (message,
01372                                       dbus_message_get_serial (reply_to)))
01373     {
01374       dbus_message_unref (message);
01375       return NULL;
01376     }
01377 
01378   if (error_message != NULL)
01379     {
01380       dbus_message_iter_init_append (message, &iter);
01381       if (!dbus_message_iter_append_basic (&iter,
01382                                            DBUS_TYPE_STRING,
01383                                            &error_message))
01384         {
01385           dbus_message_unref (message);
01386           return NULL;
01387         }
01388     }
01389 
01390   return message;
01391 }
01392 
01409 DBusMessage*
01410 dbus_message_new_error_printf (DBusMessage *reply_to,
01411                                const char  *error_name,
01412                                const char  *error_format,
01413                                ...)
01414 {
01415   va_list args;
01416   DBusString str;
01417   DBusMessage *message;
01418 
01419   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01420   _dbus_return_val_if_fail (error_name != NULL, NULL);
01421   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01422 
01423   if (!_dbus_string_init (&str))
01424     return NULL;
01425 
01426   va_start (args, error_format);
01427 
01428   if (_dbus_string_append_printf_valist (&str, error_format, args))
01429     message = dbus_message_new_error (reply_to, error_name,
01430                                       _dbus_string_get_const_data (&str));
01431   else
01432     message = NULL;
01433 
01434   _dbus_string_free (&str);
01435 
01436   va_end (args);
01437 
01438   return message;
01439 }
01440 
01441 
01454 DBusMessage *
01455 dbus_message_copy (const DBusMessage *message)
01456 {
01457   DBusMessage *retval;
01458 
01459   _dbus_return_val_if_fail (message != NULL, NULL);
01460 
01461   retval = dbus_new0 (DBusMessage, 1);
01462   if (retval == NULL)
01463     return NULL;
01464 
01465   _dbus_atomic_inc (&retval->refcount);
01466   retval->byte_order = message->byte_order;
01467   retval->locked = FALSE;
01468 #ifndef DBUS_DISABLE_CHECKS
01469   retval->generation = message->generation;
01470 #endif
01471 
01472   if (!_dbus_header_copy (&message->header, &retval->header))
01473     {
01474       dbus_free (retval);
01475       return NULL;
01476     }
01477 
01478   if (!_dbus_string_init_preallocated (&retval->body,
01479                                        _dbus_string_get_length (&message->body)))
01480     {
01481       _dbus_header_free (&retval->header);
01482       dbus_free (retval);
01483       return NULL;
01484     }
01485 
01486   if (!_dbus_string_copy (&message->body, 0,
01487                           &retval->body, 0))
01488     goto failed_copy;
01489 
01490 #ifdef HAVE_UNIX_FD_PASSING
01491   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01492   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01493     goto failed_copy;
01494 
01495   retval->n_unix_fds_allocated = message->n_unix_fds;
01496 
01497   for (retval->n_unix_fds = 0;
01498        retval->n_unix_fds < message->n_unix_fds;
01499        retval->n_unix_fds++)
01500     {
01501       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01502 
01503       if (retval->unix_fds[retval->n_unix_fds] < 0)
01504         goto failed_copy;
01505     }
01506 
01507 #endif
01508 
01509   return retval;
01510 
01511  failed_copy:
01512   _dbus_header_free (&retval->header);
01513   _dbus_string_free (&retval->body);
01514 
01515 #ifdef HAVE_UNIX_FD_PASSING
01516   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01517   dbus_free(retval->unix_fds);
01518 #endif
01519 
01520   dbus_free (retval);
01521 
01522   return NULL;
01523 }
01524 
01525 
01533 DBusMessage *
01534 dbus_message_ref (DBusMessage *message)
01535 {
01536 #ifndef DBUS_DISABLE_ASSERT
01537   dbus_int32_t old_refcount;
01538 #endif
01539 
01540   _dbus_return_val_if_fail (message != NULL, NULL);
01541   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01542   _dbus_return_val_if_fail (!message->in_cache, NULL);
01543 
01544 #ifdef DBUS_DISABLE_ASSERT
01545   _dbus_atomic_inc (&message->refcount);
01546 #else
01547   old_refcount = _dbus_atomic_inc (&message->refcount);
01548   _dbus_assert (old_refcount >= 1);
01549 #endif
01550 
01551   return message;
01552 }
01553 
01561 void
01562 dbus_message_unref (DBusMessage *message)
01563 {
01564  dbus_int32_t old_refcount;
01565 
01566   _dbus_return_if_fail (message != NULL);
01567   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01568   _dbus_return_if_fail (!message->in_cache);
01569 
01570   old_refcount = _dbus_atomic_dec (&message->refcount);
01571 
01572   _dbus_assert (old_refcount >= 1);
01573 
01574   if (old_refcount == 1)
01575     {
01576       /* Calls application callbacks! */
01577       dbus_message_cache_or_finalize (message);
01578     }
01579 }
01580 
01591 int
01592 dbus_message_get_type (DBusMessage *message)
01593 {
01594   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01595 
01596   return _dbus_header_get_message_type (&message->header);
01597 }
01598 
01661 dbus_bool_t
01662 dbus_message_append_args (DBusMessage *message,
01663                           int          first_arg_type,
01664                           ...)
01665 {
01666   dbus_bool_t retval;
01667   va_list var_args;
01668 
01669   _dbus_return_val_if_fail (message != NULL, FALSE);
01670 
01671   va_start (var_args, first_arg_type);
01672   retval = dbus_message_append_args_valist (message,
01673                                             first_arg_type,
01674                                             var_args);
01675   va_end (var_args);
01676 
01677   return retval;
01678 }
01679 
01693 dbus_bool_t
01694 dbus_message_append_args_valist (DBusMessage *message,
01695                                  int          first_arg_type,
01696                                  va_list      var_args)
01697 {
01698   int type;
01699   DBusMessageIter iter;
01700 
01701   _dbus_return_val_if_fail (message != NULL, FALSE);
01702 
01703   type = first_arg_type;
01704 
01705   dbus_message_iter_init_append (message, &iter);
01706 
01707   while (type != DBUS_TYPE_INVALID)
01708     {
01709       if (dbus_type_is_basic (type))
01710         {
01711           const DBusBasicValue *value;
01712           value = va_arg (var_args, const DBusBasicValue*);
01713 
01714           if (!dbus_message_iter_append_basic (&iter,
01715                                                type,
01716                                                value))
01717             goto failed;
01718         }
01719       else if (type == DBUS_TYPE_ARRAY)
01720         {
01721           int element_type;
01722           DBusMessageIter array;
01723           char buf[2];
01724 
01725           element_type = va_arg (var_args, int);
01726               
01727           buf[0] = element_type;
01728           buf[1] = '\0';
01729           if (!dbus_message_iter_open_container (&iter,
01730                                                  DBUS_TYPE_ARRAY,
01731                                                  buf,
01732                                                  &array))
01733             goto failed;
01734 
01735           if (dbus_type_is_fixed (element_type) &&
01736               element_type != DBUS_TYPE_UNIX_FD)
01737             {
01738               const DBusBasicValue **value;
01739               int n_elements;
01740 
01741               value = va_arg (var_args, const DBusBasicValue**);
01742               n_elements = va_arg (var_args, int);
01743               
01744               if (!dbus_message_iter_append_fixed_array (&array,
01745                                                          element_type,
01746                                                          value,
01747                                                          n_elements)) {
01748                 dbus_message_iter_abandon_container (&iter, &array);
01749                 goto failed;
01750               }
01751             }
01752           else if (element_type == DBUS_TYPE_STRING ||
01753                    element_type == DBUS_TYPE_SIGNATURE ||
01754                    element_type == DBUS_TYPE_OBJECT_PATH)
01755             {
01756               const char ***value_p;
01757               const char **value;
01758               int n_elements;
01759               int i;
01760               
01761               value_p = va_arg (var_args, const char***);
01762               n_elements = va_arg (var_args, int);
01763 
01764               value = *value_p;
01765               
01766               i = 0;
01767               while (i < n_elements)
01768                 {
01769                   if (!dbus_message_iter_append_basic (&array,
01770                                                        element_type,
01771                                                        &value[i])) {
01772                     dbus_message_iter_abandon_container (&iter, &array);
01773                     goto failed;
01774                   }
01775                   ++i;
01776                 }
01777             }
01778           else
01779             {
01780               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01781                           _dbus_type_to_string (element_type),
01782                           _DBUS_FUNCTION_NAME);
01783               goto failed;
01784             }
01785 
01786           if (!dbus_message_iter_close_container (&iter, &array))
01787             goto failed;
01788         }
01789 #ifndef DBUS_DISABLE_CHECKS
01790       else
01791         {
01792           _dbus_warn ("type %s isn't supported yet in %s\n",
01793                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01794           goto failed;
01795         }
01796 #endif
01797 
01798       type = va_arg (var_args, int);
01799     }
01800 
01801   return TRUE;
01802 
01803  failed:
01804   return FALSE;
01805 }
01806 
01851 dbus_bool_t
01852 dbus_message_get_args (DBusMessage     *message,
01853                        DBusError       *error,
01854                        int              first_arg_type,
01855                        ...)
01856 {
01857   dbus_bool_t retval;
01858   va_list var_args;
01859 
01860   _dbus_return_val_if_fail (message != NULL, FALSE);
01861   _dbus_return_val_if_error_is_set (error, FALSE);
01862 
01863   va_start (var_args, first_arg_type);
01864   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01865   va_end (var_args);
01866 
01867   return retval;
01868 }
01869 
01880 dbus_bool_t
01881 dbus_message_get_args_valist (DBusMessage     *message,
01882                               DBusError       *error,
01883                               int              first_arg_type,
01884                               va_list          var_args)
01885 {
01886   DBusMessageIter iter;
01887 
01888   _dbus_return_val_if_fail (message != NULL, FALSE);
01889   _dbus_return_val_if_error_is_set (error, FALSE);
01890 
01891   dbus_message_iter_init (message, &iter);
01892   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01893 }
01894 
01895 static void
01896 _dbus_message_iter_init_common (DBusMessage         *message,
01897                                 DBusMessageRealIter *real,
01898                                 int                  iter_type)
01899 {
01900   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01901 
01902   /* Since the iterator will read or write who-knows-what from the
01903    * message, we need to get in the right byte order
01904    */
01905   ensure_byte_order (message);
01906   
01907   real->message = message;
01908   real->changed_stamp = message->changed_stamp;
01909   real->iter_type = iter_type;
01910   real->sig_refcount = 0;
01911 }
01912 
01935 dbus_bool_t
01936 dbus_message_iter_init (DBusMessage     *message,
01937                         DBusMessageIter *iter)
01938 {
01939   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01940   const DBusString *type_str;
01941   int type_pos;
01942 
01943   _dbus_return_val_if_fail (message != NULL, FALSE);
01944   _dbus_return_val_if_fail (iter != NULL, FALSE);
01945 
01946   get_const_signature (&message->header, &type_str, &type_pos);
01947 
01948   _dbus_message_iter_init_common (message, real,
01949                                   DBUS_MESSAGE_ITER_TYPE_READER);
01950 
01951   _dbus_type_reader_init (&real->u.reader,
01952                           message->byte_order,
01953                           type_str, type_pos,
01954                           &message->body,
01955                           0);
01956 
01957   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
01958 }
01959 
01966 dbus_bool_t
01967 dbus_message_iter_has_next (DBusMessageIter *iter)
01968 {
01969   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01970 
01971   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01972   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01973 
01974   return _dbus_type_reader_has_next (&real->u.reader);
01975 }
01976 
01985 dbus_bool_t
01986 dbus_message_iter_next (DBusMessageIter *iter)
01987 {
01988   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01989 
01990   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01991   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01992 
01993   return _dbus_type_reader_next (&real->u.reader);
01994 }
01995 
02010 int
02011 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02012 {
02013   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02014 
02015   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02016   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02017 
02018   return _dbus_type_reader_get_current_type (&real->u.reader);
02019 }
02020 
02029 int
02030 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02031 {
02032   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02033 
02034   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02035   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02036   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02037 
02038   return _dbus_type_reader_get_element_type (&real->u.reader);
02039 }
02040 
02066 void
02067 dbus_message_iter_recurse (DBusMessageIter  *iter,
02068                            DBusMessageIter  *sub)
02069 {
02070   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02071   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02072 
02073   _dbus_return_if_fail (_dbus_message_iter_check (real));
02074   _dbus_return_if_fail (sub != NULL);
02075 
02076   *real_sub = *real;
02077   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02078 }
02079 
02091 char *
02092 dbus_message_iter_get_signature (DBusMessageIter *iter)
02093 {
02094   const DBusString *sig;
02095   DBusString retstr;
02096   char *ret;
02097   int start, len;
02098   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02099 
02100   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02101 
02102   if (!_dbus_string_init (&retstr))
02103     return NULL;
02104 
02105   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02106                                    &start, &len);
02107   if (!_dbus_string_append_len (&retstr,
02108                                 _dbus_string_get_const_data (sig) + start,
02109                                 len))
02110     return NULL;
02111   if (!_dbus_string_steal_data (&retstr, &ret))
02112     return NULL;
02113   _dbus_string_free (&retstr);
02114   return ret;
02115 }
02116 
02164 void
02165 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02166                              void             *value)
02167 {
02168   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02169 
02170   _dbus_return_if_fail (_dbus_message_iter_check (real));
02171   _dbus_return_if_fail (value != NULL);
02172 
02173   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02174     {
02175 #ifdef HAVE_UNIX_FD_PASSING
02176       DBusBasicValue idx;
02177 
02178       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02179 
02180       if (idx.u32 >= real->message->n_unix_fds) {
02181         /* Hmm, we cannot really signal an error here, so let's make
02182            sure to return an invalid fd. */
02183         *((int*) value) = -1;
02184         return;
02185       }
02186 
02187       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02188 #else
02189       *((int*) value) = -1;
02190 #endif
02191     }
02192   else
02193     {
02194       _dbus_type_reader_read_basic (&real->u.reader,
02195                                     value);
02196     }
02197 }
02198 
02217 int
02218 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02219 {
02220   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02221 
02222   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02223 
02224   return _dbus_type_reader_get_array_length (&real->u.reader);
02225 }
02226 
02262 void
02263 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02264                                    void             *value,
02265                                    int              *n_elements)
02266 {
02267   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02268   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02269 
02270   _dbus_return_if_fail (_dbus_message_iter_check (real));
02271   _dbus_return_if_fail (value != NULL);
02272   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02273                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02274 
02275   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02276                                       value, n_elements);
02277 }
02278 
02290 void
02291 dbus_message_iter_init_append (DBusMessage     *message,
02292                                DBusMessageIter *iter)
02293 {
02294   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02295 
02296   _dbus_return_if_fail (message != NULL);
02297   _dbus_return_if_fail (iter != NULL);
02298 
02299   _dbus_message_iter_init_common (message, real,
02300                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02301 
02302   /* We create the signature string and point iterators at it "on demand"
02303    * when a value is actually appended. That means that init() never fails
02304    * due to OOM.
02305    */
02306   _dbus_type_writer_init_types_delayed (&real->u.writer,
02307                                         message->byte_order,
02308                                         &message->body,
02309                                         _dbus_string_get_length (&message->body));
02310 }
02311 
02320 static dbus_bool_t
02321 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02322 {
02323   DBusString *str;
02324   const DBusString *current_sig;
02325   int current_sig_pos;
02326 
02327   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02328 
02329   if (real->u.writer.type_str != NULL)
02330     {
02331       _dbus_assert (real->sig_refcount > 0);
02332       real->sig_refcount += 1;
02333       return TRUE;
02334     }
02335 
02336   str = dbus_new (DBusString, 1);
02337   if (str == NULL)
02338     return FALSE;
02339 
02340   if (!_dbus_header_get_field_raw (&real->message->header,
02341                                    DBUS_HEADER_FIELD_SIGNATURE,
02342                                    &current_sig, &current_sig_pos))
02343     current_sig = NULL;
02344 
02345   if (current_sig)
02346     {
02347       int current_len;
02348 
02349       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02350       current_sig_pos += 1; /* move on to sig data */
02351 
02352       if (!_dbus_string_init_preallocated (str, current_len + 4))
02353         {
02354           dbus_free (str);
02355           return FALSE;
02356         }
02357 
02358       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02359                                   str, 0))
02360         {
02361           _dbus_string_free (str);
02362           dbus_free (str);
02363           return FALSE;
02364         }
02365     }
02366   else
02367     {
02368       if (!_dbus_string_init_preallocated (str, 4))
02369         {
02370           dbus_free (str);
02371           return FALSE;
02372         }
02373     }
02374 
02375   real->sig_refcount = 1;
02376 
02377   _dbus_type_writer_add_types (&real->u.writer,
02378                                str, _dbus_string_get_length (str));
02379   return TRUE;
02380 }
02381 
02391 static dbus_bool_t
02392 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02393 {
02394   DBusString *str;
02395   const char *v_STRING;
02396   dbus_bool_t retval;
02397 
02398   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02399   _dbus_assert (real->u.writer.type_str != NULL);
02400   _dbus_assert (real->sig_refcount > 0);
02401 
02402   real->sig_refcount -= 1;
02403 
02404   if (real->sig_refcount > 0)
02405     return TRUE;
02406   _dbus_assert (real->sig_refcount == 0);
02407 
02408   retval = TRUE;
02409 
02410   str = real->u.writer.type_str;
02411 
02412   v_STRING = _dbus_string_get_const_data (str);
02413   if (!_dbus_header_set_field_basic (&real->message->header,
02414                                      DBUS_HEADER_FIELD_SIGNATURE,
02415                                      DBUS_TYPE_SIGNATURE,
02416                                      &v_STRING))
02417     retval = FALSE;
02418 
02419   _dbus_type_writer_remove_types (&real->u.writer);
02420   _dbus_string_free (str);
02421   dbus_free (str);
02422 
02423   return retval;
02424 }
02425 
02433 static void
02434 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02435 {
02436   DBusString *str;
02437 
02438   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02439   _dbus_assert (real->u.writer.type_str != NULL);
02440   _dbus_assert (real->sig_refcount > 0);
02441 
02442   real->sig_refcount -= 1;
02443 
02444   if (real->sig_refcount > 0)
02445     return;
02446   _dbus_assert (real->sig_refcount == 0);
02447 
02448   str = real->u.writer.type_str;
02449 
02450   _dbus_type_writer_remove_types (&real->u.writer);
02451   _dbus_string_free (str);
02452   dbus_free (str);
02453 }
02454 
02455 #ifndef DBUS_DISABLE_CHECKS
02456 static dbus_bool_t
02457 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02458 {
02459   if (!_dbus_message_iter_check (iter))
02460     return FALSE;
02461 
02462   if (iter->message->locked)
02463     {
02464       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02465       return FALSE;
02466     }
02467 
02468   return TRUE;
02469 }
02470 #endif /* DBUS_DISABLE_CHECKS */
02471 
02472 #ifdef HAVE_UNIX_FD_PASSING
02473 static int *
02474 expand_fd_array(DBusMessage *m,
02475                 unsigned     n)
02476 {
02477   _dbus_assert(m);
02478 
02479   /* This makes space for adding n new fds to the array and returns a
02480      pointer to the place were the first fd should be put. */
02481 
02482   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02483     {
02484       unsigned k;
02485       int *p;
02486 
02487       /* Make twice as much space as necessary */
02488       k = (m->n_unix_fds + n) * 2;
02489 
02490       /* Allocate at least four */
02491       if (k < 4)
02492         k = 4;
02493 
02494       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02495       if (p == NULL)
02496         return NULL;
02497 
02498       m->unix_fds = p;
02499       m->n_unix_fds_allocated = k;
02500     }
02501 
02502   return m->unix_fds + m->n_unix_fds;
02503 }
02504 #endif
02505 
02525 dbus_bool_t
02526 dbus_message_iter_append_basic (DBusMessageIter *iter,
02527                                 int              type,
02528                                 const void      *value)
02529 {
02530   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02531   dbus_bool_t ret;
02532 
02533   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02534   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02535   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02536   _dbus_return_val_if_fail (value != NULL, FALSE);
02537 
02538 #ifndef DBUS_DISABLE_CHECKS
02539   switch (type)
02540     {
02541       const char * const *string_p;
02542       const dbus_bool_t *bool_p;
02543 
02544       case DBUS_TYPE_STRING:
02545         string_p = value;
02546         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02547         break;
02548 
02549       case DBUS_TYPE_OBJECT_PATH:
02550         string_p = value;
02551         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02552         break;
02553 
02554       case DBUS_TYPE_SIGNATURE:
02555         string_p = value;
02556         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02557         break;
02558 
02559       case DBUS_TYPE_BOOLEAN:
02560         bool_p = value;
02561         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02562         break;
02563 
02564       default:
02565           {
02566             /* nothing to check, all possible values are allowed */
02567           }
02568     }
02569 #endif
02570 
02571   if (!_dbus_message_iter_open_signature (real))
02572     return FALSE;
02573 
02574   if (type == DBUS_TYPE_UNIX_FD)
02575     {
02576 #ifdef HAVE_UNIX_FD_PASSING
02577       int *fds;
02578       dbus_uint32_t u;
02579 
02580       /* First step, include the fd in the fd list of this message */
02581       if (!(fds = expand_fd_array(real->message, 1)))
02582         return FALSE;
02583 
02584       *fds = _dbus_dup(*(int*) value, NULL);
02585       if (*fds < 0)
02586         return FALSE;
02587 
02588       u = real->message->n_unix_fds;
02589 
02590       /* Second step, write the index to the fd */
02591       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02592         _dbus_close(*fds, NULL);
02593         return FALSE;
02594       }
02595 
02596       real->message->n_unix_fds += 1;
02597       u += 1;
02598 
02599       /* Final step, update the header accordingly */
02600       ret = _dbus_header_set_field_basic (&real->message->header,
02601                                           DBUS_HEADER_FIELD_UNIX_FDS,
02602                                           DBUS_TYPE_UINT32,
02603                                           &u);
02604 
02605       /* If any of these operations fail the message is
02606          hosed. However, no memory or fds should be leaked since what
02607          has been added to message has been added to the message, and
02608          can hence be accounted for when the message is being
02609          freed. */
02610 #else
02611       ret = FALSE;
02612 #endif
02613     }
02614   else
02615     {
02616       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02617     }
02618 
02619   if (!_dbus_message_iter_close_signature (real))
02620     ret = FALSE;
02621 
02622   return ret;
02623 }
02624 
02664 dbus_bool_t
02665 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02666                                       int              element_type,
02667                                       const void      *value,
02668                                       int              n_elements)
02669 {
02670   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02671   dbus_bool_t ret;
02672 
02673   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02674   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02675   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02676   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02677   _dbus_return_val_if_fail (value != NULL, FALSE);
02678   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02679   _dbus_return_val_if_fail (n_elements <=
02680                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02681                             FALSE);
02682 
02683 #ifndef DBUS_DISABLE_CHECKS
02684   if (element_type == DBUS_TYPE_BOOLEAN)
02685     {
02686       const dbus_bool_t * const *bools = value;
02687       int i;
02688 
02689       for (i = 0; i < n_elements; i++)
02690         {
02691           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02692         }
02693     }
02694 #endif
02695 
02696   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02697 
02698   return ret;
02699 }
02700 
02722 dbus_bool_t
02723 dbus_message_iter_open_container (DBusMessageIter *iter,
02724                                   int              type,
02725                                   const char      *contained_signature,
02726                                   DBusMessageIter *sub)
02727 {
02728   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02729   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02730   DBusString contained_str;
02731 
02732   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02733   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02734   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02735   _dbus_return_val_if_fail (sub != NULL, FALSE);
02736   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02737                              contained_signature == NULL) ||
02738                             (type == DBUS_TYPE_DICT_ENTRY &&
02739                              contained_signature == NULL) ||
02740                             (type == DBUS_TYPE_VARIANT &&
02741                              contained_signature != NULL) ||
02742                             (type == DBUS_TYPE_ARRAY &&
02743                              contained_signature != NULL), FALSE);
02744   
02745   /* this would fail if the contained_signature is a dict entry, since
02746    * dict entries are invalid signatures standalone (they must be in
02747    * an array)
02748    */
02749   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02750                             (contained_signature == NULL ||
02751                              _dbus_check_is_valid_signature (contained_signature)),
02752                             FALSE);
02753 
02754   if (!_dbus_message_iter_open_signature (real))
02755     return FALSE;
02756 
02757   *real_sub = *real;
02758 
02759   if (contained_signature != NULL)
02760     {
02761       _dbus_string_init_const (&contained_str, contained_signature);
02762 
02763       return _dbus_type_writer_recurse (&real->u.writer,
02764                                         type,
02765                                         &contained_str, 0,
02766                                         &real_sub->u.writer);
02767     }
02768   else
02769     {
02770       return _dbus_type_writer_recurse (&real->u.writer,
02771                                         type,
02772                                         NULL, 0,
02773                                         &real_sub->u.writer);
02774     } 
02775 }
02776 
02777 
02791 dbus_bool_t
02792 dbus_message_iter_close_container (DBusMessageIter *iter,
02793                                    DBusMessageIter *sub)
02794 {
02795   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02796   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02797   dbus_bool_t ret;
02798 
02799   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02800   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02801   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02802   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02803 
02804   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02805                                      &real_sub->u.writer);
02806 
02807   if (!_dbus_message_iter_close_signature (real))
02808     ret = FALSE;
02809 
02810   return ret;
02811 }
02812 
02824 void
02825 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02826                                      DBusMessageIter *sub)
02827 {
02828   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02829   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02830 
02831   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02832   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02833   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02834   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02835 
02836   _dbus_message_iter_abandon_signature (real);
02837 }
02838 
02855 void
02856 dbus_message_set_no_reply (DBusMessage *message,
02857                            dbus_bool_t  no_reply)
02858 {
02859   _dbus_return_if_fail (message != NULL);
02860   _dbus_return_if_fail (!message->locked);
02861 
02862   _dbus_header_toggle_flag (&message->header,
02863                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02864                             no_reply);
02865 }
02866 
02874 dbus_bool_t
02875 dbus_message_get_no_reply (DBusMessage *message)
02876 {
02877   _dbus_return_val_if_fail (message != NULL, FALSE);
02878 
02879   return _dbus_header_get_flag (&message->header,
02880                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02881 }
02882 
02897 void
02898 dbus_message_set_auto_start (DBusMessage *message,
02899                              dbus_bool_t  auto_start)
02900 {
02901   _dbus_return_if_fail (message != NULL);
02902   _dbus_return_if_fail (!message->locked);
02903 
02904   _dbus_header_toggle_flag (&message->header,
02905                             DBUS_HEADER_FLAG_NO_AUTO_START,
02906                             !auto_start);
02907 }
02908 
02916 dbus_bool_t
02917 dbus_message_get_auto_start (DBusMessage *message)
02918 {
02919   _dbus_return_val_if_fail (message != NULL, FALSE);
02920 
02921   return !_dbus_header_get_flag (&message->header,
02922                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02923 }
02924 
02925 
02938 dbus_bool_t
02939 dbus_message_set_path (DBusMessage   *message,
02940                        const char    *object_path)
02941 {
02942   _dbus_return_val_if_fail (message != NULL, FALSE);
02943   _dbus_return_val_if_fail (!message->locked, FALSE);
02944   _dbus_return_val_if_fail (object_path == NULL ||
02945                             _dbus_check_is_valid_path (object_path),
02946                             FALSE);
02947 
02948   return set_or_delete_string_field (message,
02949                                      DBUS_HEADER_FIELD_PATH,
02950                                      DBUS_TYPE_OBJECT_PATH,
02951                                      object_path);
02952 }
02953 
02967 const char*
02968 dbus_message_get_path (DBusMessage   *message)
02969 {
02970   const char *v;
02971 
02972   _dbus_return_val_if_fail (message != NULL, NULL);
02973 
02974   v = NULL; /* in case field doesn't exist */
02975   _dbus_header_get_field_basic (&message->header,
02976                                 DBUS_HEADER_FIELD_PATH,
02977                                 DBUS_TYPE_OBJECT_PATH,
02978                                 (void *) &v);
02979   return v;
02980 }
02981 
02991 dbus_bool_t
02992 dbus_message_has_path (DBusMessage   *message,
02993                        const char    *path)
02994 {
02995   const char *msg_path;
02996   msg_path = dbus_message_get_path (message);
02997   
02998   if (msg_path == NULL)
02999     {
03000       if (path == NULL)
03001         return TRUE;
03002       else
03003         return FALSE;
03004     }
03005 
03006   if (path == NULL)
03007     return FALSE;
03008    
03009   if (strcmp (msg_path, path) == 0)
03010     return TRUE;
03011 
03012   return FALSE;
03013 }
03014 
03035 dbus_bool_t
03036 dbus_message_get_path_decomposed (DBusMessage   *message,
03037                                   char        ***path)
03038 {
03039   const char *v;
03040 
03041   _dbus_return_val_if_fail (message != NULL, FALSE);
03042   _dbus_return_val_if_fail (path != NULL, FALSE);
03043 
03044   *path = NULL;
03045 
03046   v = dbus_message_get_path (message);
03047   if (v != NULL)
03048     {
03049       if (!_dbus_decompose_path (v, strlen (v),
03050                                  path, NULL))
03051         return FALSE;
03052     }
03053   return TRUE;
03054 }
03055 
03069 dbus_bool_t
03070 dbus_message_set_interface (DBusMessage  *message,
03071                             const char   *interface)
03072 {
03073   _dbus_return_val_if_fail (message != NULL, FALSE);
03074   _dbus_return_val_if_fail (!message->locked, FALSE);
03075   _dbus_return_val_if_fail (interface == NULL ||
03076                             _dbus_check_is_valid_interface (interface),
03077                             FALSE);
03078 
03079   return set_or_delete_string_field (message,
03080                                      DBUS_HEADER_FIELD_INTERFACE,
03081                                      DBUS_TYPE_STRING,
03082                                      interface);
03083 }
03084 
03098 const char*
03099 dbus_message_get_interface (DBusMessage *message)
03100 {
03101   const char *v;
03102 
03103   _dbus_return_val_if_fail (message != NULL, NULL);
03104 
03105   v = NULL; /* in case field doesn't exist */
03106   _dbus_header_get_field_basic (&message->header,
03107                                 DBUS_HEADER_FIELD_INTERFACE,
03108                                 DBUS_TYPE_STRING,
03109                                 (void *) &v);
03110   return v;
03111 }
03112 
03120 dbus_bool_t
03121 dbus_message_has_interface (DBusMessage   *message,
03122                             const char    *interface)
03123 {
03124   const char *msg_interface;
03125   msg_interface = dbus_message_get_interface (message);
03126    
03127   if (msg_interface == NULL)
03128     {
03129       if (interface == NULL)
03130         return TRUE;
03131       else
03132         return FALSE;
03133     }
03134 
03135   if (interface == NULL)
03136     return FALSE;
03137      
03138   if (strcmp (msg_interface, interface) == 0)
03139     return TRUE;
03140 
03141   return FALSE;
03142 
03143 }
03144 
03157 dbus_bool_t
03158 dbus_message_set_member (DBusMessage  *message,
03159                          const char   *member)
03160 {
03161   _dbus_return_val_if_fail (message != NULL, FALSE);
03162   _dbus_return_val_if_fail (!message->locked, FALSE);
03163   _dbus_return_val_if_fail (member == NULL ||
03164                             _dbus_check_is_valid_member (member),
03165                             FALSE);
03166 
03167   return set_or_delete_string_field (message,
03168                                      DBUS_HEADER_FIELD_MEMBER,
03169                                      DBUS_TYPE_STRING,
03170                                      member);
03171 }
03172 
03184 const char*
03185 dbus_message_get_member (DBusMessage *message)
03186 {
03187   const char *v;
03188 
03189   _dbus_return_val_if_fail (message != NULL, NULL);
03190 
03191   v = NULL; /* in case field doesn't exist */
03192   _dbus_header_get_field_basic (&message->header,
03193                                 DBUS_HEADER_FIELD_MEMBER,
03194                                 DBUS_TYPE_STRING,
03195                                 (void *) &v);
03196   return v;
03197 }
03198 
03206 dbus_bool_t
03207 dbus_message_has_member (DBusMessage   *message,
03208                          const char    *member)
03209 {
03210   const char *msg_member;
03211   msg_member = dbus_message_get_member (message);
03212  
03213   if (msg_member == NULL)
03214     {
03215       if (member == NULL)
03216         return TRUE;
03217       else
03218         return FALSE;
03219     }
03220 
03221   if (member == NULL)
03222     return FALSE;
03223     
03224   if (strcmp (msg_member, member) == 0)
03225     return TRUE;
03226 
03227   return FALSE;
03228 
03229 }
03230 
03242 dbus_bool_t
03243 dbus_message_set_error_name (DBusMessage  *message,
03244                              const char   *error_name)
03245 {
03246   _dbus_return_val_if_fail (message != NULL, FALSE);
03247   _dbus_return_val_if_fail (!message->locked, FALSE);
03248   _dbus_return_val_if_fail (error_name == NULL ||
03249                             _dbus_check_is_valid_error_name (error_name),
03250                             FALSE);
03251 
03252   return set_or_delete_string_field (message,
03253                                      DBUS_HEADER_FIELD_ERROR_NAME,
03254                                      DBUS_TYPE_STRING,
03255                                      error_name);
03256 }
03257 
03268 const char*
03269 dbus_message_get_error_name (DBusMessage *message)
03270 {
03271   const char *v;
03272 
03273   _dbus_return_val_if_fail (message != NULL, NULL);
03274 
03275   v = NULL; /* in case field doesn't exist */
03276   _dbus_header_get_field_basic (&message->header,
03277                                 DBUS_HEADER_FIELD_ERROR_NAME,
03278                                 DBUS_TYPE_STRING,
03279                                 (void *) &v);
03280   return v;
03281 }
03282 
03296 dbus_bool_t
03297 dbus_message_set_destination (DBusMessage  *message,
03298                               const char   *destination)
03299 {
03300   _dbus_return_val_if_fail (message != NULL, FALSE);
03301   _dbus_return_val_if_fail (!message->locked, FALSE);
03302   _dbus_return_val_if_fail (destination == NULL ||
03303                             _dbus_check_is_valid_bus_name (destination),
03304                             FALSE);
03305 
03306   return set_or_delete_string_field (message,
03307                                      DBUS_HEADER_FIELD_DESTINATION,
03308                                      DBUS_TYPE_STRING,
03309                                      destination);
03310 }
03311 
03321 const char*
03322 dbus_message_get_destination (DBusMessage *message)
03323 {
03324   const char *v;
03325 
03326   _dbus_return_val_if_fail (message != NULL, NULL);
03327 
03328   v = NULL; /* in case field doesn't exist */
03329   _dbus_header_get_field_basic (&message->header,
03330                                 DBUS_HEADER_FIELD_DESTINATION,
03331                                 DBUS_TYPE_STRING,
03332                                 (void *) &v);
03333   return v;
03334 }
03335 
03350 dbus_bool_t
03351 dbus_message_set_sender (DBusMessage  *message,
03352                          const char   *sender)
03353 {
03354   _dbus_return_val_if_fail (message != NULL, FALSE);
03355   _dbus_return_val_if_fail (!message->locked, FALSE);
03356   _dbus_return_val_if_fail (sender == NULL ||
03357                             _dbus_check_is_valid_bus_name (sender),
03358                             FALSE);
03359 
03360   return set_or_delete_string_field (message,
03361                                      DBUS_HEADER_FIELD_SENDER,
03362                                      DBUS_TYPE_STRING,
03363                                      sender);
03364 }
03365 
03381 const char*
03382 dbus_message_get_sender (DBusMessage *message)
03383 {
03384   const char *v;
03385 
03386   _dbus_return_val_if_fail (message != NULL, NULL);
03387 
03388   v = NULL; /* in case field doesn't exist */
03389   _dbus_header_get_field_basic (&message->header,
03390                                 DBUS_HEADER_FIELD_SENDER,
03391                                 DBUS_TYPE_STRING,
03392                                 (void *) &v);
03393   return v;
03394 }
03395 
03414 const char*
03415 dbus_message_get_signature (DBusMessage *message)
03416 {
03417   const DBusString *type_str;
03418   int type_pos;
03419 
03420   _dbus_return_val_if_fail (message != NULL, NULL);
03421 
03422   get_const_signature (&message->header, &type_str, &type_pos);
03423 
03424   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03425 }
03426 
03427 static dbus_bool_t
03428 _dbus_message_has_type_interface_member (DBusMessage *message,
03429                                          int          type,
03430                                          const char  *interface,
03431                                          const char  *member)
03432 {
03433   const char *n;
03434 
03435   _dbus_assert (message != NULL);
03436   _dbus_assert (interface != NULL);
03437   _dbus_assert (member != NULL);
03438 
03439   if (dbus_message_get_type (message) != type)
03440     return FALSE;
03441 
03442   /* Optimize by checking the short member name first
03443    * instead of the longer interface name
03444    */
03445 
03446   n = dbus_message_get_member (message);
03447 
03448   if (n && strcmp (n, member) == 0)
03449     {
03450       n = dbus_message_get_interface (message);
03451 
03452       if (n == NULL || strcmp (n, interface) == 0)
03453         return TRUE;
03454     }
03455 
03456   return FALSE;
03457 }
03458 
03473 dbus_bool_t
03474 dbus_message_is_method_call (DBusMessage *message,
03475                              const char  *interface,
03476                              const char  *method)
03477 {
03478   _dbus_return_val_if_fail (message != NULL, FALSE);
03479   _dbus_return_val_if_fail (interface != NULL, FALSE);
03480   _dbus_return_val_if_fail (method != NULL, FALSE);
03481   /* don't check that interface/method are valid since it would be
03482    * expensive, and not catch many common errors
03483    */
03484 
03485   return _dbus_message_has_type_interface_member (message,
03486                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03487                                                   interface, method);
03488 }
03489 
03501 dbus_bool_t
03502 dbus_message_is_signal (DBusMessage *message,
03503                         const char  *interface,
03504                         const char  *signal_name)
03505 {
03506   _dbus_return_val_if_fail (message != NULL, FALSE);
03507   _dbus_return_val_if_fail (interface != NULL, FALSE);
03508   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03509   /* don't check that interface/name are valid since it would be
03510    * expensive, and not catch many common errors
03511    */
03512 
03513   return _dbus_message_has_type_interface_member (message,
03514                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03515                                                   interface, signal_name);
03516 }
03517 
03528 dbus_bool_t
03529 dbus_message_is_error (DBusMessage *message,
03530                        const char  *error_name)
03531 {
03532   const char *n;
03533 
03534   _dbus_return_val_if_fail (message != NULL, FALSE);
03535   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03536   /* don't check that error_name is valid since it would be expensive,
03537    * and not catch many common errors
03538    */
03539 
03540   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03541     return FALSE;
03542 
03543   n = dbus_message_get_error_name (message);
03544 
03545   if (n && strcmp (n, error_name) == 0)
03546     return TRUE;
03547   else
03548     return FALSE;
03549 }
03550 
03561 dbus_bool_t
03562 dbus_message_has_destination (DBusMessage  *message,
03563                               const char   *name)
03564 {
03565   const char *s;
03566 
03567   _dbus_return_val_if_fail (message != NULL, FALSE);
03568   _dbus_return_val_if_fail (name != NULL, FALSE);
03569   /* don't check that name is valid since it would be expensive, and
03570    * not catch many common errors
03571    */
03572 
03573   s = dbus_message_get_destination (message);
03574 
03575   if (s && strcmp (s, name) == 0)
03576     return TRUE;
03577   else
03578     return FALSE;
03579 }
03580 
03596 dbus_bool_t
03597 dbus_message_has_sender (DBusMessage  *message,
03598                          const char   *name)
03599 {
03600   const char *s;
03601 
03602   _dbus_return_val_if_fail (message != NULL, FALSE);
03603   _dbus_return_val_if_fail (name != NULL, FALSE);
03604   /* don't check that name is valid since it would be expensive, and
03605    * not catch many common errors
03606    */
03607 
03608   s = dbus_message_get_sender (message);
03609 
03610   if (s && strcmp (s, name) == 0)
03611     return TRUE;
03612   else
03613     return FALSE;
03614 }
03615 
03625 dbus_bool_t
03626 dbus_message_has_signature (DBusMessage   *message,
03627                             const char    *signature)
03628 {
03629   const char *s;
03630 
03631   _dbus_return_val_if_fail (message != NULL, FALSE);
03632   _dbus_return_val_if_fail (signature != NULL, FALSE);
03633   /* don't check that signature is valid since it would be expensive,
03634    * and not catch many common errors
03635    */
03636 
03637   s = dbus_message_get_signature (message);
03638 
03639   if (s && strcmp (s, signature) == 0)
03640     return TRUE;
03641   else
03642     return FALSE;
03643 }
03644 
03667 dbus_bool_t
03668 dbus_set_error_from_message (DBusError   *error,
03669                              DBusMessage *message)
03670 {
03671   const char *str;
03672 
03673   _dbus_return_val_if_fail (message != NULL, FALSE);
03674   _dbus_return_val_if_error_is_set (error, FALSE);
03675 
03676   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03677     return FALSE;
03678 
03679   str = NULL;
03680   dbus_message_get_args (message, NULL,
03681                          DBUS_TYPE_STRING, &str,
03682                          DBUS_TYPE_INVALID);
03683 
03684   dbus_set_error (error, dbus_message_get_error_name (message),
03685                   str ? "%s" : NULL, str);
03686 
03687   return TRUE;
03688 }
03689 
03696 dbus_bool_t
03697 dbus_message_contains_unix_fds(DBusMessage *message)
03698 {
03699 #ifdef HAVE_UNIX_FD_PASSING
03700   _dbus_assert(message);
03701 
03702   return message->n_unix_fds > 0;
03703 #else
03704   return FALSE;
03705 #endif
03706 }
03707 
03726 #define INITIAL_LOADER_DATA_LEN 32
03727 
03734 DBusMessageLoader*
03735 _dbus_message_loader_new (void)
03736 {
03737   DBusMessageLoader *loader;
03738 
03739   loader = dbus_new0 (DBusMessageLoader, 1);
03740   if (loader == NULL)
03741     return NULL;
03742   
03743   loader->refcount = 1;
03744 
03745   loader->corrupted = FALSE;
03746   loader->corruption_reason = DBUS_VALID;
03747 
03748   /* this can be configured by the app, but defaults to the protocol max */
03749   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03750 
03751   /* We set a very relatively conservative default here since due to how
03752   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03753   number of unix fds we want to receive in advance. A
03754   try-and-reallocate loop is not possible. */
03755   loader->max_message_unix_fds = 1024;
03756 
03757   if (!_dbus_string_init (&loader->data))
03758     {
03759       dbus_free (loader);
03760       return NULL;
03761     }
03762 
03763   /* preallocate the buffer for speed, ignore failure */
03764   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03765   _dbus_string_set_length (&loader->data, 0);
03766 
03767 #ifdef HAVE_UNIX_FD_PASSING
03768   loader->unix_fds = NULL;
03769   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03770   loader->unix_fds_outstanding = FALSE;
03771 #endif
03772 
03773   return loader;
03774 }
03775 
03782 DBusMessageLoader *
03783 _dbus_message_loader_ref (DBusMessageLoader *loader)
03784 {
03785   loader->refcount += 1;
03786 
03787   return loader;
03788 }
03789 
03796 void
03797 _dbus_message_loader_unref (DBusMessageLoader *loader)
03798 {
03799   loader->refcount -= 1;
03800   if (loader->refcount == 0)
03801     {
03802 #ifdef HAVE_UNIX_FD_PASSING
03803       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
03804       dbus_free(loader->unix_fds);
03805 #endif
03806       _dbus_list_foreach (&loader->messages,
03807                           (DBusForeachFunction) dbus_message_unref,
03808                           NULL);
03809       _dbus_list_clear (&loader->messages);
03810       _dbus_string_free (&loader->data);
03811       dbus_free (loader);
03812     }
03813 }
03814 
03833 void
03834 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03835                                  DBusString        **buffer)
03836 {
03837   _dbus_assert (!loader->buffer_outstanding);
03838 
03839   *buffer = &loader->data;
03840 
03841   loader->buffer_outstanding = TRUE;
03842 }
03843 
03854 void
03855 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03856                                     DBusString         *buffer,
03857                                     int                 bytes_read)
03858 {
03859   _dbus_assert (loader->buffer_outstanding);
03860   _dbus_assert (buffer == &loader->data);
03861 
03862   loader->buffer_outstanding = FALSE;
03863 }
03864 
03875 dbus_bool_t
03876 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
03877                                   int               **fds,
03878                                   unsigned           *max_n_fds)
03879 {
03880 #ifdef HAVE_UNIX_FD_PASSING
03881   _dbus_assert (!loader->unix_fds_outstanding);
03882 
03883   /* Allocate space where we can put the fds we read. We allocate
03884      space for max_message_unix_fds since this is an
03885      upper limit how many fds can be received within a single
03886      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
03887      we are allocating the maximum possible array size right from the
03888      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
03889      there is no better way. */
03890 
03891   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
03892     {
03893       int *a = dbus_realloc(loader->unix_fds,
03894                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
03895 
03896       if (!a)
03897         return FALSE;
03898 
03899       loader->unix_fds = a;
03900       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
03901     }
03902 
03903   *fds = loader->unix_fds + loader->n_unix_fds;
03904   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
03905 
03906   loader->unix_fds_outstanding = TRUE;
03907   return TRUE;
03908 #else
03909   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03910   return FALSE;
03911 #endif
03912 }
03913 
03924 void
03925 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
03926                                      int                *fds,
03927                                      unsigned            n_fds)
03928 {
03929 #ifdef HAVE_UNIX_FD_PASSING
03930   _dbus_assert(loader->unix_fds_outstanding);
03931   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
03932   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
03933 
03934   loader->n_unix_fds += n_fds;
03935   loader->unix_fds_outstanding = FALSE;
03936 #else
03937   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03938 #endif
03939 }
03940 
03941 /*
03942  * FIXME when we move the header out of the buffer, that memmoves all
03943  * buffered messages. Kind of crappy.
03944  *
03945  * Also we copy the header and body, which is kind of crappy.  To
03946  * avoid this, we have to allow header and body to be in a single
03947  * memory block, which is good for messages we read and bad for
03948  * messages we are creating. But we could move_len() the buffer into
03949  * this single memory block, and move_len() will just swap the buffers
03950  * if you're moving the entire buffer replacing the dest string.
03951  *
03952  * We could also have the message loader tell the transport how many
03953  * bytes to read; so it would first ask for some arbitrary number like
03954  * 256, then if the message was incomplete it would use the
03955  * header/body len to ask for exactly the size of the message (or
03956  * blocks the size of a typical kernel buffer for the socket). That
03957  * way we don't get trailing bytes in the buffer that have to be
03958  * memmoved. Though I suppose we also don't have a chance of reading a
03959  * bunch of small messages at once, so the optimization may be stupid.
03960  *
03961  * Another approach would be to keep a "start" index into
03962  * loader->data and only delete it occasionally, instead of after
03963  * each message is loaded.
03964  *
03965  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03966  */
03967 static dbus_bool_t
03968 load_message (DBusMessageLoader *loader,
03969               DBusMessage       *message,
03970               int                byte_order,
03971               int                fields_array_len,
03972               int                header_len,
03973               int                body_len)
03974 {
03975   dbus_bool_t oom;
03976   DBusValidity validity;
03977   const DBusString *type_str;
03978   int type_pos;
03979   DBusValidationMode mode;
03980   dbus_uint32_t n_unix_fds = 0;
03981 
03982   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03983   
03984   oom = FALSE;
03985 
03986 #if 0
03987   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03988 #endif
03989 
03990   /* 1. VALIDATE AND COPY OVER HEADER */
03991   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03992   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03993 
03994   if (!_dbus_header_load (&message->header,
03995                           mode,
03996                           &validity,
03997                           byte_order,
03998                           fields_array_len,
03999                           header_len,
04000                           body_len,
04001                           &loader->data, 0,
04002                           _dbus_string_get_length (&loader->data)))
04003     {
04004       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
04005 
04006       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
04007          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
04008       _dbus_assert (validity != DBUS_VALID);
04009 
04010       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
04011         oom = TRUE;
04012       else
04013         {
04014           loader->corrupted = TRUE;
04015           loader->corruption_reason = validity;
04016         }
04017       goto failed;
04018     }
04019 
04020   _dbus_assert (validity == DBUS_VALID);
04021 
04022   message->byte_order = byte_order;
04023 
04024   /* 2. VALIDATE BODY */
04025   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04026     {
04027       get_const_signature (&message->header, &type_str, &type_pos);
04028       
04029       /* Because the bytes_remaining arg is NULL, this validates that the
04030        * body is the right length
04031        */
04032       validity = _dbus_validate_body_with_reason (type_str,
04033                                                   type_pos,
04034                                                   byte_order,
04035                                                   NULL,
04036                                                   &loader->data,
04037                                                   header_len,
04038                                                   body_len);
04039       if (validity != DBUS_VALID)
04040         {
04041           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04042 
04043           loader->corrupted = TRUE;
04044           loader->corruption_reason = validity;
04045           
04046           goto failed;
04047         }
04048     }
04049 
04050   /* 3. COPY OVER UNIX FDS */
04051   _dbus_header_get_field_basic(&message->header,
04052                                DBUS_HEADER_FIELD_UNIX_FDS,
04053                                DBUS_TYPE_UINT32,
04054                                &n_unix_fds);
04055 
04056 #ifdef HAVE_UNIX_FD_PASSING
04057 
04058   if (n_unix_fds > loader->n_unix_fds)
04059     {
04060       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04061                     n_unix_fds, loader->n_unix_fds);
04062 
04063       loader->corrupted = TRUE;
04064       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04065       goto failed;
04066     }
04067 
04068   /* If this was a recycled message there might still be
04069      some memory allocated for the fds */
04070   dbus_free(message->unix_fds);
04071 
04072   if (n_unix_fds > 0)
04073     {
04074       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04075       if (message->unix_fds == NULL)
04076         {
04077           _dbus_verbose ("Failed to allocate file descriptor array\n");
04078           oom = TRUE;
04079           goto failed;
04080         }
04081 
04082       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04083       loader->n_unix_fds -= n_unix_fds;
04084       memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds);
04085     }
04086   else
04087     message->unix_fds = NULL;
04088 
04089 #else
04090 
04091   if (n_unix_fds > 0)
04092     {
04093       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04094                      "but that's not supported on our platform, disconnecting.\n");
04095 
04096       loader->corrupted = TRUE;
04097       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04098       goto failed;
04099     }
04100 
04101 #endif
04102 
04103   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04104 
04105   if (!_dbus_list_append (&loader->messages, message))
04106     {
04107       _dbus_verbose ("Failed to append new message to loader queue\n");
04108       oom = TRUE;
04109       goto failed;
04110     }
04111 
04112   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04113   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04114                 (header_len + body_len));
04115 
04116   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04117     {
04118       _dbus_verbose ("Failed to move body into new message\n");
04119       oom = TRUE;
04120       goto failed;
04121     }
04122 
04123   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04124 
04125   /* don't waste more than 2k of memory */
04126   _dbus_string_compact (&loader->data, 2048);
04127 
04128   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04129   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04130 
04131   _dbus_verbose ("Loaded message %p\n", message);
04132 
04133   _dbus_assert (!oom);
04134   _dbus_assert (!loader->corrupted);
04135   _dbus_assert (loader->messages != NULL);
04136   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04137 
04138   return TRUE;
04139 
04140  failed:
04141 
04142   /* Clean up */
04143 
04144   /* does nothing if the message isn't in the list */
04145   _dbus_list_remove_last (&loader->messages, message);
04146   
04147   if (oom)
04148     _dbus_assert (!loader->corrupted);
04149   else
04150     _dbus_assert (loader->corrupted);
04151 
04152   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04153 
04154   return FALSE;
04155 }
04156 
04171 dbus_bool_t
04172 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04173 {
04174   while (!loader->corrupted &&
04175          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04176     {
04177       DBusValidity validity;
04178       int byte_order, fields_array_len, header_len, body_len;
04179 
04180       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04181                                                &validity,
04182                                                &byte_order,
04183                                                &fields_array_len,
04184                                                &header_len,
04185                                                &body_len,
04186                                                &loader->data, 0,
04187                                                _dbus_string_get_length (&loader->data)))
04188         {
04189           DBusMessage *message;
04190 
04191           _dbus_assert (validity == DBUS_VALID);
04192 
04193           message = dbus_message_new_empty_header ();
04194           if (message == NULL)
04195             return FALSE;
04196 
04197           if (!load_message (loader, message,
04198                              byte_order, fields_array_len,
04199                              header_len, body_len))
04200             {
04201               dbus_message_unref (message);
04202               /* load_message() returns false if corrupted or OOM; if
04203                * corrupted then return TRUE for not OOM
04204                */
04205               return loader->corrupted;
04206             }
04207 
04208           _dbus_assert (loader->messages != NULL);
04209           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04210         }
04211       else
04212         {
04213           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04214                          validity);
04215           if (validity != DBUS_VALID)
04216             {
04217               loader->corrupted = TRUE;
04218               loader->corruption_reason = validity;
04219             }
04220           return TRUE;
04221         }
04222     }
04223 
04224   return TRUE;
04225 }
04226 
04234 DBusMessage*
04235 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04236 {
04237   if (loader->messages)
04238     return loader->messages->data;
04239   else
04240     return NULL;
04241 }
04242 
04251 DBusMessage*
04252 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04253 {
04254   return _dbus_list_pop_first (&loader->messages);
04255 }
04256 
04265 DBusList*
04266 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04267 {
04268   return _dbus_list_pop_first_link (&loader->messages);
04269 }
04270 
04277 void
04278 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04279                                            DBusList           *link)
04280 {
04281   _dbus_list_prepend_link (&loader->messages, link);
04282 }
04283 
04293 dbus_bool_t
04294 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04295 {
04296   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04297                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04298   return loader->corrupted;
04299 }
04300 
04307 DBusValidity
04308 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04309 {
04310   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04311                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04312 
04313   return loader->corruption_reason;
04314 }
04315 
04322 void
04323 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04324                                            long                size)
04325 {
04326   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04327     {
04328       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04329                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04330       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04331     }
04332   loader->max_message_size = size;
04333 }
04334 
04341 long
04342 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04343 {
04344   return loader->max_message_size;
04345 }
04346 
04353 void
04354 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04355                                                long                n)
04356 {
04357   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04358     {
04359       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04360                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04361       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04362     }
04363   loader->max_message_unix_fds = n;
04364 }
04365 
04372 long
04373 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04374 {
04375   return loader->max_message_unix_fds;
04376 }
04377 
04378 static DBusDataSlotAllocator slot_allocator;
04379 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
04380 
04395 dbus_bool_t
04396 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04397 {
04398   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04399                                           &_DBUS_LOCK_NAME (message_slots),
04400                                           slot_p);
04401 }
04402 
04414 void
04415 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04416 {
04417   _dbus_return_if_fail (*slot_p >= 0);
04418 
04419   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04420 }
04421 
04435 dbus_bool_t
04436 dbus_message_set_data (DBusMessage     *message,
04437                        dbus_int32_t     slot,
04438                        void            *data,
04439                        DBusFreeFunction free_data_func)
04440 {
04441   DBusFreeFunction old_free_func;
04442   void *old_data;
04443   dbus_bool_t retval;
04444 
04445   _dbus_return_val_if_fail (message != NULL, FALSE);
04446   _dbus_return_val_if_fail (slot >= 0, FALSE);
04447 
04448   retval = _dbus_data_slot_list_set (&slot_allocator,
04449                                      &message->slot_list,
04450                                      slot, data, free_data_func,
04451                                      &old_free_func, &old_data);
04452 
04453   if (retval)
04454     {
04455       /* Do the actual free outside the message lock */
04456       if (old_free_func)
04457         (* old_free_func) (old_data);
04458     }
04459 
04460   return retval;
04461 }
04462 
04471 void*
04472 dbus_message_get_data (DBusMessage   *message,
04473                        dbus_int32_t   slot)
04474 {
04475   void *res;
04476 
04477   _dbus_return_val_if_fail (message != NULL, NULL);
04478 
04479   res = _dbus_data_slot_list_get (&slot_allocator,
04480                                   &message->slot_list,
04481                                   slot);
04482 
04483   return res;
04484 }
04485 
04499 int
04500 dbus_message_type_from_string (const char *type_str)
04501 {
04502   if (strcmp (type_str, "method_call") == 0)
04503     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04504   if (strcmp (type_str, "method_return") == 0)
04505     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04506   else if (strcmp (type_str, "signal") == 0)
04507     return DBUS_MESSAGE_TYPE_SIGNAL;
04508   else if (strcmp (type_str, "error") == 0)
04509     return DBUS_MESSAGE_TYPE_ERROR;
04510   else
04511     return DBUS_MESSAGE_TYPE_INVALID;
04512 }
04513 
04527 const char *
04528 dbus_message_type_to_string (int type)
04529 {
04530   switch (type)
04531     {
04532     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04533       return "method_call";
04534     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04535       return "method_return";
04536     case DBUS_MESSAGE_TYPE_SIGNAL:
04537       return "signal";
04538     case DBUS_MESSAGE_TYPE_ERROR:
04539       return "error";
04540     default:
04541       return "invalid";
04542     }
04543 }
04544 
04557 dbus_bool_t
04558 dbus_message_marshal (DBusMessage  *msg,
04559                       char        **marshalled_data_p,
04560                       int          *len_p)
04561 {
04562   DBusString tmp;
04563   dbus_bool_t was_locked;
04564 
04565   _dbus_return_val_if_fail (msg != NULL, FALSE);
04566   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04567   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04568   
04569   if (!_dbus_string_init (&tmp))
04570     return FALSE;
04571 
04572   /* Ensure the message is locked, to ensure the length header is filled in. */
04573   was_locked = msg->locked;
04574 
04575   if (!was_locked)
04576     dbus_message_lock (msg);
04577 
04578   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04579     goto fail;
04580 
04581   *len_p = _dbus_string_get_length (&tmp);
04582 
04583   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04584     goto fail;
04585 
04586   *len_p = _dbus_string_get_length (&tmp);
04587 
04588   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04589     goto fail;
04590 
04591   _dbus_string_free (&tmp);
04592 
04593   if (!was_locked)
04594     msg->locked = FALSE;
04595 
04596   return TRUE;
04597 
04598  fail:
04599   _dbus_string_free (&tmp);
04600 
04601   if (!was_locked)
04602     msg->locked = FALSE;
04603 
04604   return FALSE;
04605 }
04606 
04619 DBusMessage *
04620 dbus_message_demarshal (const char *str,
04621                         int         len,
04622                         DBusError  *error)
04623 {
04624   DBusMessageLoader *loader;
04625   DBusString *buffer;
04626   DBusMessage *msg;
04627 
04628   _dbus_return_val_if_fail (str != NULL, NULL);
04629 
04630   loader = _dbus_message_loader_new ();
04631 
04632   if (loader == NULL)
04633     return NULL;
04634 
04635   _dbus_message_loader_get_buffer (loader, &buffer);
04636   _dbus_string_append_len (buffer, str, len);
04637   _dbus_message_loader_return_buffer (loader, buffer, len);
04638 
04639   if (!_dbus_message_loader_queue_messages (loader))
04640     goto fail_oom;
04641 
04642   if (_dbus_message_loader_get_is_corrupted (loader))
04643     goto fail_corrupt;
04644 
04645   msg = _dbus_message_loader_pop_message (loader);
04646 
04647   if (!msg)
04648     goto fail_oom;
04649 
04650   _dbus_message_loader_unref (loader);
04651   return msg;
04652 
04653  fail_corrupt:
04654   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04655                   _dbus_validity_to_error_message (loader->corruption_reason));
04656   _dbus_message_loader_unref (loader);
04657   return NULL;
04658 
04659  fail_oom:
04660   _DBUS_SET_OOM (error);
04661   _dbus_message_loader_unref (loader);
04662   return NULL;
04663 }
04664 
04678 int 
04679 dbus_message_demarshal_bytes_needed(const char *buf, 
04680                                     int         len)
04681 {
04682   DBusString str;
04683   int byte_order, fields_array_len, header_len, body_len;
04684   DBusValidity validity = DBUS_VALID;
04685   int have_message;
04686 
04687   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04688     return 0;
04689 
04690   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04691     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04692   _dbus_string_init_const_len (&str, buf, len);
04693   
04694   validity = DBUS_VALID;
04695   have_message
04696     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04697                                           &validity, &byte_order,
04698                                           &fields_array_len,
04699                                           &header_len,
04700                                           &body_len,
04701                                           &str, 0,
04702                                           len);
04703   _dbus_string_free (&str);
04704 
04705   if (validity == DBUS_VALID)
04706     {
04707       _dbus_assert (have_message || (header_len + body_len) > len);
04708       return header_len + body_len;
04709     }
04710   else
04711     {
04712       return -1; /* broken! */
04713     }
04714 }
04715 
04718 /* tests in dbus-message-util.c */

Generated on Fri Jul 11 2014 20:41:46 for D-Bus by  doxygen 1.7.1