D-Bus  1.6.30
dbus-message.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-validate.h"
00029 #include "dbus-marshal-byteswap.h"
00030 #include "dbus-marshal-header.h"
00031 #include "dbus-signature.h"
00032 #include "dbus-message-private.h"
00033 #include "dbus-object-tree.h"
00034 #include "dbus-memory.h"
00035 #include "dbus-list.h"
00036 #include "dbus-threads-internal.h"
00037 #ifdef HAVE_UNIX_FD_PASSING
00038 #include "dbus-sysdeps.h"
00039 #include "dbus-sysdeps-unix.h"
00040 #endif
00041 
00042 #include <string.h>
00043 
00044 #define _DBUS_TYPE_IS_STRINGLIKE(type) \
00045   (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
00046    type == DBUS_TYPE_OBJECT_PATH)
00047 
00048 static void dbus_message_finalize (DBusMessage *message);
00049 
00060 #ifdef DBUS_BUILD_TESTS
00061 static dbus_bool_t
00062 _dbus_enable_message_cache (void)
00063 {
00064   static int enabled = -1;
00065 
00066   if (enabled < 0)
00067     {
00068       const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
00069 
00070       enabled = TRUE;
00071 
00072       if (s && *s)
00073         {
00074           if (*s == '0')
00075             enabled = FALSE;
00076           else if (*s == '1')
00077             enabled = TRUE;
00078           else
00079             _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
00080                 s);
00081         }
00082     }
00083 
00084   return enabled;
00085 }
00086 #else
00087     /* constant expression, should be optimized away */
00088 #   define _dbus_enable_message_cache() (TRUE)
00089 #endif
00090 
00091 #ifndef _dbus_message_trace_ref
00092 void
00093 _dbus_message_trace_ref (DBusMessage *message,
00094                          int          old_refcount,
00095                          int          new_refcount,
00096                          const char  *why)
00097 {
00098   static int enabled = -1;
00099 
00100   _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
00101       "DBUS_MESSAGE_TRACE", &enabled);
00102 }
00103 #endif
00104 
00105 /* Not thread locked, but strictly const/read-only so should be OK
00106  */
00108 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
00109 
00110 /* these have wacky values to help trap uninitialized iterators;
00111  * but has to fit in 3 bits
00112  */
00113 enum {
00114   DBUS_MESSAGE_ITER_TYPE_READER = 3,
00115   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
00116 };
00117 
00119 typedef struct DBusMessageRealIter DBusMessageRealIter;
00120 
00126 struct DBusMessageRealIter
00127 {
00128   DBusMessage *message; 
00129   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 
00130   dbus_uint32_t iter_type : 3;      
00131   dbus_uint32_t sig_refcount : 8;   
00132   union
00133   {
00134     DBusTypeWriter writer; 
00135     DBusTypeReader reader; 
00136   } u; 
00137 };
00138 
00139 static void
00140 get_const_signature (DBusHeader        *header,
00141                      const DBusString **type_str_p,
00142                      int               *type_pos_p)
00143 {
00144   if (_dbus_header_get_field_raw (header,
00145                                   DBUS_HEADER_FIELD_SIGNATURE,
00146                                   type_str_p,
00147                                   type_pos_p))
00148     {
00149       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00150     }
00151   else
00152     {
00153       *type_str_p = &_dbus_empty_signature_str;
00154       *type_pos_p = 0;
00155     }
00156 }
00157 
00163 static void
00164 _dbus_message_byteswap (DBusMessage *message)
00165 {
00166   const DBusString *type_str;
00167   int type_pos;
00168   char byte_order;
00169 
00170   byte_order = _dbus_header_get_byte_order (&message->header);
00171 
00172   if (byte_order == DBUS_COMPILER_BYTE_ORDER)
00173     return;
00174 
00175   _dbus_verbose ("Swapping message into compiler byte order\n");
00176   
00177   get_const_signature (&message->header, &type_str, &type_pos);
00178   
00179   _dbus_marshal_byteswap (type_str, type_pos,
00180                           byte_order,
00181                           DBUS_COMPILER_BYTE_ORDER,
00182                           &message->body, 0);
00183 
00184   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00185   _dbus_assert (_dbus_header_get_byte_order (&message->header) ==
00186                 DBUS_COMPILER_BYTE_ORDER);
00187 }
00188 
00195 #define ensure_byte_order(message) _dbus_message_byteswap (message)
00196 
00207 void
00208 _dbus_message_get_network_data (DBusMessage          *message,
00209                                 const DBusString    **header,
00210                                 const DBusString    **body)
00211 {
00212   _dbus_assert (message->locked);
00213 
00214   *header = &message->header.data;
00215   *body = &message->body;
00216 }
00217 
00227 void _dbus_message_get_unix_fds(DBusMessage *message,
00228                                 const int  **fds,
00229                                 unsigned    *n_fds)
00230 {
00231   _dbus_assert (message->locked);
00232 
00233 #ifdef HAVE_UNIX_FD_PASSING
00234   *fds = message->unix_fds;
00235   *n_fds = message->n_unix_fds;
00236 #else
00237   *fds = NULL;
00238   *n_fds = 0;
00239 #endif
00240 }
00241 
00253 void 
00254 dbus_message_set_serial (DBusMessage   *message,
00255                          dbus_uint32_t  serial)
00256 {
00257   _dbus_return_if_fail (message != NULL);
00258   _dbus_return_if_fail (!message->locked);
00259 
00260   _dbus_header_set_serial (&message->header, serial);
00261 }
00262 
00279 void
00280 _dbus_message_add_counter_link (DBusMessage  *message,
00281                                 DBusList     *link)
00282 {
00283   /* right now we don't recompute the delta when message
00284    * size changes, and that's OK for current purposes
00285    * I think, but could be important to change later.
00286    * Do recompute it whenever there are no outstanding counters,
00287    * since it's basically free.
00288    */
00289   if (message->counters == NULL)
00290     {
00291       message->size_counter_delta =
00292         _dbus_string_get_length (&message->header.data) +
00293         _dbus_string_get_length (&message->body);
00294 
00295 #ifdef HAVE_UNIX_FD_PASSING
00296       message->unix_fd_counter_delta = message->n_unix_fds;
00297 #endif
00298 
00299 #if 0
00300       _dbus_verbose ("message has size %ld\n",
00301                      message->size_counter_delta);
00302 #endif
00303     }
00304 
00305   _dbus_list_append_link (&message->counters, link);
00306 
00307   _dbus_counter_adjust_size (link->data, message->size_counter_delta);
00308 
00309 #ifdef HAVE_UNIX_FD_PASSING
00310   _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
00311 #endif
00312 }
00313 
00328 dbus_bool_t
00329 _dbus_message_add_counter (DBusMessage *message,
00330                            DBusCounter *counter)
00331 {
00332   DBusList *link;
00333 
00334   link = _dbus_list_alloc_link (counter);
00335   if (link == NULL)
00336     return FALSE;
00337 
00338   _dbus_counter_ref (counter);
00339   _dbus_message_add_counter_link (message, link);
00340 
00341   return TRUE;
00342 }
00343 
00351 void
00352 _dbus_message_remove_counter (DBusMessage  *message,
00353                               DBusCounter  *counter)
00354 {
00355   DBusList *link;
00356 
00357   link = _dbus_list_find_last (&message->counters,
00358                                counter);
00359   _dbus_assert (link != NULL);
00360 
00361   _dbus_list_remove_link (&message->counters, link);
00362 
00363   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00364 
00365 #ifdef HAVE_UNIX_FD_PASSING
00366   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00367 #endif
00368 
00369   _dbus_counter_notify (counter);
00370   _dbus_counter_unref (counter);
00371 }
00372 
00383 void
00384 dbus_message_lock (DBusMessage  *message)
00385 {
00386   if (!message->locked)
00387     {
00388       _dbus_header_update_lengths (&message->header,
00389                                    _dbus_string_get_length (&message->body));
00390 
00391       /* must have a signature if you have a body */
00392       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00393                     dbus_message_get_signature (message) != NULL);
00394 
00395       message->locked = TRUE;
00396     }
00397 }
00398 
00399 static dbus_bool_t
00400 set_or_delete_string_field (DBusMessage *message,
00401                             int          field,
00402                             int          typecode,
00403                             const char  *value)
00404 {
00405   if (value == NULL)
00406     return _dbus_header_delete_field (&message->header, field);
00407   else
00408     return _dbus_header_set_field_basic (&message->header,
00409                                          field,
00410                                          typecode,
00411                                          &value);
00412 }
00413 
00414 #if 0
00415 /* Probably we don't need to use this */
00439 static dbus_bool_t
00440 _dbus_message_set_signature (DBusMessage *message,
00441                              const char  *signature)
00442 {
00443   _dbus_return_val_if_fail (message != NULL, FALSE);
00444   _dbus_return_val_if_fail (!message->locked, FALSE);
00445   _dbus_return_val_if_fail (signature == NULL ||
00446                             _dbus_check_is_valid_signature (signature));
00447   /* can't delete the signature if you have a message body */
00448   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00449                             signature != NULL);
00450 
00451   return set_or_delete_string_field (message,
00452                                      DBUS_HEADER_FIELD_SIGNATURE,
00453                                      DBUS_TYPE_SIGNATURE,
00454                                      signature);
00455 }
00456 #endif
00457 
00458 /* Message Cache
00459  *
00460  * We cache some DBusMessage to reduce the overhead of allocating
00461  * them.  In my profiling this consistently made about an 8%
00462  * difference.  It avoids the malloc for the message, the malloc for
00463  * the slot list, the malloc for the header string and body string,
00464  * and the associated free() calls. It does introduce another global
00465  * lock which could be a performance issue in certain cases.
00466  *
00467  * For the echo client/server the round trip time goes from around
00468  * .000077 to .000069 with the message cache on my laptop. The sysprof
00469  * change is as follows (numbers are cumulative percentage):
00470  *
00471  *  with message cache implemented as array as it is now (0.000069 per):
00472  *    new_empty_header           1.46
00473  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00474  *      mutex_unlock             0.25
00475  *      self                     0.41
00476  *    unref                      2.24
00477  *      self                     0.68
00478  *      list_clear               0.43
00479  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00480  *      mutex_unlock             0.25
00481  *
00482  *  with message cache implemented as list (0.000070 per roundtrip):
00483  *    new_empty_header           2.72
00484  *      list_pop_first           1.88
00485  *    unref                      3.3
00486  *      list_prepend             1.63
00487  *
00488  * without cache (0.000077 per roundtrip):
00489  *    new_empty_header           6.7
00490  *      string_init_preallocated 3.43
00491  *        dbus_malloc            2.43
00492  *      dbus_malloc0             2.59
00493  *
00494  *    unref                      4.02
00495  *      string_free              1.82
00496  *        dbus_free              1.63
00497  *      dbus_free                0.71
00498  *
00499  * If you implement the message_cache with a list, the primary reason
00500  * it's slower is that you add another thread lock (on the DBusList
00501  * mempool).
00502  */
00503 
00505 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00506 
00508 #define MAX_MESSAGE_CACHE_SIZE    5
00509 
00510 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00511 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00512 static int message_cache_count = 0;
00513 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00514 
00515 static void
00516 dbus_message_cache_shutdown (void *data)
00517 {
00518   int i;
00519 
00520   _DBUS_LOCK (message_cache);
00521 
00522   i = 0;
00523   while (i < MAX_MESSAGE_CACHE_SIZE)
00524     {
00525       if (message_cache[i])
00526         dbus_message_finalize (message_cache[i]);
00527 
00528       ++i;
00529     }
00530 
00531   message_cache_count = 0;
00532   message_cache_shutdown_registered = FALSE;
00533 
00534   _DBUS_UNLOCK (message_cache);
00535 }
00536 
00544 static DBusMessage*
00545 dbus_message_get_cached (void)
00546 {
00547   DBusMessage *message;
00548   int i;
00549 
00550   message = NULL;
00551 
00552   _DBUS_LOCK (message_cache);
00553 
00554   _dbus_assert (message_cache_count >= 0);
00555 
00556   if (message_cache_count == 0)
00557     {
00558       _DBUS_UNLOCK (message_cache);
00559       return NULL;
00560     }
00561 
00562   /* This is not necessarily true unless count > 0, and
00563    * message_cache is uninitialized until the shutdown is
00564    * registered
00565    */
00566   _dbus_assert (message_cache_shutdown_registered);
00567 
00568   i = 0;
00569   while (i < MAX_MESSAGE_CACHE_SIZE)
00570     {
00571       if (message_cache[i])
00572         {
00573           message = message_cache[i];
00574           message_cache[i] = NULL;
00575           message_cache_count -= 1;
00576           break;
00577         }
00578       ++i;
00579     }
00580   _dbus_assert (message_cache_count >= 0);
00581   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00582   _dbus_assert (message != NULL);
00583 
00584   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00585 
00586   _dbus_assert (message->counters == NULL);
00587   
00588   _DBUS_UNLOCK (message_cache);
00589 
00590   return message;
00591 }
00592 
00593 #ifdef HAVE_UNIX_FD_PASSING
00594 static void
00595 close_unix_fds(int *fds, unsigned *n_fds)
00596 {
00597   DBusError e;
00598   int i;
00599 
00600   if (*n_fds <= 0)
00601     return;
00602 
00603   dbus_error_init(&e);
00604 
00605   for (i = 0; i < *n_fds; i++)
00606     {
00607       if (!_dbus_close(fds[i], &e))
00608         {
00609           _dbus_warn("Failed to close file descriptor: %s\n", e.message);
00610           dbus_error_free(&e);
00611         }
00612     }
00613 
00614   *n_fds = 0;
00615 
00616   /* We don't free the array here, in case we can recycle it later */
00617 }
00618 #endif
00619 
00620 static void
00621 free_counter (void *element,
00622               void *data)
00623 {
00624   DBusCounter *counter = element;
00625   DBusMessage *message = data;
00626 
00627   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00628 #ifdef HAVE_UNIX_FD_PASSING
00629   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00630 #endif
00631 
00632   _dbus_counter_notify (counter);
00633   _dbus_counter_unref (counter);
00634 }
00635 
00641 static void
00642 dbus_message_cache_or_finalize (DBusMessage *message)
00643 {
00644   dbus_bool_t was_cached;
00645   int i;
00646 
00647   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00648 
00649   /* This calls application code and has to be done first thing
00650    * without holding the lock
00651    */
00652   _dbus_data_slot_list_clear (&message->slot_list);
00653 
00654   _dbus_list_foreach (&message->counters,
00655                       free_counter, message);
00656   _dbus_list_clear (&message->counters);
00657 
00658 #ifdef HAVE_UNIX_FD_PASSING
00659   close_unix_fds(message->unix_fds, &message->n_unix_fds);
00660 #endif
00661 
00662   was_cached = FALSE;
00663 
00664   _DBUS_LOCK (message_cache);
00665 
00666   if (!message_cache_shutdown_registered)
00667     {
00668       _dbus_assert (message_cache_count == 0);
00669 
00670       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00671         goto out;
00672 
00673       i = 0;
00674       while (i < MAX_MESSAGE_CACHE_SIZE)
00675         {
00676           message_cache[i] = NULL;
00677           ++i;
00678         }
00679 
00680       message_cache_shutdown_registered = TRUE;
00681     }
00682 
00683   _dbus_assert (message_cache_count >= 0);
00684 
00685   if (!_dbus_enable_message_cache ())
00686     goto out;
00687 
00688   if ((_dbus_string_get_length (&message->header.data) +
00689        _dbus_string_get_length (&message->body)) >
00690       MAX_MESSAGE_SIZE_TO_CACHE)
00691     goto out;
00692 
00693   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00694     goto out;
00695 
00696   /* Find empty slot */
00697   i = 0;
00698   while (message_cache[i] != NULL)
00699     ++i;
00700 
00701   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00702 
00703   _dbus_assert (message_cache[i] == NULL);
00704   message_cache[i] = message;
00705   message_cache_count += 1;
00706   was_cached = TRUE;
00707 #ifndef DBUS_DISABLE_CHECKS
00708   message->in_cache = TRUE;
00709 #endif
00710 
00711  out:
00712   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00713 
00714   _DBUS_UNLOCK (message_cache);
00715   
00716   if (!was_cached)
00717     dbus_message_finalize (message);
00718 }
00719 
00720 #ifndef DBUS_DISABLE_CHECKS
00721 static dbus_bool_t
00722 _dbus_message_iter_check (DBusMessageRealIter *iter)
00723 {
00724   char byte_order;
00725 
00726   if (iter == NULL)
00727     {
00728       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00729       return FALSE;
00730     }
00731 
00732   byte_order = _dbus_header_get_byte_order (&iter->message->header);
00733 
00734   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00735     {
00736       if (iter->u.reader.byte_order != byte_order)
00737         {
00738           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00739           return FALSE;
00740         }
00741       /* because we swap the message into compiler order when you init an iter */
00742       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00743     }
00744   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00745     {
00746       if (iter->u.writer.byte_order != byte_order)
00747         {
00748           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00749           return FALSE;
00750         }
00751       /* because we swap the message into compiler order when you init an iter */
00752       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00753     }
00754   else
00755     {
00756       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00757       return FALSE;
00758     }
00759 
00760   if (iter->changed_stamp != iter->message->changed_stamp)
00761     {
00762       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00763       return FALSE;
00764     }
00765 
00766   return TRUE;
00767 }
00768 #endif /* DBUS_DISABLE_CHECKS */
00769 
00784 dbus_bool_t
00785 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00786                                     DBusError       *error,
00787                                     int              first_arg_type,
00788                                     va_list          var_args)
00789 {
00790   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00791   int spec_type, msg_type, i;
00792   dbus_bool_t retval;
00793 
00794   _dbus_assert (_dbus_message_iter_check (real));
00795 
00796   retval = FALSE;
00797 
00798   spec_type = first_arg_type;
00799   i = 0;
00800 
00801   while (spec_type != DBUS_TYPE_INVALID)
00802     {
00803       msg_type = dbus_message_iter_get_arg_type (iter);
00804 
00805       if (msg_type != spec_type)
00806         {
00807           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00808                           "Argument %d is specified to be of type \"%s\", but "
00809                           "is actually of type \"%s\"\n", i,
00810                           _dbus_type_to_string (spec_type),
00811                           _dbus_type_to_string (msg_type));
00812 
00813           goto out;
00814         }
00815 
00816       if (spec_type == DBUS_TYPE_UNIX_FD)
00817         {
00818 #ifdef HAVE_UNIX_FD_PASSING
00819           DBusBasicValue idx;
00820           int *pfd, nfd;
00821 
00822           pfd = va_arg (var_args, int*);
00823           _dbus_assert(pfd);
00824 
00825           _dbus_type_reader_read_basic(&real->u.reader, &idx);
00826 
00827           if (idx.u32 >= real->message->n_unix_fds)
00828             {
00829               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
00830                               "Message refers to file descriptor at index %i,"
00831                               "but has only %i descriptors attached.\n",
00832                               idx.u32,
00833                               real->message->n_unix_fds);
00834               goto out;
00835             }
00836 
00837           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
00838             goto out;
00839 
00840           *pfd = nfd;
00841 #else
00842           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00843                           "Platform does not support file desciptor passing.\n");
00844           goto out;
00845 #endif
00846         }
00847       else if (dbus_type_is_basic (spec_type))
00848         {
00849           DBusBasicValue *ptr;
00850 
00851           ptr = va_arg (var_args, DBusBasicValue*);
00852 
00853           _dbus_assert (ptr != NULL);
00854 
00855           _dbus_type_reader_read_basic (&real->u.reader,
00856                                         ptr);
00857         }
00858       else if (spec_type == DBUS_TYPE_ARRAY)
00859         {
00860           int element_type;
00861           int spec_element_type;
00862           const DBusBasicValue **ptr;
00863           int *n_elements_p;
00864           DBusTypeReader array;
00865 
00866           spec_element_type = va_arg (var_args, int);
00867           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00868 
00869           if (spec_element_type != element_type)
00870             {
00871               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00872                               "Argument %d is specified to be an array of \"%s\", but "
00873                               "is actually an array of \"%s\"\n",
00874                               i,
00875                               _dbus_type_to_string (spec_element_type),
00876                               _dbus_type_to_string (element_type));
00877 
00878               goto out;
00879             }
00880 
00881           if (dbus_type_is_fixed (spec_element_type) &&
00882               element_type != DBUS_TYPE_UNIX_FD)
00883             {
00884               ptr = va_arg (var_args, const DBusBasicValue**);
00885               n_elements_p = va_arg (var_args, int*);
00886 
00887               _dbus_assert (ptr != NULL);
00888               _dbus_assert (n_elements_p != NULL);
00889 
00890               _dbus_type_reader_recurse (&real->u.reader, &array);
00891 
00892               _dbus_type_reader_read_fixed_multi (&array,
00893                                                   (void *) ptr, n_elements_p);
00894             }
00895           else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
00896             {
00897               char ***str_array_p;
00898               int n_elements;
00899               char **str_array;
00900 
00901               str_array_p = va_arg (var_args, char***);
00902               n_elements_p = va_arg (var_args, int*);
00903 
00904               _dbus_assert (str_array_p != NULL);
00905               _dbus_assert (n_elements_p != NULL);
00906 
00907               /* Count elements in the array */
00908               _dbus_type_reader_recurse (&real->u.reader, &array);
00909 
00910               n_elements = 0;
00911               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00912                 {
00913                   ++n_elements;
00914                   _dbus_type_reader_next (&array);
00915                 }
00916 
00917               str_array = dbus_new0 (char*, n_elements + 1);
00918               if (str_array == NULL)
00919                 {
00920                   _DBUS_SET_OOM (error);
00921                   goto out;
00922                 }
00923 
00924               /* Now go through and dup each string */
00925               _dbus_type_reader_recurse (&real->u.reader, &array);
00926 
00927               i = 0;
00928               while (i < n_elements)
00929                 {
00930                   const char *s;
00931                   _dbus_type_reader_read_basic (&array,
00932                                                 (void *) &s);
00933                   
00934                   str_array[i] = _dbus_strdup (s);
00935                   if (str_array[i] == NULL)
00936                     {
00937                       dbus_free_string_array (str_array);
00938                       _DBUS_SET_OOM (error);
00939                       goto out;
00940                     }
00941                   
00942                   ++i;
00943                   
00944                   if (!_dbus_type_reader_next (&array))
00945                     _dbus_assert (i == n_elements);
00946                 }
00947 
00948               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00949               _dbus_assert (i == n_elements);
00950               _dbus_assert (str_array[i] == NULL);
00951 
00952               *str_array_p = str_array;
00953               *n_elements_p = n_elements;
00954             }
00955 #ifndef DBUS_DISABLE_CHECKS
00956           else
00957             {
00958               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00959                           _DBUS_FUNCTION_NAME);
00960               goto out;
00961             }
00962 #endif
00963         }
00964 #ifndef DBUS_DISABLE_CHECKS
00965       else
00966         {
00967           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00968                       _DBUS_FUNCTION_NAME);
00969           goto out;
00970         }
00971 #endif
00972 
00973       spec_type = va_arg (var_args, int);
00974       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00975         {
00976           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00977                           "Message has only %d arguments, but more were expected", i);
00978           goto out;
00979         }
00980 
00981       i++;
00982     }
00983 
00984   retval = TRUE;
00985 
00986  out:
00987 
00988   return retval;
00989 }
00990 
01049 dbus_uint32_t
01050 dbus_message_get_serial (DBusMessage *message)
01051 {
01052   _dbus_return_val_if_fail (message != NULL, 0);
01053 
01054   return _dbus_header_get_serial (&message->header);
01055 }
01056 
01065 dbus_bool_t
01066 dbus_message_set_reply_serial (DBusMessage   *message,
01067                                dbus_uint32_t  reply_serial)
01068 {
01069   _dbus_return_val_if_fail (message != NULL, FALSE);
01070   _dbus_return_val_if_fail (!message->locked, FALSE);
01071   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01072 
01073   return _dbus_header_set_field_basic (&message->header,
01074                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01075                                        DBUS_TYPE_UINT32,
01076                                        &reply_serial);
01077 }
01078 
01085 dbus_uint32_t
01086 dbus_message_get_reply_serial  (DBusMessage *message)
01087 {
01088   dbus_uint32_t v_UINT32;
01089 
01090   _dbus_return_val_if_fail (message != NULL, 0);
01091 
01092   if (_dbus_header_get_field_basic (&message->header,
01093                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01094                                     DBUS_TYPE_UINT32,
01095                                     &v_UINT32))
01096     return v_UINT32;
01097   else
01098     return 0;
01099 }
01100 
01101 static void
01102 dbus_message_finalize (DBusMessage *message)
01103 {
01104   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01105 
01106   /* This calls application callbacks! */
01107   _dbus_data_slot_list_free (&message->slot_list);
01108 
01109   _dbus_list_foreach (&message->counters,
01110                       free_counter, message);
01111   _dbus_list_clear (&message->counters);
01112 
01113   _dbus_header_free (&message->header);
01114   _dbus_string_free (&message->body);
01115 
01116 #ifdef HAVE_UNIX_FD_PASSING
01117   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01118   dbus_free(message->unix_fds);
01119 #endif
01120 
01121   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01122 
01123   dbus_free (message);
01124 }
01125 
01126 static DBusMessage*
01127 dbus_message_new_empty_header (void)
01128 {
01129   DBusMessage *message;
01130   dbus_bool_t from_cache;
01131 
01132   message = dbus_message_get_cached ();
01133 
01134   if (message != NULL)
01135     {
01136       from_cache = TRUE;
01137     }
01138   else
01139     {
01140       from_cache = FALSE;
01141       message = dbus_new0 (DBusMessage, 1);
01142       if (message == NULL)
01143         return NULL;
01144 #ifndef DBUS_DISABLE_CHECKS
01145       message->generation = _dbus_current_generation;
01146 #endif
01147 
01148 #ifdef HAVE_UNIX_FD_PASSING
01149       message->unix_fds = NULL;
01150       message->n_unix_fds_allocated = 0;
01151 #endif
01152     }
01153 
01154   _dbus_atomic_inc (&message->refcount);
01155 
01156   _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
01157 
01158   message->locked = FALSE;
01159 #ifndef DBUS_DISABLE_CHECKS
01160   message->in_cache = FALSE;
01161 #endif
01162   message->counters = NULL;
01163   message->size_counter_delta = 0;
01164   message->changed_stamp = 0;
01165 
01166 #ifdef HAVE_UNIX_FD_PASSING
01167   message->n_unix_fds = 0;
01168   message->n_unix_fds_allocated = 0;
01169   message->unix_fd_counter_delta = 0;
01170 #endif
01171 
01172   if (!from_cache)
01173     _dbus_data_slot_list_init (&message->slot_list);
01174 
01175   if (from_cache)
01176     {
01177       _dbus_header_reinit (&message->header);
01178       _dbus_string_set_length (&message->body, 0);
01179     }
01180   else
01181     {
01182       if (!_dbus_header_init (&message->header))
01183         {
01184           dbus_free (message);
01185           return NULL;
01186         }
01187 
01188       if (!_dbus_string_init_preallocated (&message->body, 32))
01189         {
01190           _dbus_header_free (&message->header);
01191           dbus_free (message);
01192           return NULL;
01193         }
01194     }
01195 
01196   return message;
01197 }
01198 
01211 DBusMessage*
01212 dbus_message_new (int message_type)
01213 {
01214   DBusMessage *message;
01215 
01216   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01217 
01218   message = dbus_message_new_empty_header ();
01219   if (message == NULL)
01220     return NULL;
01221 
01222   if (!_dbus_header_create (&message->header,
01223                             DBUS_COMPILER_BYTE_ORDER,
01224                             message_type,
01225                             NULL, NULL, NULL, NULL, NULL))
01226     {
01227       dbus_message_unref (message);
01228       return NULL;
01229     }
01230 
01231   return message;
01232 }
01233 
01255 DBusMessage*
01256 dbus_message_new_method_call (const char *destination,
01257                               const char *path,
01258                               const char *iface,
01259                               const char *method)
01260 {
01261   DBusMessage *message;
01262 
01263   _dbus_return_val_if_fail (path != NULL, NULL);
01264   _dbus_return_val_if_fail (method != NULL, NULL);
01265   _dbus_return_val_if_fail (destination == NULL ||
01266                             _dbus_check_is_valid_bus_name (destination), NULL);
01267   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01268   _dbus_return_val_if_fail (iface == NULL ||
01269                             _dbus_check_is_valid_interface (iface), NULL);
01270   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01271 
01272   message = dbus_message_new_empty_header ();
01273   if (message == NULL)
01274     return NULL;
01275 
01276   if (!_dbus_header_create (&message->header,
01277                             DBUS_COMPILER_BYTE_ORDER,
01278                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01279                             destination, path, iface, method, NULL))
01280     {
01281       dbus_message_unref (message);
01282       return NULL;
01283     }
01284 
01285   return message;
01286 }
01287 
01295 DBusMessage*
01296 dbus_message_new_method_return (DBusMessage *method_call)
01297 {
01298   DBusMessage *message;
01299   const char *sender;
01300 
01301   _dbus_return_val_if_fail (method_call != NULL, NULL);
01302 
01303   sender = dbus_message_get_sender (method_call);
01304 
01305   /* sender is allowed to be null here in peer-to-peer case */
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_COMPILER_BYTE_ORDER,
01313                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01314                             sender, NULL, NULL, NULL, NULL))
01315     {
01316       dbus_message_unref (message);
01317       return NULL;
01318     }
01319 
01320   dbus_message_set_no_reply (message, TRUE);
01321 
01322   if (!dbus_message_set_reply_serial (message,
01323                                       dbus_message_get_serial (method_call)))
01324     {
01325       dbus_message_unref (message);
01326       return NULL;
01327     }
01328 
01329   return message;
01330 }
01331 
01346 DBusMessage*
01347 dbus_message_new_signal (const char *path,
01348                          const char *iface,
01349                          const char *name)
01350 {
01351   DBusMessage *message;
01352 
01353   _dbus_return_val_if_fail (path != NULL, NULL);
01354   _dbus_return_val_if_fail (iface != NULL, NULL);
01355   _dbus_return_val_if_fail (name != NULL, NULL);
01356   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01357   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
01358   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01359 
01360   message = dbus_message_new_empty_header ();
01361   if (message == NULL)
01362     return NULL;
01363 
01364   if (!_dbus_header_create (&message->header,
01365                             DBUS_COMPILER_BYTE_ORDER,
01366                             DBUS_MESSAGE_TYPE_SIGNAL,
01367                             NULL, path, iface, name, NULL))
01368     {
01369       dbus_message_unref (message);
01370       return NULL;
01371     }
01372 
01373   dbus_message_set_no_reply (message, TRUE);
01374 
01375   return message;
01376 }
01377 
01392 DBusMessage*
01393 dbus_message_new_error (DBusMessage *reply_to,
01394                         const char  *error_name,
01395                         const char  *error_message)
01396 {
01397   DBusMessage *message;
01398   const char *sender;
01399   DBusMessageIter iter;
01400 
01401   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01402   _dbus_return_val_if_fail (error_name != NULL, NULL);
01403   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01404 
01405   sender = dbus_message_get_sender (reply_to);
01406 
01407   /* sender may be NULL for non-message-bus case or
01408    * when the message bus is dealing with an unregistered
01409    * connection.
01410    */
01411   message = dbus_message_new_empty_header ();
01412   if (message == NULL)
01413     return NULL;
01414 
01415   if (!_dbus_header_create (&message->header,
01416                             DBUS_COMPILER_BYTE_ORDER,
01417                             DBUS_MESSAGE_TYPE_ERROR,
01418                             sender, NULL, NULL, NULL, error_name))
01419     {
01420       dbus_message_unref (message);
01421       return NULL;
01422     }
01423 
01424   dbus_message_set_no_reply (message, TRUE);
01425 
01426   if (!dbus_message_set_reply_serial (message,
01427                                       dbus_message_get_serial (reply_to)))
01428     {
01429       dbus_message_unref (message);
01430       return NULL;
01431     }
01432 
01433   if (error_message != NULL)
01434     {
01435       dbus_message_iter_init_append (message, &iter);
01436       if (!dbus_message_iter_append_basic (&iter,
01437                                            DBUS_TYPE_STRING,
01438                                            &error_message))
01439         {
01440           dbus_message_unref (message);
01441           return NULL;
01442         }
01443     }
01444 
01445   return message;
01446 }
01447 
01464 DBusMessage*
01465 dbus_message_new_error_printf (DBusMessage *reply_to,
01466                                const char  *error_name,
01467                                const char  *error_format,
01468                                ...)
01469 {
01470   va_list args;
01471   DBusString str;
01472   DBusMessage *message;
01473 
01474   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01475   _dbus_return_val_if_fail (error_name != NULL, NULL);
01476   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01477 
01478   if (!_dbus_string_init (&str))
01479     return NULL;
01480 
01481   va_start (args, error_format);
01482 
01483   if (_dbus_string_append_printf_valist (&str, error_format, args))
01484     message = dbus_message_new_error (reply_to, error_name,
01485                                       _dbus_string_get_const_data (&str));
01486   else
01487     message = NULL;
01488 
01489   _dbus_string_free (&str);
01490 
01491   va_end (args);
01492 
01493   return message;
01494 }
01495 
01496 
01509 DBusMessage *
01510 dbus_message_copy (const DBusMessage *message)
01511 {
01512   DBusMessage *retval;
01513 
01514   _dbus_return_val_if_fail (message != NULL, NULL);
01515 
01516   retval = dbus_new0 (DBusMessage, 1);
01517   if (retval == NULL)
01518     return NULL;
01519 
01520   _dbus_atomic_inc (&retval->refcount);
01521 
01522   retval->locked = FALSE;
01523 #ifndef DBUS_DISABLE_CHECKS
01524   retval->generation = message->generation;
01525 #endif
01526 
01527   if (!_dbus_header_copy (&message->header, &retval->header))
01528     {
01529       dbus_free (retval);
01530       return NULL;
01531     }
01532 
01533   if (!_dbus_string_init_preallocated (&retval->body,
01534                                        _dbus_string_get_length (&message->body)))
01535     {
01536       _dbus_header_free (&retval->header);
01537       dbus_free (retval);
01538       return NULL;
01539     }
01540 
01541   if (!_dbus_string_copy (&message->body, 0,
01542                           &retval->body, 0))
01543     goto failed_copy;
01544 
01545 #ifdef HAVE_UNIX_FD_PASSING
01546   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01547   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01548     goto failed_copy;
01549 
01550   retval->n_unix_fds_allocated = message->n_unix_fds;
01551 
01552   for (retval->n_unix_fds = 0;
01553        retval->n_unix_fds < message->n_unix_fds;
01554        retval->n_unix_fds++)
01555     {
01556       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01557 
01558       if (retval->unix_fds[retval->n_unix_fds] < 0)
01559         goto failed_copy;
01560     }
01561 
01562 #endif
01563 
01564   _dbus_message_trace_ref (retval, 0, 1, "copy");
01565   return retval;
01566 
01567  failed_copy:
01568   _dbus_header_free (&retval->header);
01569   _dbus_string_free (&retval->body);
01570 
01571 #ifdef HAVE_UNIX_FD_PASSING
01572   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01573   dbus_free(retval->unix_fds);
01574 #endif
01575 
01576   dbus_free (retval);
01577 
01578   return NULL;
01579 }
01580 
01581 
01589 DBusMessage *
01590 dbus_message_ref (DBusMessage *message)
01591 {
01592   dbus_int32_t old_refcount;
01593 
01594   _dbus_return_val_if_fail (message != NULL, NULL);
01595   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01596   _dbus_return_val_if_fail (!message->in_cache, NULL);
01597 
01598   old_refcount = _dbus_atomic_inc (&message->refcount);
01599   _dbus_assert (old_refcount >= 1);
01600   _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
01601 
01602   return message;
01603 }
01604 
01612 void
01613 dbus_message_unref (DBusMessage *message)
01614 {
01615  dbus_int32_t old_refcount;
01616 
01617   _dbus_return_if_fail (message != NULL);
01618   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01619   _dbus_return_if_fail (!message->in_cache);
01620 
01621   old_refcount = _dbus_atomic_dec (&message->refcount);
01622 
01623   _dbus_assert (old_refcount >= 1);
01624 
01625   _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
01626 
01627   if (old_refcount == 1)
01628     {
01629       /* Calls application callbacks! */
01630       dbus_message_cache_or_finalize (message);
01631     }
01632 }
01633 
01644 int
01645 dbus_message_get_type (DBusMessage *message)
01646 {
01647   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01648 
01649   return _dbus_header_get_message_type (&message->header);
01650 }
01651 
01714 dbus_bool_t
01715 dbus_message_append_args (DBusMessage *message,
01716                           int          first_arg_type,
01717                           ...)
01718 {
01719   dbus_bool_t retval;
01720   va_list var_args;
01721 
01722   _dbus_return_val_if_fail (message != NULL, FALSE);
01723 
01724   va_start (var_args, first_arg_type);
01725   retval = dbus_message_append_args_valist (message,
01726                                             first_arg_type,
01727                                             var_args);
01728   va_end (var_args);
01729 
01730   return retval;
01731 }
01732 
01746 dbus_bool_t
01747 dbus_message_append_args_valist (DBusMessage *message,
01748                                  int          first_arg_type,
01749                                  va_list      var_args)
01750 {
01751   int type;
01752   DBusMessageIter iter;
01753 
01754   _dbus_return_val_if_fail (message != NULL, FALSE);
01755 
01756   type = first_arg_type;
01757 
01758   dbus_message_iter_init_append (message, &iter);
01759 
01760   while (type != DBUS_TYPE_INVALID)
01761     {
01762       if (dbus_type_is_basic (type))
01763         {
01764           const DBusBasicValue *value;
01765           value = va_arg (var_args, const DBusBasicValue*);
01766 
01767           if (!dbus_message_iter_append_basic (&iter,
01768                                                type,
01769                                                value))
01770             goto failed;
01771         }
01772       else if (type == DBUS_TYPE_ARRAY)
01773         {
01774           int element_type;
01775           DBusMessageIter array;
01776           char buf[2];
01777 
01778           element_type = va_arg (var_args, int);
01779               
01780           buf[0] = element_type;
01781           buf[1] = '\0';
01782           if (!dbus_message_iter_open_container (&iter,
01783                                                  DBUS_TYPE_ARRAY,
01784                                                  buf,
01785                                                  &array))
01786             goto failed;
01787 
01788           if (dbus_type_is_fixed (element_type) &&
01789               element_type != DBUS_TYPE_UNIX_FD)
01790             {
01791               const DBusBasicValue **value;
01792               int n_elements;
01793 
01794               value = va_arg (var_args, const DBusBasicValue**);
01795               n_elements = va_arg (var_args, int);
01796               
01797               if (!dbus_message_iter_append_fixed_array (&array,
01798                                                          element_type,
01799                                                          value,
01800                                                          n_elements)) {
01801                 dbus_message_iter_abandon_container (&iter, &array);
01802                 goto failed;
01803               }
01804             }
01805           else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
01806             {
01807               const char ***value_p;
01808               const char **value;
01809               int n_elements;
01810               int i;
01811               
01812               value_p = va_arg (var_args, const char***);
01813               n_elements = va_arg (var_args, int);
01814 
01815               value = *value_p;
01816               
01817               i = 0;
01818               while (i < n_elements)
01819                 {
01820                   if (!dbus_message_iter_append_basic (&array,
01821                                                        element_type,
01822                                                        &value[i])) {
01823                     dbus_message_iter_abandon_container (&iter, &array);
01824                     goto failed;
01825                   }
01826                   ++i;
01827                 }
01828             }
01829           else
01830             {
01831               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01832                           _dbus_type_to_string (element_type),
01833                           _DBUS_FUNCTION_NAME);
01834               goto failed;
01835             }
01836 
01837           if (!dbus_message_iter_close_container (&iter, &array))
01838             goto failed;
01839         }
01840 #ifndef DBUS_DISABLE_CHECKS
01841       else
01842         {
01843           _dbus_warn ("type %s isn't supported yet in %s\n",
01844                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01845           goto failed;
01846         }
01847 #endif
01848 
01849       type = va_arg (var_args, int);
01850     }
01851 
01852   return TRUE;
01853 
01854  failed:
01855   return FALSE;
01856 }
01857 
01902 dbus_bool_t
01903 dbus_message_get_args (DBusMessage     *message,
01904                        DBusError       *error,
01905                        int              first_arg_type,
01906                        ...)
01907 {
01908   dbus_bool_t retval;
01909   va_list var_args;
01910 
01911   _dbus_return_val_if_fail (message != NULL, FALSE);
01912   _dbus_return_val_if_error_is_set (error, FALSE);
01913 
01914   va_start (var_args, first_arg_type);
01915   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01916   va_end (var_args);
01917 
01918   return retval;
01919 }
01920 
01931 dbus_bool_t
01932 dbus_message_get_args_valist (DBusMessage     *message,
01933                               DBusError       *error,
01934                               int              first_arg_type,
01935                               va_list          var_args)
01936 {
01937   DBusMessageIter iter;
01938 
01939   _dbus_return_val_if_fail (message != NULL, FALSE);
01940   _dbus_return_val_if_error_is_set (error, FALSE);
01941 
01942   dbus_message_iter_init (message, &iter);
01943   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01944 }
01945 
01946 static void
01947 _dbus_message_iter_init_common (DBusMessage         *message,
01948                                 DBusMessageRealIter *real,
01949                                 int                  iter_type)
01950 {
01951   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01952 
01953   /* Since the iterator will read or write who-knows-what from the
01954    * message, we need to get in the right byte order
01955    */
01956   ensure_byte_order (message);
01957   
01958   real->message = message;
01959   real->changed_stamp = message->changed_stamp;
01960   real->iter_type = iter_type;
01961   real->sig_refcount = 0;
01962 }
01963 
01986 dbus_bool_t
01987 dbus_message_iter_init (DBusMessage     *message,
01988                         DBusMessageIter *iter)
01989 {
01990   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01991   const DBusString *type_str;
01992   int type_pos;
01993 
01994   _dbus_return_val_if_fail (message != NULL, FALSE);
01995   _dbus_return_val_if_fail (iter != NULL, FALSE);
01996 
01997   get_const_signature (&message->header, &type_str, &type_pos);
01998 
01999   _dbus_message_iter_init_common (message, real,
02000                                   DBUS_MESSAGE_ITER_TYPE_READER);
02001 
02002   _dbus_type_reader_init (&real->u.reader,
02003                           _dbus_header_get_byte_order (&message->header),
02004                           type_str, type_pos,
02005                           &message->body,
02006                           0);
02007 
02008   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
02009 }
02010 
02017 dbus_bool_t
02018 dbus_message_iter_has_next (DBusMessageIter *iter)
02019 {
02020   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02021 
02022   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02023   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02024 
02025   return _dbus_type_reader_has_next (&real->u.reader);
02026 }
02027 
02036 dbus_bool_t
02037 dbus_message_iter_next (DBusMessageIter *iter)
02038 {
02039   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02040 
02041   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02042   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02043 
02044   return _dbus_type_reader_next (&real->u.reader);
02045 }
02046 
02061 int
02062 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02063 {
02064   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02065 
02066   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02067   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02068 
02069   return _dbus_type_reader_get_current_type (&real->u.reader);
02070 }
02071 
02080 int
02081 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02082 {
02083   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02084 
02085   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02086   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02087   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02088 
02089   return _dbus_type_reader_get_element_type (&real->u.reader);
02090 }
02091 
02117 void
02118 dbus_message_iter_recurse (DBusMessageIter  *iter,
02119                            DBusMessageIter  *sub)
02120 {
02121   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02122   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02123 
02124   _dbus_return_if_fail (_dbus_message_iter_check (real));
02125   _dbus_return_if_fail (sub != NULL);
02126 
02127   *real_sub = *real;
02128   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02129 }
02130 
02142 char *
02143 dbus_message_iter_get_signature (DBusMessageIter *iter)
02144 {
02145   const DBusString *sig;
02146   DBusString retstr;
02147   char *ret;
02148   int start, len;
02149   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02150 
02151   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02152 
02153   if (!_dbus_string_init (&retstr))
02154     return NULL;
02155 
02156   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02157                                    &start, &len);
02158   if (!_dbus_string_append_len (&retstr,
02159                                 _dbus_string_get_const_data (sig) + start,
02160                                 len))
02161     return NULL;
02162   if (!_dbus_string_steal_data (&retstr, &ret))
02163     return NULL;
02164   _dbus_string_free (&retstr);
02165   return ret;
02166 }
02167 
02215 void
02216 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02217                              void             *value)
02218 {
02219   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02220 
02221   _dbus_return_if_fail (_dbus_message_iter_check (real));
02222   _dbus_return_if_fail (value != NULL);
02223 
02224   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02225     {
02226 #ifdef HAVE_UNIX_FD_PASSING
02227       DBusBasicValue idx;
02228 
02229       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02230 
02231       if (idx.u32 >= real->message->n_unix_fds) {
02232         /* Hmm, we cannot really signal an error here, so let's make
02233            sure to return an invalid fd. */
02234         *((int*) value) = -1;
02235         return;
02236       }
02237 
02238       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02239 #else
02240       *((int*) value) = -1;
02241 #endif
02242     }
02243   else
02244     {
02245       _dbus_type_reader_read_basic (&real->u.reader,
02246                                     value);
02247     }
02248 }
02249 
02268 int
02269 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02270 {
02271   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02272 
02273   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02274 
02275   return _dbus_type_reader_get_array_length (&real->u.reader);
02276 }
02277 
02313 void
02314 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02315                                    void             *value,
02316                                    int              *n_elements)
02317 {
02318   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02319 #ifndef DBUS_DISABLE_CHECKS
02320   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02321 
02322   _dbus_return_if_fail (_dbus_message_iter_check (real));
02323   _dbus_return_if_fail (value != NULL);
02324   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02325                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02326 #endif
02327 
02328   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02329                                       value, n_elements);
02330 }
02331 
02343 void
02344 dbus_message_iter_init_append (DBusMessage     *message,
02345                                DBusMessageIter *iter)
02346 {
02347   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02348 
02349   _dbus_return_if_fail (message != NULL);
02350   _dbus_return_if_fail (iter != NULL);
02351 
02352   _dbus_message_iter_init_common (message, real,
02353                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02354 
02355   /* We create the signature string and point iterators at it "on demand"
02356    * when a value is actually appended. That means that init() never fails
02357    * due to OOM.
02358    */
02359   _dbus_type_writer_init_types_delayed (&real->u.writer,
02360                                         _dbus_header_get_byte_order (&message->header),
02361                                         &message->body,
02362                                         _dbus_string_get_length (&message->body));
02363 }
02364 
02373 static dbus_bool_t
02374 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02375 {
02376   DBusString *str;
02377   const DBusString *current_sig;
02378   int current_sig_pos;
02379 
02380   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02381 
02382   if (real->u.writer.type_str != NULL)
02383     {
02384       _dbus_assert (real->sig_refcount > 0);
02385       real->sig_refcount += 1;
02386       return TRUE;
02387     }
02388 
02389   str = dbus_new (DBusString, 1);
02390   if (str == NULL)
02391     return FALSE;
02392 
02393   if (!_dbus_header_get_field_raw (&real->message->header,
02394                                    DBUS_HEADER_FIELD_SIGNATURE,
02395                                    &current_sig, &current_sig_pos))
02396     current_sig = NULL;
02397 
02398   if (current_sig)
02399     {
02400       int current_len;
02401 
02402       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02403       current_sig_pos += 1; /* move on to sig data */
02404 
02405       if (!_dbus_string_init_preallocated (str, current_len + 4))
02406         {
02407           dbus_free (str);
02408           return FALSE;
02409         }
02410 
02411       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02412                                   str, 0))
02413         {
02414           _dbus_string_free (str);
02415           dbus_free (str);
02416           return FALSE;
02417         }
02418     }
02419   else
02420     {
02421       if (!_dbus_string_init_preallocated (str, 4))
02422         {
02423           dbus_free (str);
02424           return FALSE;
02425         }
02426     }
02427 
02428   real->sig_refcount = 1;
02429 
02430   _dbus_type_writer_add_types (&real->u.writer,
02431                                str, _dbus_string_get_length (str));
02432   return TRUE;
02433 }
02434 
02444 static dbus_bool_t
02445 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02446 {
02447   DBusString *str;
02448   const char *v_STRING;
02449   dbus_bool_t retval;
02450 
02451   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02452   _dbus_assert (real->u.writer.type_str != NULL);
02453   _dbus_assert (real->sig_refcount > 0);
02454 
02455   real->sig_refcount -= 1;
02456 
02457   if (real->sig_refcount > 0)
02458     return TRUE;
02459   _dbus_assert (real->sig_refcount == 0);
02460 
02461   retval = TRUE;
02462 
02463   str = real->u.writer.type_str;
02464 
02465   v_STRING = _dbus_string_get_const_data (str);
02466   if (!_dbus_header_set_field_basic (&real->message->header,
02467                                      DBUS_HEADER_FIELD_SIGNATURE,
02468                                      DBUS_TYPE_SIGNATURE,
02469                                      &v_STRING))
02470     retval = FALSE;
02471 
02472   _dbus_type_writer_remove_types (&real->u.writer);
02473   _dbus_string_free (str);
02474   dbus_free (str);
02475 
02476   return retval;
02477 }
02478 
02486 static void
02487 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02488 {
02489   DBusString *str;
02490 
02491   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02492   _dbus_assert (real->u.writer.type_str != NULL);
02493   _dbus_assert (real->sig_refcount > 0);
02494 
02495   real->sig_refcount -= 1;
02496 
02497   if (real->sig_refcount > 0)
02498     return;
02499   _dbus_assert (real->sig_refcount == 0);
02500 
02501   str = real->u.writer.type_str;
02502 
02503   _dbus_type_writer_remove_types (&real->u.writer);
02504   _dbus_string_free (str);
02505   dbus_free (str);
02506 }
02507 
02508 #ifndef DBUS_DISABLE_CHECKS
02509 static dbus_bool_t
02510 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02511 {
02512   if (!_dbus_message_iter_check (iter))
02513     return FALSE;
02514 
02515   if (iter->message->locked)
02516     {
02517       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02518       return FALSE;
02519     }
02520 
02521   return TRUE;
02522 }
02523 #endif /* DBUS_DISABLE_CHECKS */
02524 
02525 #ifdef HAVE_UNIX_FD_PASSING
02526 static int *
02527 expand_fd_array(DBusMessage *m,
02528                 unsigned     n)
02529 {
02530   _dbus_assert(m);
02531 
02532   /* This makes space for adding n new fds to the array and returns a
02533      pointer to the place were the first fd should be put. */
02534 
02535   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02536     {
02537       unsigned k;
02538       int *p;
02539 
02540       /* Make twice as much space as necessary */
02541       k = (m->n_unix_fds + n) * 2;
02542 
02543       /* Allocate at least four */
02544       if (k < 4)
02545         k = 4;
02546 
02547       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02548       if (p == NULL)
02549         return NULL;
02550 
02551       m->unix_fds = p;
02552       m->n_unix_fds_allocated = k;
02553     }
02554 
02555   return m->unix_fds + m->n_unix_fds;
02556 }
02557 #endif
02558 
02578 dbus_bool_t
02579 dbus_message_iter_append_basic (DBusMessageIter *iter,
02580                                 int              type,
02581                                 const void      *value)
02582 {
02583   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02584   dbus_bool_t ret;
02585 
02586   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02587   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02588   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02589   _dbus_return_val_if_fail (value != NULL, FALSE);
02590 
02591 #ifndef DBUS_DISABLE_CHECKS
02592   switch (type)
02593     {
02594       const char * const *string_p;
02595       const dbus_bool_t *bool_p;
02596 
02597       case DBUS_TYPE_STRING:
02598         string_p = value;
02599         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02600         break;
02601 
02602       case DBUS_TYPE_OBJECT_PATH:
02603         string_p = value;
02604         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02605         break;
02606 
02607       case DBUS_TYPE_SIGNATURE:
02608         string_p = value;
02609         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02610         break;
02611 
02612       case DBUS_TYPE_BOOLEAN:
02613         bool_p = value;
02614         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02615         break;
02616 
02617       default:
02618           {
02619             /* nothing to check, all possible values are allowed */
02620           }
02621     }
02622 #endif
02623 
02624   if (!_dbus_message_iter_open_signature (real))
02625     return FALSE;
02626 
02627   if (type == DBUS_TYPE_UNIX_FD)
02628     {
02629 #ifdef HAVE_UNIX_FD_PASSING
02630       int *fds;
02631       dbus_uint32_t u;
02632 
02633       /* First step, include the fd in the fd list of this message */
02634       if (!(fds = expand_fd_array(real->message, 1)))
02635         return FALSE;
02636 
02637       *fds = _dbus_dup(*(int*) value, NULL);
02638       if (*fds < 0)
02639         return FALSE;
02640 
02641       u = real->message->n_unix_fds;
02642 
02643       /* Second step, write the index to the fd */
02644       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02645         _dbus_close(*fds, NULL);
02646         return FALSE;
02647       }
02648 
02649       real->message->n_unix_fds += 1;
02650       u += 1;
02651 
02652       /* Final step, update the header accordingly */
02653       ret = _dbus_header_set_field_basic (&real->message->header,
02654                                           DBUS_HEADER_FIELD_UNIX_FDS,
02655                                           DBUS_TYPE_UINT32,
02656                                           &u);
02657 
02658       /* If any of these operations fail the message is
02659          hosed. However, no memory or fds should be leaked since what
02660          has been added to message has been added to the message, and
02661          can hence be accounted for when the message is being
02662          freed. */
02663 #else
02664       ret = FALSE;
02665 #endif
02666     }
02667   else
02668     {
02669       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02670     }
02671 
02672   if (!_dbus_message_iter_close_signature (real))
02673     ret = FALSE;
02674 
02675   return ret;
02676 }
02677 
02713 dbus_bool_t
02714 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02715                                       int              element_type,
02716                                       const void      *value,
02717                                       int              n_elements)
02718 {
02719   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02720   dbus_bool_t ret;
02721 
02722   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02723   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02724   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02725   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02726   _dbus_return_val_if_fail (value != NULL, FALSE);
02727   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02728   _dbus_return_val_if_fail (n_elements <=
02729                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02730                             FALSE);
02731 
02732 #ifndef DBUS_DISABLE_CHECKS
02733   if (element_type == DBUS_TYPE_BOOLEAN)
02734     {
02735       const dbus_bool_t * const *bools = value;
02736       int i;
02737 
02738       for (i = 0; i < n_elements; i++)
02739         {
02740           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02741         }
02742     }
02743 #endif
02744 
02745   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02746 
02747   return ret;
02748 }
02749 
02771 dbus_bool_t
02772 dbus_message_iter_open_container (DBusMessageIter *iter,
02773                                   int              type,
02774                                   const char      *contained_signature,
02775                                   DBusMessageIter *sub)
02776 {
02777   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02778   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02779   DBusString contained_str;
02780 
02781   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02782   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02783   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02784   _dbus_return_val_if_fail (sub != NULL, FALSE);
02785   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02786                              contained_signature == NULL) ||
02787                             (type == DBUS_TYPE_DICT_ENTRY &&
02788                              contained_signature == NULL) ||
02789                             (type == DBUS_TYPE_VARIANT &&
02790                              contained_signature != NULL) ||
02791                             (type == DBUS_TYPE_ARRAY &&
02792                              contained_signature != NULL), FALSE);
02793   
02794   /* this would fail if the contained_signature is a dict entry, since
02795    * dict entries are invalid signatures standalone (they must be in
02796    * an array)
02797    */
02798   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02799                             (contained_signature == NULL ||
02800                              _dbus_check_is_valid_signature (contained_signature)),
02801                             FALSE);
02802 
02803   if (!_dbus_message_iter_open_signature (real))
02804     return FALSE;
02805 
02806   *real_sub = *real;
02807 
02808   if (contained_signature != NULL)
02809     {
02810       _dbus_string_init_const (&contained_str, contained_signature);
02811 
02812       return _dbus_type_writer_recurse (&real->u.writer,
02813                                         type,
02814                                         &contained_str, 0,
02815                                         &real_sub->u.writer);
02816     }
02817   else
02818     {
02819       return _dbus_type_writer_recurse (&real->u.writer,
02820                                         type,
02821                                         NULL, 0,
02822                                         &real_sub->u.writer);
02823     } 
02824 }
02825 
02826 
02840 dbus_bool_t
02841 dbus_message_iter_close_container (DBusMessageIter *iter,
02842                                    DBusMessageIter *sub)
02843 {
02844   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02845   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02846   dbus_bool_t ret;
02847 
02848   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02849   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02850   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02851   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02852 
02853   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02854                                      &real_sub->u.writer);
02855 
02856   if (!_dbus_message_iter_close_signature (real))
02857     ret = FALSE;
02858 
02859   return ret;
02860 }
02861 
02873 void
02874 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02875                                      DBusMessageIter *sub)
02876 {
02877   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02878 #ifndef DBUS_DISABLE_CHECKS
02879   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02880 
02881   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02882   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02883   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02884   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02885 #endif
02886 
02887   _dbus_message_iter_abandon_signature (real);
02888 }
02889 
02906 void
02907 dbus_message_set_no_reply (DBusMessage *message,
02908                            dbus_bool_t  no_reply)
02909 {
02910   _dbus_return_if_fail (message != NULL);
02911   _dbus_return_if_fail (!message->locked);
02912 
02913   _dbus_header_toggle_flag (&message->header,
02914                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02915                             no_reply);
02916 }
02917 
02925 dbus_bool_t
02926 dbus_message_get_no_reply (DBusMessage *message)
02927 {
02928   _dbus_return_val_if_fail (message != NULL, FALSE);
02929 
02930   return _dbus_header_get_flag (&message->header,
02931                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02932 }
02933 
02948 void
02949 dbus_message_set_auto_start (DBusMessage *message,
02950                              dbus_bool_t  auto_start)
02951 {
02952   _dbus_return_if_fail (message != NULL);
02953   _dbus_return_if_fail (!message->locked);
02954 
02955   _dbus_header_toggle_flag (&message->header,
02956                             DBUS_HEADER_FLAG_NO_AUTO_START,
02957                             !auto_start);
02958 }
02959 
02967 dbus_bool_t
02968 dbus_message_get_auto_start (DBusMessage *message)
02969 {
02970   _dbus_return_val_if_fail (message != NULL, FALSE);
02971 
02972   return !_dbus_header_get_flag (&message->header,
02973                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02974 }
02975 
02976 
02989 dbus_bool_t
02990 dbus_message_set_path (DBusMessage   *message,
02991                        const char    *object_path)
02992 {
02993   _dbus_return_val_if_fail (message != NULL, FALSE);
02994   _dbus_return_val_if_fail (!message->locked, FALSE);
02995   _dbus_return_val_if_fail (object_path == NULL ||
02996                             _dbus_check_is_valid_path (object_path),
02997                             FALSE);
02998 
02999   return set_or_delete_string_field (message,
03000                                      DBUS_HEADER_FIELD_PATH,
03001                                      DBUS_TYPE_OBJECT_PATH,
03002                                      object_path);
03003 }
03004 
03018 const char*
03019 dbus_message_get_path (DBusMessage   *message)
03020 {
03021   const char *v;
03022 
03023   _dbus_return_val_if_fail (message != NULL, NULL);
03024 
03025   v = NULL; /* in case field doesn't exist */
03026   _dbus_header_get_field_basic (&message->header,
03027                                 DBUS_HEADER_FIELD_PATH,
03028                                 DBUS_TYPE_OBJECT_PATH,
03029                                 (void *) &v);
03030   return v;
03031 }
03032 
03042 dbus_bool_t
03043 dbus_message_has_path (DBusMessage   *message,
03044                        const char    *path)
03045 {
03046   const char *msg_path;
03047   msg_path = dbus_message_get_path (message);
03048   
03049   if (msg_path == NULL)
03050     {
03051       if (path == NULL)
03052         return TRUE;
03053       else
03054         return FALSE;
03055     }
03056 
03057   if (path == NULL)
03058     return FALSE;
03059    
03060   if (strcmp (msg_path, path) == 0)
03061     return TRUE;
03062 
03063   return FALSE;
03064 }
03065 
03086 dbus_bool_t
03087 dbus_message_get_path_decomposed (DBusMessage   *message,
03088                                   char        ***path)
03089 {
03090   const char *v;
03091 
03092   _dbus_return_val_if_fail (message != NULL, FALSE);
03093   _dbus_return_val_if_fail (path != NULL, FALSE);
03094 
03095   *path = NULL;
03096 
03097   v = dbus_message_get_path (message);
03098   if (v != NULL)
03099     {
03100       if (!_dbus_decompose_path (v, strlen (v),
03101                                  path, NULL))
03102         return FALSE;
03103     }
03104   return TRUE;
03105 }
03106 
03120 dbus_bool_t
03121 dbus_message_set_interface (DBusMessage  *message,
03122                             const char   *iface)
03123 {
03124   _dbus_return_val_if_fail (message != NULL, FALSE);
03125   _dbus_return_val_if_fail (!message->locked, FALSE);
03126   _dbus_return_val_if_fail (iface == NULL ||
03127                             _dbus_check_is_valid_interface (iface),
03128                             FALSE);
03129 
03130   return set_or_delete_string_field (message,
03131                                      DBUS_HEADER_FIELD_INTERFACE,
03132                                      DBUS_TYPE_STRING,
03133                                      iface);
03134 }
03135 
03149 const char*
03150 dbus_message_get_interface (DBusMessage *message)
03151 {
03152   const char *v;
03153 
03154   _dbus_return_val_if_fail (message != NULL, NULL);
03155 
03156   v = NULL; /* in case field doesn't exist */
03157   _dbus_header_get_field_basic (&message->header,
03158                                 DBUS_HEADER_FIELD_INTERFACE,
03159                                 DBUS_TYPE_STRING,
03160                                 (void *) &v);
03161   return v;
03162 }
03163 
03171 dbus_bool_t
03172 dbus_message_has_interface (DBusMessage   *message,
03173                             const char    *iface)
03174 {
03175   const char *msg_interface;
03176   msg_interface = dbus_message_get_interface (message);
03177    
03178   if (msg_interface == NULL)
03179     {
03180       if (iface == NULL)
03181         return TRUE;
03182       else
03183         return FALSE;
03184     }
03185 
03186   if (iface == NULL)
03187     return FALSE;
03188      
03189   if (strcmp (msg_interface, iface) == 0)
03190     return TRUE;
03191 
03192   return FALSE;
03193 
03194 }
03195 
03208 dbus_bool_t
03209 dbus_message_set_member (DBusMessage  *message,
03210                          const char   *member)
03211 {
03212   _dbus_return_val_if_fail (message != NULL, FALSE);
03213   _dbus_return_val_if_fail (!message->locked, FALSE);
03214   _dbus_return_val_if_fail (member == NULL ||
03215                             _dbus_check_is_valid_member (member),
03216                             FALSE);
03217 
03218   return set_or_delete_string_field (message,
03219                                      DBUS_HEADER_FIELD_MEMBER,
03220                                      DBUS_TYPE_STRING,
03221                                      member);
03222 }
03223 
03235 const char*
03236 dbus_message_get_member (DBusMessage *message)
03237 {
03238   const char *v;
03239 
03240   _dbus_return_val_if_fail (message != NULL, NULL);
03241 
03242   v = NULL; /* in case field doesn't exist */
03243   _dbus_header_get_field_basic (&message->header,
03244                                 DBUS_HEADER_FIELD_MEMBER,
03245                                 DBUS_TYPE_STRING,
03246                                 (void *) &v);
03247   return v;
03248 }
03249 
03257 dbus_bool_t
03258 dbus_message_has_member (DBusMessage   *message,
03259                          const char    *member)
03260 {
03261   const char *msg_member;
03262   msg_member = dbus_message_get_member (message);
03263  
03264   if (msg_member == NULL)
03265     {
03266       if (member == NULL)
03267         return TRUE;
03268       else
03269         return FALSE;
03270     }
03271 
03272   if (member == NULL)
03273     return FALSE;
03274     
03275   if (strcmp (msg_member, member) == 0)
03276     return TRUE;
03277 
03278   return FALSE;
03279 
03280 }
03281 
03293 dbus_bool_t
03294 dbus_message_set_error_name (DBusMessage  *message,
03295                              const char   *error_name)
03296 {
03297   _dbus_return_val_if_fail (message != NULL, FALSE);
03298   _dbus_return_val_if_fail (!message->locked, FALSE);
03299   _dbus_return_val_if_fail (error_name == NULL ||
03300                             _dbus_check_is_valid_error_name (error_name),
03301                             FALSE);
03302 
03303   return set_or_delete_string_field (message,
03304                                      DBUS_HEADER_FIELD_ERROR_NAME,
03305                                      DBUS_TYPE_STRING,
03306                                      error_name);
03307 }
03308 
03319 const char*
03320 dbus_message_get_error_name (DBusMessage *message)
03321 {
03322   const char *v;
03323 
03324   _dbus_return_val_if_fail (message != NULL, NULL);
03325 
03326   v = NULL; /* in case field doesn't exist */
03327   _dbus_header_get_field_basic (&message->header,
03328                                 DBUS_HEADER_FIELD_ERROR_NAME,
03329                                 DBUS_TYPE_STRING,
03330                                 (void *) &v);
03331   return v;
03332 }
03333 
03347 dbus_bool_t
03348 dbus_message_set_destination (DBusMessage  *message,
03349                               const char   *destination)
03350 {
03351   _dbus_return_val_if_fail (message != NULL, FALSE);
03352   _dbus_return_val_if_fail (!message->locked, FALSE);
03353   _dbus_return_val_if_fail (destination == NULL ||
03354                             _dbus_check_is_valid_bus_name (destination),
03355                             FALSE);
03356 
03357   return set_or_delete_string_field (message,
03358                                      DBUS_HEADER_FIELD_DESTINATION,
03359                                      DBUS_TYPE_STRING,
03360                                      destination);
03361 }
03362 
03372 const char*
03373 dbus_message_get_destination (DBusMessage *message)
03374 {
03375   const char *v;
03376 
03377   _dbus_return_val_if_fail (message != NULL, NULL);
03378 
03379   v = NULL; /* in case field doesn't exist */
03380   _dbus_header_get_field_basic (&message->header,
03381                                 DBUS_HEADER_FIELD_DESTINATION,
03382                                 DBUS_TYPE_STRING,
03383                                 (void *) &v);
03384   return v;
03385 }
03386 
03401 dbus_bool_t
03402 dbus_message_set_sender (DBusMessage  *message,
03403                          const char   *sender)
03404 {
03405   _dbus_return_val_if_fail (message != NULL, FALSE);
03406   _dbus_return_val_if_fail (!message->locked, FALSE);
03407   _dbus_return_val_if_fail (sender == NULL ||
03408                             _dbus_check_is_valid_bus_name (sender),
03409                             FALSE);
03410 
03411   return set_or_delete_string_field (message,
03412                                      DBUS_HEADER_FIELD_SENDER,
03413                                      DBUS_TYPE_STRING,
03414                                      sender);
03415 }
03416 
03432 const char*
03433 dbus_message_get_sender (DBusMessage *message)
03434 {
03435   const char *v;
03436 
03437   _dbus_return_val_if_fail (message != NULL, NULL);
03438 
03439   v = NULL; /* in case field doesn't exist */
03440   _dbus_header_get_field_basic (&message->header,
03441                                 DBUS_HEADER_FIELD_SENDER,
03442                                 DBUS_TYPE_STRING,
03443                                 (void *) &v);
03444   return v;
03445 }
03446 
03465 const char*
03466 dbus_message_get_signature (DBusMessage *message)
03467 {
03468   const DBusString *type_str;
03469   int type_pos;
03470 
03471   _dbus_return_val_if_fail (message != NULL, NULL);
03472 
03473   get_const_signature (&message->header, &type_str, &type_pos);
03474 
03475   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03476 }
03477 
03478 static dbus_bool_t
03479 _dbus_message_has_type_interface_member (DBusMessage *message,
03480                                          int          type,
03481                                          const char  *iface,
03482                                          const char  *member)
03483 {
03484   const char *n;
03485 
03486   _dbus_assert (message != NULL);
03487   _dbus_assert (iface != NULL);
03488   _dbus_assert (member != NULL);
03489 
03490   if (dbus_message_get_type (message) != type)
03491     return FALSE;
03492 
03493   /* Optimize by checking the short member name first
03494    * instead of the longer interface name
03495    */
03496 
03497   n = dbus_message_get_member (message);
03498 
03499   if (n && strcmp (n, member) == 0)
03500     {
03501       n = dbus_message_get_interface (message);
03502 
03503       if (n == NULL || strcmp (n, iface) == 0)
03504         return TRUE;
03505     }
03506 
03507   return FALSE;
03508 }
03509 
03524 dbus_bool_t
03525 dbus_message_is_method_call (DBusMessage *message,
03526                              const char  *iface,
03527                              const char  *method)
03528 {
03529   _dbus_return_val_if_fail (message != NULL, FALSE);
03530   _dbus_return_val_if_fail (iface != NULL, FALSE);
03531   _dbus_return_val_if_fail (method != NULL, FALSE);
03532   /* don't check that interface/method are valid since it would be
03533    * expensive, and not catch many common errors
03534    */
03535 
03536   return _dbus_message_has_type_interface_member (message,
03537                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03538                                                   iface, method);
03539 }
03540 
03552 dbus_bool_t
03553 dbus_message_is_signal (DBusMessage *message,
03554                         const char  *iface,
03555                         const char  *signal_name)
03556 {
03557   _dbus_return_val_if_fail (message != NULL, FALSE);
03558   _dbus_return_val_if_fail (iface != NULL, FALSE);
03559   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03560   /* don't check that interface/name are valid since it would be
03561    * expensive, and not catch many common errors
03562    */
03563 
03564   return _dbus_message_has_type_interface_member (message,
03565                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03566                                                   iface, signal_name);
03567 }
03568 
03579 dbus_bool_t
03580 dbus_message_is_error (DBusMessage *message,
03581                        const char  *error_name)
03582 {
03583   const char *n;
03584 
03585   _dbus_return_val_if_fail (message != NULL, FALSE);
03586   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03587   /* don't check that error_name is valid since it would be expensive,
03588    * and not catch many common errors
03589    */
03590 
03591   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03592     return FALSE;
03593 
03594   n = dbus_message_get_error_name (message);
03595 
03596   if (n && strcmp (n, error_name) == 0)
03597     return TRUE;
03598   else
03599     return FALSE;
03600 }
03601 
03612 dbus_bool_t
03613 dbus_message_has_destination (DBusMessage  *message,
03614                               const char   *name)
03615 {
03616   const char *s;
03617 
03618   _dbus_return_val_if_fail (message != NULL, FALSE);
03619   _dbus_return_val_if_fail (name != NULL, FALSE);
03620   /* don't check that name is valid since it would be expensive, and
03621    * not catch many common errors
03622    */
03623 
03624   s = dbus_message_get_destination (message);
03625 
03626   if (s && strcmp (s, name) == 0)
03627     return TRUE;
03628   else
03629     return FALSE;
03630 }
03631 
03647 dbus_bool_t
03648 dbus_message_has_sender (DBusMessage  *message,
03649                          const char   *name)
03650 {
03651   const char *s;
03652 
03653   _dbus_return_val_if_fail (message != NULL, FALSE);
03654   _dbus_return_val_if_fail (name != NULL, FALSE);
03655   /* don't check that name is valid since it would be expensive, and
03656    * not catch many common errors
03657    */
03658 
03659   s = dbus_message_get_sender (message);
03660 
03661   if (s && strcmp (s, name) == 0)
03662     return TRUE;
03663   else
03664     return FALSE;
03665 }
03666 
03676 dbus_bool_t
03677 dbus_message_has_signature (DBusMessage   *message,
03678                             const char    *signature)
03679 {
03680   const char *s;
03681 
03682   _dbus_return_val_if_fail (message != NULL, FALSE);
03683   _dbus_return_val_if_fail (signature != NULL, FALSE);
03684   /* don't check that signature is valid since it would be expensive,
03685    * and not catch many common errors
03686    */
03687 
03688   s = dbus_message_get_signature (message);
03689 
03690   if (s && strcmp (s, signature) == 0)
03691     return TRUE;
03692   else
03693     return FALSE;
03694 }
03695 
03718 dbus_bool_t
03719 dbus_set_error_from_message (DBusError   *error,
03720                              DBusMessage *message)
03721 {
03722   const char *str;
03723 
03724   _dbus_return_val_if_fail (message != NULL, FALSE);
03725   _dbus_return_val_if_error_is_set (error, FALSE);
03726 
03727   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03728     return FALSE;
03729 
03730   str = NULL;
03731   dbus_message_get_args (message, NULL,
03732                          DBUS_TYPE_STRING, &str,
03733                          DBUS_TYPE_INVALID);
03734 
03735   dbus_set_error (error, dbus_message_get_error_name (message),
03736                   str ? "%s" : NULL, str);
03737 
03738   return TRUE;
03739 }
03740 
03747 dbus_bool_t
03748 dbus_message_contains_unix_fds(DBusMessage *message)
03749 {
03750 #ifdef HAVE_UNIX_FD_PASSING
03751   _dbus_assert(message);
03752 
03753   return message->n_unix_fds > 0;
03754 #else
03755   return FALSE;
03756 #endif
03757 }
03758 
03777 #define INITIAL_LOADER_DATA_LEN 32
03778 
03785 DBusMessageLoader*
03786 _dbus_message_loader_new (void)
03787 {
03788   DBusMessageLoader *loader;
03789 
03790   loader = dbus_new0 (DBusMessageLoader, 1);
03791   if (loader == NULL)
03792     return NULL;
03793   
03794   loader->refcount = 1;
03795 
03796   loader->corrupted = FALSE;
03797   loader->corruption_reason = DBUS_VALID;
03798 
03799   /* this can be configured by the app, but defaults to the protocol max */
03800   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03801 
03802   /* We set a very relatively conservative default here since due to how
03803   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03804   number of unix fds we want to receive in advance. A
03805   try-and-reallocate loop is not possible. */
03806   loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
03807 
03808   if (!_dbus_string_init (&loader->data))
03809     {
03810       dbus_free (loader);
03811       return NULL;
03812     }
03813 
03814   /* preallocate the buffer for speed, ignore failure */
03815   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03816   _dbus_string_set_length (&loader->data, 0);
03817 
03818 #ifdef HAVE_UNIX_FD_PASSING
03819   loader->unix_fds = NULL;
03820   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03821   loader->unix_fds_outstanding = FALSE;
03822 #endif
03823 
03824   return loader;
03825 }
03826 
03833 DBusMessageLoader *
03834 _dbus_message_loader_ref (DBusMessageLoader *loader)
03835 {
03836   loader->refcount += 1;
03837 
03838   return loader;
03839 }
03840 
03847 void
03848 _dbus_message_loader_unref (DBusMessageLoader *loader)
03849 {
03850   loader->refcount -= 1;
03851   if (loader->refcount == 0)
03852     {
03853 #ifdef HAVE_UNIX_FD_PASSING
03854       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
03855       dbus_free(loader->unix_fds);
03856 #endif
03857       _dbus_list_foreach (&loader->messages,
03858                           (DBusForeachFunction) dbus_message_unref,
03859                           NULL);
03860       _dbus_list_clear (&loader->messages);
03861       _dbus_string_free (&loader->data);
03862       dbus_free (loader);
03863     }
03864 }
03865 
03884 void
03885 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03886                                  DBusString        **buffer)
03887 {
03888   _dbus_assert (!loader->buffer_outstanding);
03889 
03890   *buffer = &loader->data;
03891 
03892   loader->buffer_outstanding = TRUE;
03893 }
03894 
03905 void
03906 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03907                                     DBusString         *buffer,
03908                                     int                 bytes_read)
03909 {
03910   _dbus_assert (loader->buffer_outstanding);
03911   _dbus_assert (buffer == &loader->data);
03912 
03913   loader->buffer_outstanding = FALSE;
03914 }
03915 
03926 dbus_bool_t
03927 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
03928                                   int               **fds,
03929                                   unsigned           *max_n_fds)
03930 {
03931 #ifdef HAVE_UNIX_FD_PASSING
03932   _dbus_assert (!loader->unix_fds_outstanding);
03933 
03934   /* Allocate space where we can put the fds we read. We allocate
03935      space for max_message_unix_fds since this is an
03936      upper limit how many fds can be received within a single
03937      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
03938      we are allocating the maximum possible array size right from the
03939      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
03940      there is no better way. */
03941 
03942   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
03943     {
03944       int *a = dbus_realloc(loader->unix_fds,
03945                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
03946 
03947       if (!a)
03948         return FALSE;
03949 
03950       loader->unix_fds = a;
03951       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
03952     }
03953 
03954   *fds = loader->unix_fds + loader->n_unix_fds;
03955   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
03956 
03957   loader->unix_fds_outstanding = TRUE;
03958   return TRUE;
03959 #else
03960   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03961   return FALSE;
03962 #endif
03963 }
03964 
03975 void
03976 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
03977                                      int                *fds,
03978                                      unsigned            n_fds)
03979 {
03980 #ifdef HAVE_UNIX_FD_PASSING
03981   _dbus_assert(loader->unix_fds_outstanding);
03982   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
03983   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
03984 
03985   loader->n_unix_fds += n_fds;
03986   loader->unix_fds_outstanding = FALSE;
03987 
03988   if (n_fds && loader->unix_fds_change)
03989     loader->unix_fds_change (loader->unix_fds_change_data);
03990 #else
03991   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03992 #endif
03993 }
03994 
03995 /*
03996  * FIXME when we move the header out of the buffer, that memmoves all
03997  * buffered messages. Kind of crappy.
03998  *
03999  * Also we copy the header and body, which is kind of crappy.  To
04000  * avoid this, we have to allow header and body to be in a single
04001  * memory block, which is good for messages we read and bad for
04002  * messages we are creating. But we could move_len() the buffer into
04003  * this single memory block, and move_len() will just swap the buffers
04004  * if you're moving the entire buffer replacing the dest string.
04005  *
04006  * We could also have the message loader tell the transport how many
04007  * bytes to read; so it would first ask for some arbitrary number like
04008  * 256, then if the message was incomplete it would use the
04009  * header/body len to ask for exactly the size of the message (or
04010  * blocks the size of a typical kernel buffer for the socket). That
04011  * way we don't get trailing bytes in the buffer that have to be
04012  * memmoved. Though I suppose we also don't have a chance of reading a
04013  * bunch of small messages at once, so the optimization may be stupid.
04014  *
04015  * Another approach would be to keep a "start" index into
04016  * loader->data and only delete it occasionally, instead of after
04017  * each message is loaded.
04018  *
04019  * load_message() returns FALSE if not enough memory OR the loader was corrupted
04020  */
04021 static dbus_bool_t
04022 load_message (DBusMessageLoader *loader,
04023               DBusMessage       *message,
04024               int                byte_order,
04025               int                fields_array_len,
04026               int                header_len,
04027               int                body_len)
04028 {
04029   dbus_bool_t oom;
04030   DBusValidity validity;
04031   const DBusString *type_str;
04032   int type_pos;
04033   DBusValidationMode mode;
04034   dbus_uint32_t n_unix_fds = 0;
04035 
04036   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
04037   
04038   oom = FALSE;
04039 
04040 #if 0
04041   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
04042 #endif
04043 
04044   /* 1. VALIDATE AND COPY OVER HEADER */
04045   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
04046   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
04047 
04048   if (!_dbus_header_load (&message->header,
04049                           mode,
04050                           &validity,
04051                           byte_order,
04052                           fields_array_len,
04053                           header_len,
04054                           body_len,
04055                           &loader->data, 0,
04056                           _dbus_string_get_length (&loader->data)))
04057     {
04058       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
04059 
04060       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
04061          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
04062       _dbus_assert (validity != DBUS_VALID);
04063 
04064       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
04065         oom = TRUE;
04066       else
04067         {
04068           loader->corrupted = TRUE;
04069           loader->corruption_reason = validity;
04070         }
04071       goto failed;
04072     }
04073 
04074   _dbus_assert (validity == DBUS_VALID);
04075 
04076   /* 2. VALIDATE BODY */
04077   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04078     {
04079       get_const_signature (&message->header, &type_str, &type_pos);
04080       
04081       /* Because the bytes_remaining arg is NULL, this validates that the
04082        * body is the right length
04083        */
04084       validity = _dbus_validate_body_with_reason (type_str,
04085                                                   type_pos,
04086                                                   byte_order,
04087                                                   NULL,
04088                                                   &loader->data,
04089                                                   header_len,
04090                                                   body_len);
04091       if (validity != DBUS_VALID)
04092         {
04093           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04094 
04095           loader->corrupted = TRUE;
04096           loader->corruption_reason = validity;
04097           
04098           goto failed;
04099         }
04100     }
04101 
04102   /* 3. COPY OVER UNIX FDS */
04103   _dbus_header_get_field_basic(&message->header,
04104                                DBUS_HEADER_FIELD_UNIX_FDS,
04105                                DBUS_TYPE_UINT32,
04106                                &n_unix_fds);
04107 
04108 #ifdef HAVE_UNIX_FD_PASSING
04109 
04110   if (n_unix_fds > loader->n_unix_fds)
04111     {
04112       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04113                     n_unix_fds, loader->n_unix_fds);
04114 
04115       loader->corrupted = TRUE;
04116       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04117       goto failed;
04118     }
04119 
04120   /* If this was a recycled message there might still be
04121      some memory allocated for the fds */
04122   dbus_free(message->unix_fds);
04123 
04124   if (n_unix_fds > 0)
04125     {
04126       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04127       if (message->unix_fds == NULL)
04128         {
04129           _dbus_verbose ("Failed to allocate file descriptor array\n");
04130           oom = TRUE;
04131           goto failed;
04132         }
04133 
04134       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04135       loader->n_unix_fds -= n_unix_fds;
04136       memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
04137 
04138       if (loader->unix_fds_change)
04139         loader->unix_fds_change (loader->unix_fds_change_data);
04140     }
04141   else
04142     message->unix_fds = NULL;
04143 
04144 #else
04145 
04146   if (n_unix_fds > 0)
04147     {
04148       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04149                      "but that's not supported on our platform, disconnecting.\n");
04150 
04151       loader->corrupted = TRUE;
04152       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04153       goto failed;
04154     }
04155 
04156 #endif
04157 
04158   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04159 
04160   if (!_dbus_list_append (&loader->messages, message))
04161     {
04162       _dbus_verbose ("Failed to append new message to loader queue\n");
04163       oom = TRUE;
04164       goto failed;
04165     }
04166 
04167   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04168   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04169                 (header_len + body_len));
04170 
04171   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04172     {
04173       _dbus_verbose ("Failed to move body into new message\n");
04174       oom = TRUE;
04175       goto failed;
04176     }
04177 
04178   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04179 
04180   /* don't waste more than 2k of memory */
04181   _dbus_string_compact (&loader->data, 2048);
04182 
04183   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04184   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04185 
04186   _dbus_verbose ("Loaded message %p\n", message);
04187 
04188   _dbus_assert (!oom);
04189   _dbus_assert (!loader->corrupted);
04190   _dbus_assert (loader->messages != NULL);
04191   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04192 
04193   return TRUE;
04194 
04195  failed:
04196 
04197   /* Clean up */
04198 
04199   /* does nothing if the message isn't in the list */
04200   _dbus_list_remove_last (&loader->messages, message);
04201   
04202   if (oom)
04203     _dbus_assert (!loader->corrupted);
04204   else
04205     _dbus_assert (loader->corrupted);
04206 
04207   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04208 
04209   return FALSE;
04210 }
04211 
04226 dbus_bool_t
04227 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04228 {
04229   while (!loader->corrupted &&
04230          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04231     {
04232       DBusValidity validity;
04233       int byte_order, fields_array_len, header_len, body_len;
04234 
04235       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04236                                                &validity,
04237                                                &byte_order,
04238                                                &fields_array_len,
04239                                                &header_len,
04240                                                &body_len,
04241                                                &loader->data, 0,
04242                                                _dbus_string_get_length (&loader->data)))
04243         {
04244           DBusMessage *message;
04245 
04246           _dbus_assert (validity == DBUS_VALID);
04247 
04248           message = dbus_message_new_empty_header ();
04249           if (message == NULL)
04250             return FALSE;
04251 
04252           if (!load_message (loader, message,
04253                              byte_order, fields_array_len,
04254                              header_len, body_len))
04255             {
04256               dbus_message_unref (message);
04257               /* load_message() returns false if corrupted or OOM; if
04258                * corrupted then return TRUE for not OOM
04259                */
04260               return loader->corrupted;
04261             }
04262 
04263           _dbus_assert (loader->messages != NULL);
04264           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04265         }
04266       else
04267         {
04268           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04269                          validity);
04270           if (validity != DBUS_VALID)
04271             {
04272               loader->corrupted = TRUE;
04273               loader->corruption_reason = validity;
04274             }
04275           return TRUE;
04276         }
04277     }
04278 
04279   return TRUE;
04280 }
04281 
04289 DBusMessage*
04290 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04291 {
04292   if (loader->messages)
04293     return loader->messages->data;
04294   else
04295     return NULL;
04296 }
04297 
04306 DBusMessage*
04307 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04308 {
04309   return _dbus_list_pop_first (&loader->messages);
04310 }
04311 
04320 DBusList*
04321 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04322 {
04323   return _dbus_list_pop_first_link (&loader->messages);
04324 }
04325 
04332 void
04333 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04334                                            DBusList           *link)
04335 {
04336   _dbus_list_prepend_link (&loader->messages, link);
04337 }
04338 
04348 dbus_bool_t
04349 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04350 {
04351   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04352                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04353   return loader->corrupted;
04354 }
04355 
04362 DBusValidity
04363 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04364 {
04365   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04366                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04367 
04368   return loader->corruption_reason;
04369 }
04370 
04377 void
04378 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04379                                            long                size)
04380 {
04381   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04382     {
04383       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04384                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04385       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04386     }
04387   loader->max_message_size = size;
04388 }
04389 
04396 long
04397 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04398 {
04399   return loader->max_message_size;
04400 }
04401 
04408 void
04409 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04410                                                long                n)
04411 {
04412   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04413     {
04414       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04415                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04416       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04417     }
04418   loader->max_message_unix_fds = n;
04419 }
04420 
04427 long
04428 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04429 {
04430   return loader->max_message_unix_fds;
04431 }
04432 
04433 static DBusDataSlotAllocator slot_allocator;
04434 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
04435 
04441 int
04442 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
04443 {
04444 #ifdef HAVE_UNIX_FD_PASSING
04445   return loader->n_unix_fds;
04446 #else
04447   return 0;
04448 #endif
04449 }
04450 
04459 void
04460 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
04461                                                void (* callback) (void *),
04462                                                void *data)
04463 {
04464 #ifdef HAVE_UNIX_FD_PASSING
04465   loader->unix_fds_change = callback;
04466   loader->unix_fds_change_data = data;
04467 #endif
04468 }
04469 
04484 dbus_bool_t
04485 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04486 {
04487   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04488                                           &_DBUS_LOCK_NAME (message_slots),
04489                                           slot_p);
04490 }
04491 
04503 void
04504 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04505 {
04506   _dbus_return_if_fail (*slot_p >= 0);
04507 
04508   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04509 }
04510 
04524 dbus_bool_t
04525 dbus_message_set_data (DBusMessage     *message,
04526                        dbus_int32_t     slot,
04527                        void            *data,
04528                        DBusFreeFunction free_data_func)
04529 {
04530   DBusFreeFunction old_free_func;
04531   void *old_data;
04532   dbus_bool_t retval;
04533 
04534   _dbus_return_val_if_fail (message != NULL, FALSE);
04535   _dbus_return_val_if_fail (slot >= 0, FALSE);
04536 
04537   retval = _dbus_data_slot_list_set (&slot_allocator,
04538                                      &message->slot_list,
04539                                      slot, data, free_data_func,
04540                                      &old_free_func, &old_data);
04541 
04542   if (retval)
04543     {
04544       /* Do the actual free outside the message lock */
04545       if (old_free_func)
04546         (* old_free_func) (old_data);
04547     }
04548 
04549   return retval;
04550 }
04551 
04560 void*
04561 dbus_message_get_data (DBusMessage   *message,
04562                        dbus_int32_t   slot)
04563 {
04564   void *res;
04565 
04566   _dbus_return_val_if_fail (message != NULL, NULL);
04567 
04568   res = _dbus_data_slot_list_get (&slot_allocator,
04569                                   &message->slot_list,
04570                                   slot);
04571 
04572   return res;
04573 }
04574 
04588 int
04589 dbus_message_type_from_string (const char *type_str)
04590 {
04591   if (strcmp (type_str, "method_call") == 0)
04592     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04593   if (strcmp (type_str, "method_return") == 0)
04594     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04595   else if (strcmp (type_str, "signal") == 0)
04596     return DBUS_MESSAGE_TYPE_SIGNAL;
04597   else if (strcmp (type_str, "error") == 0)
04598     return DBUS_MESSAGE_TYPE_ERROR;
04599   else
04600     return DBUS_MESSAGE_TYPE_INVALID;
04601 }
04602 
04616 const char *
04617 dbus_message_type_to_string (int type)
04618 {
04619   switch (type)
04620     {
04621     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04622       return "method_call";
04623     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04624       return "method_return";
04625     case DBUS_MESSAGE_TYPE_SIGNAL:
04626       return "signal";
04627     case DBUS_MESSAGE_TYPE_ERROR:
04628       return "error";
04629     default:
04630       return "invalid";
04631     }
04632 }
04633 
04646 dbus_bool_t
04647 dbus_message_marshal (DBusMessage  *msg,
04648                       char        **marshalled_data_p,
04649                       int          *len_p)
04650 {
04651   DBusString tmp;
04652   dbus_bool_t was_locked;
04653 
04654   _dbus_return_val_if_fail (msg != NULL, FALSE);
04655   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04656   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04657   
04658   if (!_dbus_string_init (&tmp))
04659     return FALSE;
04660 
04661   /* Ensure the message is locked, to ensure the length header is filled in. */
04662   was_locked = msg->locked;
04663 
04664   if (!was_locked)
04665     dbus_message_lock (msg);
04666 
04667   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04668     goto fail;
04669 
04670   *len_p = _dbus_string_get_length (&tmp);
04671 
04672   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04673     goto fail;
04674 
04675   *len_p = _dbus_string_get_length (&tmp);
04676 
04677   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04678     goto fail;
04679 
04680   _dbus_string_free (&tmp);
04681 
04682   if (!was_locked)
04683     msg->locked = FALSE;
04684 
04685   return TRUE;
04686 
04687  fail:
04688   _dbus_string_free (&tmp);
04689 
04690   if (!was_locked)
04691     msg->locked = FALSE;
04692 
04693   return FALSE;
04694 }
04695 
04708 DBusMessage *
04709 dbus_message_demarshal (const char *str,
04710                         int         len,
04711                         DBusError  *error)
04712 {
04713   DBusMessageLoader *loader;
04714   DBusString *buffer;
04715   DBusMessage *msg;
04716 
04717   _dbus_return_val_if_fail (str != NULL, NULL);
04718 
04719   loader = _dbus_message_loader_new ();
04720 
04721   if (loader == NULL)
04722     return NULL;
04723 
04724   _dbus_message_loader_get_buffer (loader, &buffer);
04725   _dbus_string_append_len (buffer, str, len);
04726   _dbus_message_loader_return_buffer (loader, buffer, len);
04727 
04728   if (!_dbus_message_loader_queue_messages (loader))
04729     goto fail_oom;
04730 
04731   if (_dbus_message_loader_get_is_corrupted (loader))
04732     goto fail_corrupt;
04733 
04734   msg = _dbus_message_loader_pop_message (loader);
04735 
04736   if (!msg)
04737     goto fail_oom;
04738 
04739   _dbus_message_loader_unref (loader);
04740   return msg;
04741 
04742  fail_corrupt:
04743   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04744                   _dbus_validity_to_error_message (loader->corruption_reason));
04745   _dbus_message_loader_unref (loader);
04746   return NULL;
04747 
04748  fail_oom:
04749   _DBUS_SET_OOM (error);
04750   _dbus_message_loader_unref (loader);
04751   return NULL;
04752 }
04753 
04767 int 
04768 dbus_message_demarshal_bytes_needed(const char *buf, 
04769                                     int         len)
04770 {
04771   DBusString str;
04772   int byte_order, fields_array_len, header_len, body_len;
04773   DBusValidity validity = DBUS_VALID;
04774   int have_message;
04775 
04776   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04777     return 0;
04778 
04779   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04780     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04781   _dbus_string_init_const_len (&str, buf, len);
04782   
04783   validity = DBUS_VALID;
04784   have_message
04785     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04786                                           &validity, &byte_order,
04787                                           &fields_array_len,
04788                                           &header_len,
04789                                           &body_len,
04790                                           &str, 0,
04791                                           len);
04792   _dbus_string_free (&str);
04793 
04794   if (validity == DBUS_VALID)
04795     {
04796       _dbus_assert (have_message || (header_len + body_len) > len);
04797       (void) have_message; /* unused unless asserting */
04798       return header_len + body_len;
04799     }
04800   else
04801     {
04802       return -1; /* broken! */
04803     }
04804 }
04805 
04808 /* tests in dbus-message-util.c */