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