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

dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-marshal-recursive.h"
00027 #include "dbus-marshal-validate.h"
00028 #include "dbus-marshal-byteswap.h"
00029 #include "dbus-marshal-header.h"
00030 #include "dbus-signature.h"
00031 #include "dbus-message-private.h"
00032 #include "dbus-object-tree.h"
00033 #include "dbus-memory.h"
00034 #include "dbus-list.h"
00035 #include "dbus-threads-internal.h"
00036 #include <string.h>
00037 
00038 static void dbus_message_finalize (DBusMessage *message);
00039 
00050 /* Not thread locked, but strictly const/read-only so should be OK
00051  */
00053 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
00054 
00055 /* these have wacky values to help trap uninitialized iterators;
00056  * but has to fit in 3 bits
00057  */
00058 enum {
00059   DBUS_MESSAGE_ITER_TYPE_READER = 3,
00060   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
00061 };
00062 
00064 typedef struct DBusMessageRealIter DBusMessageRealIter;
00065 
00071 struct DBusMessageRealIter
00072 {
00073   DBusMessage *message; 
00074   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 
00075   dbus_uint32_t iter_type : 3;      
00076   dbus_uint32_t sig_refcount : 8;   
00077   union
00078   {
00079     DBusTypeWriter writer; 
00080     DBusTypeReader reader; 
00081   } u; 
00082 };
00083 
00084 static void
00085 get_const_signature (DBusHeader        *header,
00086                      const DBusString **type_str_p,
00087                      int               *type_pos_p)
00088 {
00089   if (_dbus_header_get_field_raw (header,
00090                                   DBUS_HEADER_FIELD_SIGNATURE,
00091                                   type_str_p,
00092                                   type_pos_p))
00093     {
00094       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00095     }
00096   else
00097     {
00098       *type_str_p = &_dbus_empty_signature_str;
00099       *type_pos_p = 0;
00100     }
00101 }
00102 
00108 static void
00109 _dbus_message_byteswap (DBusMessage *message)
00110 {
00111   const DBusString *type_str;
00112   int type_pos;
00113   
00114   if (message->byte_order == DBUS_COMPILER_BYTE_ORDER)
00115     return;
00116 
00117   _dbus_verbose ("Swapping message into compiler byte order\n");
00118   
00119   get_const_signature (&message->header, &type_str, &type_pos);
00120   
00121   _dbus_marshal_byteswap (type_str, type_pos,
00122                           message->byte_order,
00123                           DBUS_COMPILER_BYTE_ORDER,
00124                           &message->body, 0);
00125 
00126   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00127   
00128   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00129 }
00130 
00137 #define ensure_byte_order(message)                      \
00138  if (message->byte_order != DBUS_COMPILER_BYTE_ORDER)   \
00139    _dbus_message_byteswap (message)
00140 
00151 void
00152 _dbus_message_get_network_data (DBusMessage          *message,
00153                                 const DBusString    **header,
00154                                 const DBusString    **body)
00155 {
00156   _dbus_assert (message->locked);
00157 
00158   *header = &message->header.data;
00159   *body = &message->body;
00160 }
00161 
00173 void 
00174 dbus_message_set_serial (DBusMessage   *message,
00175                          dbus_uint32_t  serial)
00176 {
00177   _dbus_return_if_fail (message != NULL);
00178   _dbus_return_if_fail (!message->locked);
00179 
00180   _dbus_header_set_serial (&message->header, serial);
00181 }
00182 
00195 void
00196 _dbus_message_add_size_counter_link (DBusMessage  *message,
00197                                      DBusList     *link)
00198 {
00199   /* right now we don't recompute the delta when message
00200    * size changes, and that's OK for current purposes
00201    * I think, but could be important to change later.
00202    * Do recompute it whenever there are no outstanding counters,
00203    * since it's basically free.
00204    */
00205   if (message->size_counters == NULL)
00206     {
00207       message->size_counter_delta =
00208         _dbus_string_get_length (&message->header.data) +
00209         _dbus_string_get_length (&message->body);
00210 
00211 #if 0
00212       _dbus_verbose ("message has size %ld\n",
00213                      message->size_counter_delta);
00214 #endif
00215     }
00216 
00217   _dbus_list_append_link (&message->size_counters, link);
00218 
00219   _dbus_counter_adjust (link->data, message->size_counter_delta);
00220 }
00221 
00231 dbus_bool_t
00232 _dbus_message_add_size_counter (DBusMessage *message,
00233                                 DBusCounter *counter)
00234 {
00235   DBusList *link;
00236 
00237   link = _dbus_list_alloc_link (counter);
00238   if (link == NULL)
00239     return FALSE;
00240 
00241   _dbus_counter_ref (counter);
00242   _dbus_message_add_size_counter_link (message, link);
00243 
00244   return TRUE;
00245 }
00246 
00255 void
00256 _dbus_message_remove_size_counter (DBusMessage  *message,
00257                                    DBusCounter  *counter,
00258                                    DBusList    **link_return)
00259 {
00260   DBusList *link;
00261 
00262   link = _dbus_list_find_last (&message->size_counters,
00263                                counter);
00264   _dbus_assert (link != NULL);
00265 
00266   _dbus_list_unlink (&message->size_counters,
00267                      link);
00268   if (link_return)
00269     *link_return = link;
00270   else
00271     _dbus_list_free_link (link);
00272 
00273   _dbus_counter_adjust (counter, - message->size_counter_delta);
00274 
00275   _dbus_counter_unref (counter);
00276 }
00277 
00288 void
00289 dbus_message_lock (DBusMessage  *message)
00290 {
00291   if (!message->locked)
00292     {
00293       _dbus_header_update_lengths (&message->header,
00294                                    _dbus_string_get_length (&message->body));
00295 
00296       /* must have a signature if you have a body */
00297       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00298                     dbus_message_get_signature (message) != NULL);
00299 
00300       message->locked = TRUE;
00301     }
00302 }
00303 
00304 static dbus_bool_t
00305 set_or_delete_string_field (DBusMessage *message,
00306                             int          field,
00307                             int          typecode,
00308                             const char  *value)
00309 {
00310   if (value == NULL)
00311     return _dbus_header_delete_field (&message->header, field);
00312   else
00313     return _dbus_header_set_field_basic (&message->header,
00314                                          field,
00315                                          typecode,
00316                                          &value);
00317 }
00318 
00319 #if 0
00320 /* Probably we don't need to use this */
00344 static dbus_bool_t
00345 _dbus_message_set_signature (DBusMessage *message,
00346                              const char  *signature)
00347 {
00348   _dbus_return_val_if_fail (message != NULL, FALSE);
00349   _dbus_return_val_if_fail (!message->locked, FALSE);
00350   _dbus_return_val_if_fail (signature == NULL ||
00351                             _dbus_check_is_valid_signature (signature));
00352   /* can't delete the signature if you have a message body */
00353   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00354                             signature != NULL);
00355 
00356   return set_or_delete_string_field (message,
00357                                      DBUS_HEADER_FIELD_SIGNATURE,
00358                                      DBUS_TYPE_SIGNATURE,
00359                                      signature);
00360 }
00361 #endif
00362 
00363 /* Message Cache
00364  *
00365  * We cache some DBusMessage to reduce the overhead of allocating
00366  * them.  In my profiling this consistently made about an 8%
00367  * difference.  It avoids the malloc for the message, the malloc for
00368  * the slot list, the malloc for the header string and body string,
00369  * and the associated free() calls. It does introduce another global
00370  * lock which could be a performance issue in certain cases.
00371  *
00372  * For the echo client/server the round trip time goes from around
00373  * .000077 to .000069 with the message cache on my laptop. The sysprof
00374  * change is as follows (numbers are cumulative percentage):
00375  *
00376  *  with message cache implemented as array as it is now (0.000069 per):
00377  *    new_empty_header           1.46
00378  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00379  *      mutex_unlock             0.25
00380  *      self                     0.41
00381  *    unref                      2.24
00382  *      self                     0.68
00383  *      list_clear               0.43
00384  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00385  *      mutex_unlock             0.25
00386  *
00387  *  with message cache implemented as list (0.000070 per roundtrip):
00388  *    new_empty_header           2.72
00389  *      list_pop_first           1.88
00390  *    unref                      3.3
00391  *      list_prepend             1.63
00392  *
00393  * without cache (0.000077 per roundtrip):
00394  *    new_empty_header           6.7
00395  *      string_init_preallocated 3.43
00396  *        dbus_malloc            2.43
00397  *      dbus_malloc0             2.59
00398  *
00399  *    unref                      4.02
00400  *      string_free              1.82
00401  *        dbus_free              1.63
00402  *      dbus_free                0.71
00403  *
00404  * If you implement the message_cache with a list, the primary reason
00405  * it's slower is that you add another thread lock (on the DBusList
00406  * mempool).
00407  */
00408 
00410 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00411 
00413 #define MAX_MESSAGE_CACHE_SIZE    5
00414 
00415 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00416 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00417 static int message_cache_count = 0;
00418 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00419 
00420 static void
00421 dbus_message_cache_shutdown (void *data)
00422 {
00423   int i;
00424 
00425   _DBUS_LOCK (message_cache);
00426 
00427   i = 0;
00428   while (i < MAX_MESSAGE_CACHE_SIZE)
00429     {
00430       if (message_cache[i])
00431         dbus_message_finalize (message_cache[i]);
00432 
00433       ++i;
00434     }
00435 
00436   message_cache_count = 0;
00437   message_cache_shutdown_registered = FALSE;
00438 
00439   _DBUS_UNLOCK (message_cache);
00440 }
00441 
00449 static DBusMessage*
00450 dbus_message_get_cached (void)
00451 {
00452   DBusMessage *message;
00453   int i;
00454 
00455   message = NULL;
00456 
00457   _DBUS_LOCK (message_cache);
00458 
00459   _dbus_assert (message_cache_count >= 0);
00460 
00461   if (message_cache_count == 0)
00462     {
00463       _DBUS_UNLOCK (message_cache);
00464       return NULL;
00465     }
00466 
00467   /* This is not necessarily true unless count > 0, and
00468    * message_cache is uninitialized until the shutdown is
00469    * registered
00470    */
00471   _dbus_assert (message_cache_shutdown_registered);
00472 
00473   i = 0;
00474   while (i < MAX_MESSAGE_CACHE_SIZE)
00475     {
00476       if (message_cache[i])
00477         {
00478           message = message_cache[i];
00479           message_cache[i] = NULL;
00480           message_cache_count -= 1;
00481           break;
00482         }
00483       ++i;
00484     }
00485   _dbus_assert (message_cache_count >= 0);
00486   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00487   _dbus_assert (message != NULL);
00488 
00489   _dbus_assert (message->refcount.value == 0);
00490   _dbus_assert (message->size_counters == NULL);
00491   
00492   _DBUS_UNLOCK (message_cache);
00493 
00494   return message;
00495 }
00496 
00497 static void
00498 free_size_counter (void *element,
00499                    void *data)
00500 {
00501   DBusCounter *counter = element;
00502   DBusMessage *message = data;
00503 
00504   _dbus_counter_adjust (counter, - message->size_counter_delta);
00505 
00506   _dbus_counter_unref (counter);
00507 }
00508 
00514 static void
00515 dbus_message_cache_or_finalize (DBusMessage *message)
00516 {
00517   dbus_bool_t was_cached;
00518   int i;
00519   
00520   _dbus_assert (message->refcount.value == 0);
00521 
00522   /* This calls application code and has to be done first thing
00523    * without holding the lock
00524    */
00525   _dbus_data_slot_list_clear (&message->slot_list);
00526 
00527   _dbus_list_foreach (&message->size_counters,
00528                       free_size_counter, message);
00529   _dbus_list_clear (&message->size_counters);
00530 
00531   was_cached = FALSE;
00532 
00533   _DBUS_LOCK (message_cache);
00534 
00535   if (!message_cache_shutdown_registered)
00536     {
00537       _dbus_assert (message_cache_count == 0);
00538 
00539       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00540         goto out;
00541 
00542       i = 0;
00543       while (i < MAX_MESSAGE_CACHE_SIZE)
00544         {
00545           message_cache[i] = NULL;
00546           ++i;
00547         }
00548 
00549       message_cache_shutdown_registered = TRUE;
00550     }
00551 
00552   _dbus_assert (message_cache_count >= 0);
00553 
00554   if ((_dbus_string_get_length (&message->header.data) +
00555        _dbus_string_get_length (&message->body)) >
00556       MAX_MESSAGE_SIZE_TO_CACHE)
00557     goto out;
00558 
00559   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00560     goto out;
00561 
00562   /* Find empty slot */
00563   i = 0;
00564   while (message_cache[i] != NULL)
00565     ++i;
00566 
00567   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00568 
00569   _dbus_assert (message_cache[i] == NULL);
00570   message_cache[i] = message;
00571   message_cache_count += 1;
00572   was_cached = TRUE;
00573 #ifndef DBUS_DISABLE_CHECKS
00574   message->in_cache = TRUE;
00575 #endif
00576 
00577  out:
00578   _dbus_assert (message->refcount.value == 0);
00579   
00580   _DBUS_UNLOCK (message_cache);
00581   
00582   if (!was_cached)
00583     dbus_message_finalize (message);
00584 }
00585 
00586 #ifndef DBUS_DISABLE_CHECKS
00587 static dbus_bool_t
00588 _dbus_message_iter_check (DBusMessageRealIter *iter)
00589 {
00590   if (iter == NULL)
00591     {
00592       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00593       return FALSE;
00594     }
00595 
00596   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00597     {
00598       if (iter->u.reader.byte_order != iter->message->byte_order)
00599         {
00600           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00601           return FALSE;
00602         }
00603       /* because we swap the message into compiler order when you init an iter */
00604       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00605     }
00606   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00607     {
00608       if (iter->u.writer.byte_order != iter->message->byte_order)
00609         {
00610           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00611           return FALSE;
00612         }
00613       /* because we swap the message into compiler order when you init an iter */
00614       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00615     }
00616   else
00617     {
00618       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00619       return FALSE;
00620     }
00621 
00622   if (iter->changed_stamp != iter->message->changed_stamp)
00623     {
00624       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00625       return FALSE;
00626     }
00627 
00628   return TRUE;
00629 }
00630 #endif /* DBUS_DISABLE_CHECKS */
00631 
00644 dbus_bool_t
00645 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00646                                     DBusError       *error,
00647                                     int              first_arg_type,
00648                                     va_list          var_args)
00649 {
00650   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00651   int spec_type, msg_type, i;
00652   dbus_bool_t retval;
00653 
00654   _dbus_assert (_dbus_message_iter_check (real));
00655 
00656   retval = FALSE;
00657 
00658   spec_type = first_arg_type;
00659   i = 0;
00660 
00661   while (spec_type != DBUS_TYPE_INVALID)
00662     {
00663       msg_type = dbus_message_iter_get_arg_type (iter);
00664 
00665       if (msg_type != spec_type)
00666         {
00667           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00668                           "Argument %d is specified to be of type \"%s\", but "
00669                           "is actually of type \"%s\"\n", i,
00670                           _dbus_type_to_string (spec_type),
00671                           _dbus_type_to_string (msg_type));
00672 
00673           goto out;
00674         }
00675 
00676       if (dbus_type_is_basic (spec_type))
00677         {
00678           DBusBasicValue *ptr;
00679 
00680           ptr = va_arg (var_args, DBusBasicValue*);
00681 
00682           _dbus_assert (ptr != NULL);
00683 
00684           _dbus_type_reader_read_basic (&real->u.reader,
00685                                         ptr);
00686         }
00687       else if (spec_type == DBUS_TYPE_ARRAY)
00688         {
00689           int element_type;
00690           int spec_element_type;
00691           const DBusBasicValue **ptr;
00692           int *n_elements_p;
00693           DBusTypeReader array;
00694 
00695           spec_element_type = va_arg (var_args, int);
00696           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00697 
00698           if (spec_element_type != element_type)
00699             {
00700               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00701                               "Argument %d is specified to be an array of \"%s\", but "
00702                               "is actually an array of \"%s\"\n",
00703                               i,
00704                               _dbus_type_to_string (spec_element_type),
00705                               _dbus_type_to_string (element_type));
00706 
00707               goto out;
00708             }
00709 
00710           if (dbus_type_is_fixed (spec_element_type))
00711             {
00712               ptr = va_arg (var_args, const DBusBasicValue**);
00713               n_elements_p = va_arg (var_args, int*);
00714 
00715               _dbus_assert (ptr != NULL);
00716               _dbus_assert (n_elements_p != NULL);
00717 
00718               _dbus_type_reader_recurse (&real->u.reader, &array);
00719 
00720               _dbus_type_reader_read_fixed_multi (&array,
00721                                                   ptr, n_elements_p);
00722             }
00723           else if (spec_element_type == DBUS_TYPE_STRING ||
00724                    spec_element_type == DBUS_TYPE_SIGNATURE ||
00725                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
00726             {
00727               char ***str_array_p;
00728               int n_elements;
00729               char **str_array;
00730 
00731               str_array_p = va_arg (var_args, char***);
00732               n_elements_p = va_arg (var_args, int*);
00733 
00734               _dbus_assert (str_array_p != NULL);
00735               _dbus_assert (n_elements_p != NULL);
00736 
00737               /* Count elements in the array */
00738               _dbus_type_reader_recurse (&real->u.reader, &array);
00739 
00740               n_elements = 0;
00741               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00742                 {
00743                   ++n_elements;
00744                   _dbus_type_reader_next (&array);
00745                 }
00746 
00747               str_array = dbus_new0 (char*, n_elements + 1);
00748               if (str_array == NULL)
00749                 {
00750                   _DBUS_SET_OOM (error);
00751                   goto out;
00752                 }
00753 
00754               /* Now go through and dup each string */
00755               _dbus_type_reader_recurse (&real->u.reader, &array);
00756 
00757               i = 0;
00758               while (i < n_elements)
00759                 {
00760                   const char *s;
00761                   _dbus_type_reader_read_basic (&array,
00762                                                 &s);
00763                   
00764                   str_array[i] = _dbus_strdup (s);
00765                   if (str_array[i] == NULL)
00766                     {
00767                       dbus_free_string_array (str_array);
00768                       _DBUS_SET_OOM (error);
00769                       goto out;
00770                     }
00771                   
00772                   ++i;
00773                   
00774                   if (!_dbus_type_reader_next (&array))
00775                     _dbus_assert (i == n_elements);
00776                 }
00777 
00778               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00779               _dbus_assert (i == n_elements);
00780               _dbus_assert (str_array[i] == NULL);
00781 
00782               *str_array_p = str_array;
00783               *n_elements_p = n_elements;
00784             }
00785 #ifndef DBUS_DISABLE_CHECKS
00786           else
00787             {
00788               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00789                           _DBUS_FUNCTION_NAME);
00790               goto out;
00791             }
00792 #endif
00793         }
00794 #ifndef DBUS_DISABLE_CHECKS
00795       else
00796         {
00797           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00798                       _DBUS_FUNCTION_NAME);
00799           goto out;
00800         }
00801 #endif
00802 
00803       spec_type = va_arg (var_args, int);
00804       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00805         {
00806           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00807                           "Message has only %d arguments, but more were expected", i);
00808           goto out;
00809         }
00810 
00811       i++;
00812     }
00813 
00814   retval = TRUE;
00815 
00816  out:
00817 
00818   return retval;
00819 }
00820 
00879 dbus_uint32_t
00880 dbus_message_get_serial (DBusMessage *message)
00881 {
00882   _dbus_return_val_if_fail (message != NULL, 0);
00883 
00884   return _dbus_header_get_serial (&message->header);
00885 }
00886 
00895 dbus_bool_t
00896 dbus_message_set_reply_serial (DBusMessage   *message,
00897                                dbus_uint32_t  reply_serial)
00898 {
00899   _dbus_return_val_if_fail (message != NULL, FALSE);
00900   _dbus_return_val_if_fail (!message->locked, FALSE);
00901   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
00902 
00903   return _dbus_header_set_field_basic (&message->header,
00904                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
00905                                        DBUS_TYPE_UINT32,
00906                                        &reply_serial);
00907 }
00908 
00915 dbus_uint32_t
00916 dbus_message_get_reply_serial  (DBusMessage *message)
00917 {
00918   dbus_uint32_t v_UINT32;
00919 
00920   _dbus_return_val_if_fail (message != NULL, 0);
00921 
00922   if (_dbus_header_get_field_basic (&message->header,
00923                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
00924                                     DBUS_TYPE_UINT32,
00925                                     &v_UINT32))
00926     return v_UINT32;
00927   else
00928     return 0;
00929 }
00930 
00931 static void
00932 dbus_message_finalize (DBusMessage *message)
00933 {
00934   _dbus_assert (message->refcount.value == 0);
00935 
00936   /* This calls application callbacks! */
00937   _dbus_data_slot_list_free (&message->slot_list);
00938 
00939   _dbus_list_foreach (&message->size_counters,
00940                       free_size_counter, message);
00941   _dbus_list_clear (&message->size_counters);
00942 
00943   _dbus_header_free (&message->header);
00944   _dbus_string_free (&message->body);
00945 
00946   _dbus_assert (message->refcount.value == 0);
00947   
00948   dbus_free (message);
00949 }
00950 
00951 static DBusMessage*
00952 dbus_message_new_empty_header (void)
00953 {
00954   DBusMessage *message;
00955   dbus_bool_t from_cache;
00956 
00957   message = dbus_message_get_cached ();
00958 
00959   if (message != NULL)
00960     {
00961       from_cache = TRUE;
00962     }
00963   else
00964     {
00965       from_cache = FALSE;
00966       message = dbus_new (DBusMessage, 1);
00967       if (message == NULL)
00968         return NULL;
00969 #ifndef DBUS_DISABLE_CHECKS
00970       message->generation = _dbus_current_generation;
00971 #endif
00972     }
00973   
00974   message->refcount.value = 1;
00975   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00976   message->locked = FALSE;
00977 #ifndef DBUS_DISABLE_CHECKS
00978   message->in_cache = FALSE;
00979 #endif
00980   message->size_counters = NULL;
00981   message->size_counter_delta = 0;
00982   message->changed_stamp = 0;
00983 
00984   if (!from_cache)
00985     _dbus_data_slot_list_init (&message->slot_list);
00986 
00987   if (from_cache)
00988     {
00989       _dbus_header_reinit (&message->header, message->byte_order);
00990       _dbus_string_set_length (&message->body, 0);
00991     }
00992   else
00993     {
00994       if (!_dbus_header_init (&message->header, message->byte_order))
00995         {
00996           dbus_free (message);
00997           return NULL;
00998         }
00999 
01000       if (!_dbus_string_init_preallocated (&message->body, 32))
01001         {
01002           _dbus_header_free (&message->header);
01003           dbus_free (message);
01004           return NULL;
01005         }
01006     }
01007 
01008   return message;
01009 }
01010 
01023 DBusMessage*
01024 dbus_message_new (int message_type)
01025 {
01026   DBusMessage *message;
01027 
01028   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01029 
01030   message = dbus_message_new_empty_header ();
01031   if (message == NULL)
01032     return NULL;
01033 
01034   if (!_dbus_header_create (&message->header,
01035                             message_type,
01036                             NULL, NULL, NULL, NULL, NULL))
01037     {
01038       dbus_message_unref (message);
01039       return NULL;
01040     }
01041 
01042   return message;
01043 }
01044 
01066 DBusMessage*
01067 dbus_message_new_method_call (const char *destination,
01068                               const char *path,
01069                               const char *interface,
01070                               const char *method)
01071 {
01072   DBusMessage *message;
01073 
01074   _dbus_return_val_if_fail (path != NULL, NULL);
01075   _dbus_return_val_if_fail (method != NULL, NULL);
01076   _dbus_return_val_if_fail (destination == NULL ||
01077                             _dbus_check_is_valid_bus_name (destination), NULL);
01078   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01079   _dbus_return_val_if_fail (interface == NULL ||
01080                             _dbus_check_is_valid_interface (interface), NULL);
01081   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01082 
01083   message = dbus_message_new_empty_header ();
01084   if (message == NULL)
01085     return NULL;
01086 
01087   if (!_dbus_header_create (&message->header,
01088                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01089                             destination, path, interface, method, NULL))
01090     {
01091       dbus_message_unref (message);
01092       return NULL;
01093     }
01094 
01095   return message;
01096 }
01097 
01105 DBusMessage*
01106 dbus_message_new_method_return (DBusMessage *method_call)
01107 {
01108   DBusMessage *message;
01109   const char *sender;
01110 
01111   _dbus_return_val_if_fail (method_call != NULL, NULL);
01112 
01113   sender = dbus_message_get_sender (method_call);
01114 
01115   /* sender is allowed to be null here in peer-to-peer case */
01116 
01117   message = dbus_message_new_empty_header ();
01118   if (message == NULL)
01119     return NULL;
01120 
01121   if (!_dbus_header_create (&message->header,
01122                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01123                             sender, NULL, NULL, NULL, NULL))
01124     {
01125       dbus_message_unref (message);
01126       return NULL;
01127     }
01128 
01129   dbus_message_set_no_reply (message, TRUE);
01130 
01131   if (!dbus_message_set_reply_serial (message,
01132                                       dbus_message_get_serial (method_call)))
01133     {
01134       dbus_message_unref (message);
01135       return NULL;
01136     }
01137 
01138   return message;
01139 }
01140 
01155 DBusMessage*
01156 dbus_message_new_signal (const char *path,
01157                          const char *interface,
01158                          const char *name)
01159 {
01160   DBusMessage *message;
01161 
01162   _dbus_return_val_if_fail (path != NULL, NULL);
01163   _dbus_return_val_if_fail (interface != NULL, NULL);
01164   _dbus_return_val_if_fail (name != NULL, NULL);
01165   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01166   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
01167   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01168 
01169   message = dbus_message_new_empty_header ();
01170   if (message == NULL)
01171     return NULL;
01172 
01173   if (!_dbus_header_create (&message->header,
01174                             DBUS_MESSAGE_TYPE_SIGNAL,
01175                             NULL, path, interface, name, NULL))
01176     {
01177       dbus_message_unref (message);
01178       return NULL;
01179     }
01180 
01181   dbus_message_set_no_reply (message, TRUE);
01182 
01183   return message;
01184 }
01185 
01200 DBusMessage*
01201 dbus_message_new_error (DBusMessage *reply_to,
01202                         const char  *error_name,
01203                         const char  *error_message)
01204 {
01205   DBusMessage *message;
01206   const char *sender;
01207   DBusMessageIter iter;
01208 
01209   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01210   _dbus_return_val_if_fail (error_name != NULL, NULL);
01211   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01212 
01213   sender = dbus_message_get_sender (reply_to);
01214 
01215   /* sender may be NULL for non-message-bus case or
01216    * when the message bus is dealing with an unregistered
01217    * connection.
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_MESSAGE_TYPE_ERROR,
01225                             sender, NULL, NULL, NULL, error_name))
01226     {
01227       dbus_message_unref (message);
01228       return NULL;
01229     }
01230 
01231   dbus_message_set_no_reply (message, TRUE);
01232 
01233   if (!dbus_message_set_reply_serial (message,
01234                                       dbus_message_get_serial (reply_to)))
01235     {
01236       dbus_message_unref (message);
01237       return NULL;
01238     }
01239 
01240   if (error_message != NULL)
01241     {
01242       dbus_message_iter_init_append (message, &iter);
01243       if (!dbus_message_iter_append_basic (&iter,
01244                                            DBUS_TYPE_STRING,
01245                                            &error_message))
01246         {
01247           dbus_message_unref (message);
01248           return NULL;
01249         }
01250     }
01251 
01252   return message;
01253 }
01254 
01271 DBusMessage*
01272 dbus_message_new_error_printf (DBusMessage *reply_to,
01273                                const char  *error_name,
01274                                const char  *error_format,
01275                                ...)
01276 {
01277   va_list args;
01278   DBusString str;
01279   DBusMessage *message;
01280 
01281   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01282   _dbus_return_val_if_fail (error_name != NULL, NULL);
01283   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01284 
01285   if (!_dbus_string_init (&str))
01286     return NULL;
01287 
01288   va_start (args, error_format);
01289 
01290   if (_dbus_string_append_printf_valist (&str, error_format, args))
01291     message = dbus_message_new_error (reply_to, error_name,
01292                                       _dbus_string_get_const_data (&str));
01293   else
01294     message = NULL;
01295 
01296   _dbus_string_free (&str);
01297 
01298   va_end (args);
01299 
01300   return message;
01301 }
01302 
01303 
01314 DBusMessage *
01315 dbus_message_copy (const DBusMessage *message)
01316 {
01317   DBusMessage *retval;
01318 
01319   _dbus_return_val_if_fail (message != NULL, NULL);
01320 
01321   retval = dbus_new0 (DBusMessage, 1);
01322   if (retval == NULL)
01323     return NULL;
01324 
01325   retval->refcount.value = 1;
01326   retval->byte_order = message->byte_order;
01327   retval->locked = FALSE;
01328 #ifndef DBUS_DISABLE_CHECKS
01329   retval->generation = message->generation;
01330 #endif
01331 
01332   if (!_dbus_header_copy (&message->header, &retval->header))
01333     {
01334       dbus_free (retval);
01335       return NULL;
01336     }
01337 
01338   if (!_dbus_string_init_preallocated (&retval->body,
01339                                        _dbus_string_get_length (&message->body)))
01340     {
01341       _dbus_header_free (&retval->header);
01342       dbus_free (retval);
01343       return NULL;
01344     }
01345 
01346   if (!_dbus_string_copy (&message->body, 0,
01347                           &retval->body, 0))
01348     goto failed_copy;
01349 
01350   return retval;
01351 
01352  failed_copy:
01353   _dbus_header_free (&retval->header);
01354   _dbus_string_free (&retval->body);
01355   dbus_free (retval);
01356 
01357   return NULL;
01358 }
01359 
01360 
01368 DBusMessage *
01369 dbus_message_ref (DBusMessage *message)
01370 {
01371   dbus_int32_t old_refcount;
01372 
01373   _dbus_return_val_if_fail (message != NULL, NULL);
01374   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01375   _dbus_return_val_if_fail (!message->in_cache, NULL);
01376   
01377   old_refcount = _dbus_atomic_inc (&message->refcount);
01378   _dbus_assert (old_refcount >= 1);
01379 
01380   return message;
01381 }
01382 
01390 void
01391 dbus_message_unref (DBusMessage *message)
01392 {
01393  dbus_int32_t old_refcount;
01394 
01395   _dbus_return_if_fail (message != NULL);
01396   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01397   _dbus_return_if_fail (!message->in_cache);
01398 
01399   old_refcount = _dbus_atomic_dec (&message->refcount);
01400 
01401   _dbus_assert (old_refcount >= 0);
01402 
01403   if (old_refcount == 1)
01404     {
01405       /* Calls application callbacks! */
01406       dbus_message_cache_or_finalize (message);
01407     }
01408 }
01409 
01420 int
01421 dbus_message_get_type (DBusMessage *message)
01422 {
01423   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01424 
01425   return _dbus_header_get_message_type (&message->header);
01426 }
01427 
01485 dbus_bool_t
01486 dbus_message_append_args (DBusMessage *message,
01487                           int          first_arg_type,
01488                           ...)
01489 {
01490   dbus_bool_t retval;
01491   va_list var_args;
01492 
01493   _dbus_return_val_if_fail (message != NULL, FALSE);
01494 
01495   va_start (var_args, first_arg_type);
01496   retval = dbus_message_append_args_valist (message,
01497                                             first_arg_type,
01498                                             var_args);
01499   va_end (var_args);
01500 
01501   return retval;
01502 }
01503 
01517 dbus_bool_t
01518 dbus_message_append_args_valist (DBusMessage *message,
01519                                  int          first_arg_type,
01520                                  va_list      var_args)
01521 {
01522   int type;
01523   DBusMessageIter iter;
01524 
01525   _dbus_return_val_if_fail (message != NULL, FALSE);
01526 
01527   type = first_arg_type;
01528 
01529   dbus_message_iter_init_append (message, &iter);
01530 
01531   while (type != DBUS_TYPE_INVALID)
01532     {
01533       if (dbus_type_is_basic (type))
01534         {
01535           const DBusBasicValue *value;
01536           value = va_arg (var_args, const DBusBasicValue*);
01537 
01538           if (!dbus_message_iter_append_basic (&iter,
01539                                                type,
01540                                                value))
01541             goto failed;
01542         }
01543       else if (type == DBUS_TYPE_ARRAY)
01544         {
01545           int element_type;
01546           DBusMessageIter array;
01547           char buf[2];
01548 
01549           element_type = va_arg (var_args, int);
01550               
01551           buf[0] = element_type;
01552           buf[1] = '\0';
01553           if (!dbus_message_iter_open_container (&iter,
01554                                                  DBUS_TYPE_ARRAY,
01555                                                  buf,
01556                                                  &array))
01557             goto failed;
01558           
01559           if (dbus_type_is_fixed (element_type))
01560             {
01561               const DBusBasicValue **value;
01562               int n_elements;
01563 
01564               value = va_arg (var_args, const DBusBasicValue**);
01565               n_elements = va_arg (var_args, int);
01566               
01567               if (!dbus_message_iter_append_fixed_array (&array,
01568                                                          element_type,
01569                                                          value,
01570                                                          n_elements)) {
01571                 dbus_message_iter_abandon_container (&iter, &array);
01572                 goto failed;
01573               }
01574             }
01575           else if (element_type == DBUS_TYPE_STRING ||
01576                    element_type == DBUS_TYPE_SIGNATURE ||
01577                    element_type == DBUS_TYPE_OBJECT_PATH)
01578             {
01579               const char ***value_p;
01580               const char **value;
01581               int n_elements;
01582               int i;
01583               
01584               value_p = va_arg (var_args, const char***);
01585               n_elements = va_arg (var_args, int);
01586 
01587               value = *value_p;
01588               
01589               i = 0;
01590               while (i < n_elements)
01591                 {
01592                   if (!dbus_message_iter_append_basic (&array,
01593                                                        element_type,
01594                                                        &value[i])) {
01595                     dbus_message_iter_abandon_container (&iter, &array);
01596                     goto failed;
01597                   }
01598                   ++i;
01599                 }
01600             }
01601           else
01602             {
01603               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01604                           _dbus_type_to_string (element_type),
01605                           _DBUS_FUNCTION_NAME);
01606               goto failed;
01607             }
01608 
01609           if (!dbus_message_iter_close_container (&iter, &array))
01610             goto failed;
01611         }
01612 #ifndef DBUS_DISABLE_CHECKS
01613       else
01614         {
01615           _dbus_warn ("type %s isn't supported yet in %s\n",
01616                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01617           goto failed;
01618         }
01619 #endif
01620 
01621       type = va_arg (var_args, int);
01622     }
01623 
01624   return TRUE;
01625 
01626  failed:
01627   return FALSE;
01628 }
01629 
01665 dbus_bool_t
01666 dbus_message_get_args (DBusMessage     *message,
01667                        DBusError       *error,
01668                        int              first_arg_type,
01669                        ...)
01670 {
01671   dbus_bool_t retval;
01672   va_list var_args;
01673 
01674   _dbus_return_val_if_fail (message != NULL, FALSE);
01675   _dbus_return_val_if_error_is_set (error, FALSE);
01676 
01677   va_start (var_args, first_arg_type);
01678   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01679   va_end (var_args);
01680 
01681   return retval;
01682 }
01683 
01694 dbus_bool_t
01695 dbus_message_get_args_valist (DBusMessage     *message,
01696                               DBusError       *error,
01697                               int              first_arg_type,
01698                               va_list          var_args)
01699 {
01700   DBusMessageIter iter;
01701 
01702   _dbus_return_val_if_fail (message != NULL, FALSE);
01703   _dbus_return_val_if_error_is_set (error, FALSE);
01704 
01705   dbus_message_iter_init (message, &iter);
01706   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01707 }
01708 
01709 static void
01710 _dbus_message_iter_init_common (DBusMessage         *message,
01711                                 DBusMessageRealIter *real,
01712                                 int                  iter_type)
01713 {
01714   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01715 
01716   /* Since the iterator will read or write who-knows-what from the
01717    * message, we need to get in the right byte order
01718    */
01719   ensure_byte_order (message);
01720   
01721   real->message = message;
01722   real->changed_stamp = message->changed_stamp;
01723   real->iter_type = iter_type;
01724   real->sig_refcount = 0;
01725 }
01726 
01749 dbus_bool_t
01750 dbus_message_iter_init (DBusMessage     *message,
01751                         DBusMessageIter *iter)
01752 {
01753   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01754   const DBusString *type_str;
01755   int type_pos;
01756 
01757   _dbus_return_val_if_fail (message != NULL, FALSE);
01758   _dbus_return_val_if_fail (iter != NULL, FALSE);
01759 
01760   get_const_signature (&message->header, &type_str, &type_pos);
01761 
01762   _dbus_message_iter_init_common (message, real,
01763                                   DBUS_MESSAGE_ITER_TYPE_READER);
01764 
01765   _dbus_type_reader_init (&real->u.reader,
01766                           message->byte_order,
01767                           type_str, type_pos,
01768                           &message->body,
01769                           0);
01770 
01771   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
01772 }
01773 
01780 dbus_bool_t
01781 dbus_message_iter_has_next (DBusMessageIter *iter)
01782 {
01783   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01784 
01785   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01786   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01787 
01788   return _dbus_type_reader_has_next (&real->u.reader);
01789 }
01790 
01799 dbus_bool_t
01800 dbus_message_iter_next (DBusMessageIter *iter)
01801 {
01802   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01803 
01804   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01805   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01806 
01807   return _dbus_type_reader_next (&real->u.reader);
01808 }
01809 
01824 int
01825 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
01826 {
01827   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01828 
01829   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01830   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01831 
01832   return _dbus_type_reader_get_current_type (&real->u.reader);
01833 }
01834 
01843 int
01844 dbus_message_iter_get_element_type (DBusMessageIter *iter)
01845 {
01846   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01847 
01848   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01849   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
01850   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
01851 
01852   return _dbus_type_reader_get_element_type (&real->u.reader);
01853 }
01854 
01880 void
01881 dbus_message_iter_recurse (DBusMessageIter  *iter,
01882                            DBusMessageIter  *sub)
01883 {
01884   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01885   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
01886 
01887   _dbus_return_if_fail (_dbus_message_iter_check (real));
01888   _dbus_return_if_fail (sub != NULL);
01889 
01890   *real_sub = *real;
01891   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
01892 }
01893 
01905 char *
01906 dbus_message_iter_get_signature (DBusMessageIter *iter)
01907 {
01908   const DBusString *sig;
01909   DBusString retstr;
01910   char *ret;
01911   int start, len;
01912   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01913 
01914   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
01915 
01916   if (!_dbus_string_init (&retstr))
01917     return NULL;
01918 
01919   _dbus_type_reader_get_signature (&real->u.reader, &sig,
01920                                    &start, &len);
01921   if (!_dbus_string_append_len (&retstr,
01922                                 _dbus_string_get_const_data (sig) + start,
01923                                 len))
01924     return NULL;
01925   if (!_dbus_string_steal_data (&retstr, &ret))
01926     return NULL;
01927   _dbus_string_free (&retstr);
01928   return ret;
01929 }
01930 
01971 void
01972 dbus_message_iter_get_basic (DBusMessageIter  *iter,
01973                              void             *value)
01974 {
01975   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01976 
01977   _dbus_return_if_fail (_dbus_message_iter_check (real));
01978   _dbus_return_if_fail (value != NULL);
01979 
01980   _dbus_type_reader_read_basic (&real->u.reader,
01981                                 value);
01982 }
01983 
02002 int
02003 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02004 {
02005   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02006 
02007   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02008 
02009   return _dbus_type_reader_get_array_length (&real->u.reader);
02010 }
02011 
02043 void
02044 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02045                                    void             *value,
02046                                    int              *n_elements)
02047 {
02048   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02049   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02050 
02051   _dbus_return_if_fail (_dbus_message_iter_check (real));
02052   _dbus_return_if_fail (value != NULL);
02053   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02054                          dbus_type_is_fixed (subtype));
02055 
02056   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02057                                       value, n_elements);
02058 }
02059 
02071 void
02072 dbus_message_iter_init_append (DBusMessage     *message,
02073                                DBusMessageIter *iter)
02074 {
02075   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02076 
02077   _dbus_return_if_fail (message != NULL);
02078   _dbus_return_if_fail (iter != NULL);
02079 
02080   _dbus_message_iter_init_common (message, real,
02081                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02082 
02083   /* We create the signature string and point iterators at it "on demand"
02084    * when a value is actually appended. That means that init() never fails
02085    * due to OOM.
02086    */
02087   _dbus_type_writer_init_types_delayed (&real->u.writer,
02088                                         message->byte_order,
02089                                         &message->body,
02090                                         _dbus_string_get_length (&message->body));
02091 }
02092 
02101 static dbus_bool_t
02102 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02103 {
02104   DBusString *str;
02105   const DBusString *current_sig;
02106   int current_sig_pos;
02107 
02108   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02109 
02110   if (real->u.writer.type_str != NULL)
02111     {
02112       _dbus_assert (real->sig_refcount > 0);
02113       real->sig_refcount += 1;
02114       return TRUE;
02115     }
02116 
02117   str = dbus_new (DBusString, 1);
02118   if (str == NULL)
02119     return FALSE;
02120 
02121   if (!_dbus_header_get_field_raw (&real->message->header,
02122                                    DBUS_HEADER_FIELD_SIGNATURE,
02123                                    &current_sig, &current_sig_pos))
02124     current_sig = NULL;
02125 
02126   if (current_sig)
02127     {
02128       int current_len;
02129 
02130       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02131       current_sig_pos += 1; /* move on to sig data */
02132 
02133       if (!_dbus_string_init_preallocated (str, current_len + 4))
02134         {
02135           dbus_free (str);
02136           return FALSE;
02137         }
02138 
02139       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02140                                   str, 0))
02141         {
02142           _dbus_string_free (str);
02143           dbus_free (str);
02144           return FALSE;
02145         }
02146     }
02147   else
02148     {
02149       if (!_dbus_string_init_preallocated (str, 4))
02150         {
02151           dbus_free (str);
02152           return FALSE;
02153         }
02154     }
02155 
02156   real->sig_refcount = 1;
02157 
02158   _dbus_type_writer_add_types (&real->u.writer,
02159                                str, _dbus_string_get_length (str));
02160   return TRUE;
02161 }
02162 
02172 static dbus_bool_t
02173 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02174 {
02175   DBusString *str;
02176   const char *v_STRING;
02177   dbus_bool_t retval;
02178 
02179   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02180   _dbus_assert (real->u.writer.type_str != NULL);
02181   _dbus_assert (real->sig_refcount > 0);
02182 
02183   real->sig_refcount -= 1;
02184 
02185   if (real->sig_refcount > 0)
02186     return TRUE;
02187   _dbus_assert (real->sig_refcount == 0);
02188 
02189   retval = TRUE;
02190 
02191   str = real->u.writer.type_str;
02192 
02193   v_STRING = _dbus_string_get_const_data (str);
02194   if (!_dbus_header_set_field_basic (&real->message->header,
02195                                      DBUS_HEADER_FIELD_SIGNATURE,
02196                                      DBUS_TYPE_SIGNATURE,
02197                                      &v_STRING))
02198     retval = FALSE;
02199 
02200   _dbus_type_writer_remove_types (&real->u.writer);
02201   _dbus_string_free (str);
02202   dbus_free (str);
02203 
02204   return retval;
02205 }
02206 
02214 static void
02215 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02216 {
02217   DBusString *str;
02218 
02219   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02220   _dbus_assert (real->u.writer.type_str != NULL);
02221   _dbus_assert (real->sig_refcount > 0);
02222 
02223   real->sig_refcount -= 1;
02224 
02225   if (real->sig_refcount > 0)
02226     return;
02227   _dbus_assert (real->sig_refcount == 0);
02228 
02229   str = real->u.writer.type_str;
02230 
02231   _dbus_type_writer_remove_types (&real->u.writer);
02232   _dbus_string_free (str);
02233   dbus_free (str);
02234 }
02235 
02236 #ifndef DBUS_DISABLE_CHECKS
02237 static dbus_bool_t
02238 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02239 {
02240   if (!_dbus_message_iter_check (iter))
02241     return FALSE;
02242 
02243   if (iter->message->locked)
02244     {
02245       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02246       return FALSE;
02247     }
02248 
02249   return TRUE;
02250 }
02251 #endif /* DBUS_DISABLE_CHECKS */
02252 
02268 dbus_bool_t
02269 dbus_message_iter_append_basic (DBusMessageIter *iter,
02270                                 int              type,
02271                                 const void      *value)
02272 {
02273   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02274   dbus_bool_t ret;
02275 
02276   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02277   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02278   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02279   _dbus_return_val_if_fail (value != NULL, FALSE);
02280 
02281   if (!_dbus_message_iter_open_signature (real))
02282     return FALSE;
02283 
02284   ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02285 
02286   if (!_dbus_message_iter_close_signature (real))
02287     ret = FALSE;
02288 
02289   return ret;
02290 }
02291 
02327 dbus_bool_t
02328 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02329                                       int              element_type,
02330                                       const void      *value,
02331                                       int              n_elements)
02332 {
02333   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02334   dbus_bool_t ret;
02335 
02336   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02337   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02338   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type), FALSE);
02339   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02340   _dbus_return_val_if_fail (value != NULL, FALSE);
02341   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02342   _dbus_return_val_if_fail (n_elements <=
02343                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02344                             FALSE);
02345 
02346   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02347 
02348   return ret;
02349 }
02350 
02372 dbus_bool_t
02373 dbus_message_iter_open_container (DBusMessageIter *iter,
02374                                   int              type,
02375                                   const char      *contained_signature,
02376                                   DBusMessageIter *sub)
02377 {
02378   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02379   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02380   DBusString contained_str;
02381 
02382   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02383   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02384   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02385   _dbus_return_val_if_fail (sub != NULL, FALSE);
02386   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02387                              contained_signature == NULL) ||
02388                             (type == DBUS_TYPE_DICT_ENTRY &&
02389                              contained_signature == NULL) ||
02390                             (type == DBUS_TYPE_VARIANT &&
02391                              contained_signature != NULL) ||
02392                             (type == DBUS_TYPE_ARRAY &&
02393                              contained_signature != NULL), FALSE);
02394   
02395   /* this would fail if the contained_signature is a dict entry, since
02396    * dict entries are invalid signatures standalone (they must be in
02397    * an array)
02398    */
02399   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02400                             (contained_signature == NULL ||
02401                              _dbus_check_is_valid_signature (contained_signature)),
02402                             FALSE);
02403 
02404   if (!_dbus_message_iter_open_signature (real))
02405     return FALSE;
02406 
02407   *real_sub = *real;
02408 
02409   if (contained_signature != NULL)
02410     {
02411       _dbus_string_init_const (&contained_str, contained_signature);
02412 
02413       return _dbus_type_writer_recurse (&real->u.writer,
02414                                         type,
02415                                         &contained_str, 0,
02416                                         &real_sub->u.writer);
02417     }
02418   else
02419     {
02420       return _dbus_type_writer_recurse (&real->u.writer,
02421                                         type,
02422                                         NULL, 0,
02423                                         &real_sub->u.writer);
02424     } 
02425 }
02426 
02427 
02441 dbus_bool_t
02442 dbus_message_iter_close_container (DBusMessageIter *iter,
02443                                    DBusMessageIter *sub)
02444 {
02445   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02446   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02447   dbus_bool_t ret;
02448 
02449   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02450   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02451   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02452   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02453 
02454   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02455                                      &real_sub->u.writer);
02456 
02457   if (!_dbus_message_iter_close_signature (real))
02458     ret = FALSE;
02459 
02460   return ret;
02461 }
02462 
02474 void
02475 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02476                                      DBusMessageIter *sub)
02477 {
02478   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02479   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02480 
02481   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02482   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02483   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02484   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02485 
02486   _dbus_message_iter_abandon_signature (real);
02487 }
02488 
02505 void
02506 dbus_message_set_no_reply (DBusMessage *message,
02507                            dbus_bool_t  no_reply)
02508 {
02509   _dbus_return_if_fail (message != NULL);
02510   _dbus_return_if_fail (!message->locked);
02511 
02512   _dbus_header_toggle_flag (&message->header,
02513                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02514                             no_reply);
02515 }
02516 
02524 dbus_bool_t
02525 dbus_message_get_no_reply (DBusMessage *message)
02526 {
02527   _dbus_return_val_if_fail (message != NULL, FALSE);
02528 
02529   return _dbus_header_get_flag (&message->header,
02530                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02531 }
02532 
02547 void
02548 dbus_message_set_auto_start (DBusMessage *message,
02549                              dbus_bool_t  auto_start)
02550 {
02551   _dbus_return_if_fail (message != NULL);
02552   _dbus_return_if_fail (!message->locked);
02553 
02554   _dbus_header_toggle_flag (&message->header,
02555                             DBUS_HEADER_FLAG_NO_AUTO_START,
02556                             !auto_start);
02557 }
02558 
02566 dbus_bool_t
02567 dbus_message_get_auto_start (DBusMessage *message)
02568 {
02569   _dbus_return_val_if_fail (message != NULL, FALSE);
02570 
02571   return !_dbus_header_get_flag (&message->header,
02572                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02573 }
02574 
02575 
02588 dbus_bool_t
02589 dbus_message_set_path (DBusMessage   *message,
02590                        const char    *object_path)
02591 {
02592   _dbus_return_val_if_fail (message != NULL, FALSE);
02593   _dbus_return_val_if_fail (!message->locked, FALSE);
02594   _dbus_return_val_if_fail (object_path == NULL ||
02595                             _dbus_check_is_valid_path (object_path),
02596                             FALSE);
02597 
02598   return set_or_delete_string_field (message,
02599                                      DBUS_HEADER_FIELD_PATH,
02600                                      DBUS_TYPE_OBJECT_PATH,
02601                                      object_path);
02602 }
02603 
02617 const char*
02618 dbus_message_get_path (DBusMessage   *message)
02619 {
02620   const char *v;
02621 
02622   _dbus_return_val_if_fail (message != NULL, NULL);
02623 
02624   v = NULL; /* in case field doesn't exist */
02625   _dbus_header_get_field_basic (&message->header,
02626                                 DBUS_HEADER_FIELD_PATH,
02627                                 DBUS_TYPE_OBJECT_PATH,
02628                                 &v);
02629   return v;
02630 }
02631 
02641 dbus_bool_t
02642 dbus_message_has_path (DBusMessage   *message,
02643                        const char    *path)
02644 {
02645   const char *msg_path;
02646   msg_path = dbus_message_get_path (message);
02647   
02648   if (msg_path == NULL)
02649     {
02650       if (path == NULL)
02651         return TRUE;
02652       else
02653         return FALSE;
02654     }
02655 
02656   if (path == NULL)
02657     return FALSE;
02658    
02659   if (strcmp (msg_path, path) == 0)
02660     return TRUE;
02661 
02662   return FALSE;
02663 }
02664 
02685 dbus_bool_t
02686 dbus_message_get_path_decomposed (DBusMessage   *message,
02687                                   char        ***path)
02688 {
02689   const char *v;
02690 
02691   _dbus_return_val_if_fail (message != NULL, FALSE);
02692   _dbus_return_val_if_fail (path != NULL, FALSE);
02693 
02694   *path = NULL;
02695 
02696   v = dbus_message_get_path (message);
02697   if (v != NULL)
02698     {
02699       if (!_dbus_decompose_path (v, strlen (v),
02700                                  path, NULL))
02701         return FALSE;
02702     }
02703   return TRUE;
02704 }
02705 
02719 dbus_bool_t
02720 dbus_message_set_interface (DBusMessage  *message,
02721                             const char   *interface)
02722 {
02723   _dbus_return_val_if_fail (message != NULL, FALSE);
02724   _dbus_return_val_if_fail (!message->locked, FALSE);
02725   _dbus_return_val_if_fail (interface == NULL ||
02726                             _dbus_check_is_valid_interface (interface),
02727                             FALSE);
02728 
02729   return set_or_delete_string_field (message,
02730                                      DBUS_HEADER_FIELD_INTERFACE,
02731                                      DBUS_TYPE_STRING,
02732                                      interface);
02733 }
02734 
02748 const char*
02749 dbus_message_get_interface (DBusMessage *message)
02750 {
02751   const char *v;
02752 
02753   _dbus_return_val_if_fail (message != NULL, NULL);
02754 
02755   v = NULL; /* in case field doesn't exist */
02756   _dbus_header_get_field_basic (&message->header,
02757                                 DBUS_HEADER_FIELD_INTERFACE,
02758                                 DBUS_TYPE_STRING,
02759                                 &v);
02760   return v;
02761 }
02762 
02770 dbus_bool_t
02771 dbus_message_has_interface (DBusMessage   *message,
02772                             const char    *interface)
02773 {
02774   const char *msg_interface;
02775   msg_interface = dbus_message_get_interface (message);
02776    
02777   if (msg_interface == NULL)
02778     {
02779       if (interface == NULL)
02780         return TRUE;
02781       else
02782         return FALSE;
02783     }
02784 
02785   if (interface == NULL)
02786     return FALSE;
02787      
02788   if (strcmp (msg_interface, interface) == 0)
02789     return TRUE;
02790 
02791   return FALSE;
02792 
02793 }
02794 
02807 dbus_bool_t
02808 dbus_message_set_member (DBusMessage  *message,
02809                          const char   *member)
02810 {
02811   _dbus_return_val_if_fail (message != NULL, FALSE);
02812   _dbus_return_val_if_fail (!message->locked, FALSE);
02813   _dbus_return_val_if_fail (member == NULL ||
02814                             _dbus_check_is_valid_member (member),
02815                             FALSE);
02816 
02817   return set_or_delete_string_field (message,
02818                                      DBUS_HEADER_FIELD_MEMBER,
02819                                      DBUS_TYPE_STRING,
02820                                      member);
02821 }
02822 
02834 const char*
02835 dbus_message_get_member (DBusMessage *message)
02836 {
02837   const char *v;
02838 
02839   _dbus_return_val_if_fail (message != NULL, NULL);
02840 
02841   v = NULL; /* in case field doesn't exist */
02842   _dbus_header_get_field_basic (&message->header,
02843                                 DBUS_HEADER_FIELD_MEMBER,
02844                                 DBUS_TYPE_STRING,
02845                                 &v);
02846   return v;
02847 }
02848 
02856 dbus_bool_t
02857 dbus_message_has_member (DBusMessage   *message,
02858                          const char    *member)
02859 {
02860   const char *msg_member;
02861   msg_member = dbus_message_get_member (message);
02862  
02863   if (msg_member == NULL)
02864     {
02865       if (member == NULL)
02866         return TRUE;
02867       else
02868         return FALSE;
02869     }
02870 
02871   if (member == NULL)
02872     return FALSE;
02873     
02874   if (strcmp (msg_member, member) == 0)
02875     return TRUE;
02876 
02877   return FALSE;
02878 
02879 }
02880 
02892 dbus_bool_t
02893 dbus_message_set_error_name (DBusMessage  *message,
02894                              const char   *error_name)
02895 {
02896   _dbus_return_val_if_fail (message != NULL, FALSE);
02897   _dbus_return_val_if_fail (!message->locked, FALSE);
02898   _dbus_return_val_if_fail (error_name == NULL ||
02899                             _dbus_check_is_valid_error_name (error_name),
02900                             FALSE);
02901 
02902   return set_or_delete_string_field (message,
02903                                      DBUS_HEADER_FIELD_ERROR_NAME,
02904                                      DBUS_TYPE_STRING,
02905                                      error_name);
02906 }
02907 
02918 const char*
02919 dbus_message_get_error_name (DBusMessage *message)
02920 {
02921   const char *v;
02922 
02923   _dbus_return_val_if_fail (message != NULL, NULL);
02924 
02925   v = NULL; /* in case field doesn't exist */
02926   _dbus_header_get_field_basic (&message->header,
02927                                 DBUS_HEADER_FIELD_ERROR_NAME,
02928                                 DBUS_TYPE_STRING,
02929                                 &v);
02930   return v;
02931 }
02932 
02946 dbus_bool_t
02947 dbus_message_set_destination (DBusMessage  *message,
02948                               const char   *destination)
02949 {
02950   _dbus_return_val_if_fail (message != NULL, FALSE);
02951   _dbus_return_val_if_fail (!message->locked, FALSE);
02952   _dbus_return_val_if_fail (destination == NULL ||
02953                             _dbus_check_is_valid_bus_name (destination),
02954                             FALSE);
02955 
02956   return set_or_delete_string_field (message,
02957                                      DBUS_HEADER_FIELD_DESTINATION,
02958                                      DBUS_TYPE_STRING,
02959                                      destination);
02960 }
02961 
02971 const char*
02972 dbus_message_get_destination (DBusMessage *message)
02973 {
02974   const char *v;
02975 
02976   _dbus_return_val_if_fail (message != NULL, NULL);
02977 
02978   v = NULL; /* in case field doesn't exist */
02979   _dbus_header_get_field_basic (&message->header,
02980                                 DBUS_HEADER_FIELD_DESTINATION,
02981                                 DBUS_TYPE_STRING,
02982                                 &v);
02983   return v;
02984 }
02985 
03000 dbus_bool_t
03001 dbus_message_set_sender (DBusMessage  *message,
03002                          const char   *sender)
03003 {
03004   _dbus_return_val_if_fail (message != NULL, FALSE);
03005   _dbus_return_val_if_fail (!message->locked, FALSE);
03006   _dbus_return_val_if_fail (sender == NULL ||
03007                             _dbus_check_is_valid_bus_name (sender),
03008                             FALSE);
03009 
03010   return set_or_delete_string_field (message,
03011                                      DBUS_HEADER_FIELD_SENDER,
03012                                      DBUS_TYPE_STRING,
03013                                      sender);
03014 }
03015 
03031 const char*
03032 dbus_message_get_sender (DBusMessage *message)
03033 {
03034   const char *v;
03035 
03036   _dbus_return_val_if_fail (message != NULL, NULL);
03037 
03038   v = NULL; /* in case field doesn't exist */
03039   _dbus_header_get_field_basic (&message->header,
03040                                 DBUS_HEADER_FIELD_SENDER,
03041                                 DBUS_TYPE_STRING,
03042                                 &v);
03043   return v;
03044 }
03045 
03064 const char*
03065 dbus_message_get_signature (DBusMessage *message)
03066 {
03067   const DBusString *type_str;
03068   int type_pos;
03069 
03070   _dbus_return_val_if_fail (message != NULL, NULL);
03071 
03072   get_const_signature (&message->header, &type_str, &type_pos);
03073 
03074   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03075 }
03076 
03077 static dbus_bool_t
03078 _dbus_message_has_type_interface_member (DBusMessage *message,
03079                                          int          type,
03080                                          const char  *interface,
03081                                          const char  *member)
03082 {
03083   const char *n;
03084 
03085   _dbus_assert (message != NULL);
03086   _dbus_assert (interface != NULL);
03087   _dbus_assert (member != NULL);
03088 
03089   if (dbus_message_get_type (message) != type)
03090     return FALSE;
03091 
03092   /* Optimize by checking the short member name first
03093    * instead of the longer interface name
03094    */
03095 
03096   n = dbus_message_get_member (message);
03097 
03098   if (n && strcmp (n, member) == 0)
03099     {
03100       n = dbus_message_get_interface (message);
03101 
03102       if (n == NULL || strcmp (n, interface) == 0)
03103         return TRUE;
03104     }
03105 
03106   return FALSE;
03107 }
03108 
03123 dbus_bool_t
03124 dbus_message_is_method_call (DBusMessage *message,
03125                              const char  *interface,
03126                              const char  *method)
03127 {
03128   _dbus_return_val_if_fail (message != NULL, FALSE);
03129   _dbus_return_val_if_fail (interface != NULL, FALSE);
03130   _dbus_return_val_if_fail (method != NULL, FALSE);
03131   /* don't check that interface/method are valid since it would be
03132    * expensive, and not catch many common errors
03133    */
03134 
03135   return _dbus_message_has_type_interface_member (message,
03136                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03137                                                   interface, method);
03138 }
03139 
03151 dbus_bool_t
03152 dbus_message_is_signal (DBusMessage *message,
03153                         const char  *interface,
03154                         const char  *signal_name)
03155 {
03156   _dbus_return_val_if_fail (message != NULL, FALSE);
03157   _dbus_return_val_if_fail (interface != NULL, FALSE);
03158   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03159   /* don't check that interface/name are valid since it would be
03160    * expensive, and not catch many common errors
03161    */
03162 
03163   return _dbus_message_has_type_interface_member (message,
03164                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03165                                                   interface, signal_name);
03166 }
03167 
03178 dbus_bool_t
03179 dbus_message_is_error (DBusMessage *message,
03180                        const char  *error_name)
03181 {
03182   const char *n;
03183 
03184   _dbus_return_val_if_fail (message != NULL, FALSE);
03185   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03186   /* don't check that error_name is valid since it would be expensive,
03187    * and not catch many common errors
03188    */
03189 
03190   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03191     return FALSE;
03192 
03193   n = dbus_message_get_error_name (message);
03194 
03195   if (n && strcmp (n, error_name) == 0)
03196     return TRUE;
03197   else
03198     return FALSE;
03199 }
03200 
03211 dbus_bool_t
03212 dbus_message_has_destination (DBusMessage  *message,
03213                               const char   *name)
03214 {
03215   const char *s;
03216 
03217   _dbus_return_val_if_fail (message != NULL, FALSE);
03218   _dbus_return_val_if_fail (name != NULL, FALSE);
03219   /* don't check that name is valid since it would be expensive, and
03220    * not catch many common errors
03221    */
03222 
03223   s = dbus_message_get_destination (message);
03224 
03225   if (s && strcmp (s, name) == 0)
03226     return TRUE;
03227   else
03228     return FALSE;
03229 }
03230 
03246 dbus_bool_t
03247 dbus_message_has_sender (DBusMessage  *message,
03248                          const char   *name)
03249 {
03250   const char *s;
03251 
03252   _dbus_return_val_if_fail (message != NULL, FALSE);
03253   _dbus_return_val_if_fail (name != NULL, FALSE);
03254   /* don't check that name is valid since it would be expensive, and
03255    * not catch many common errors
03256    */
03257 
03258   s = dbus_message_get_sender (message);
03259 
03260   if (s && strcmp (s, name) == 0)
03261     return TRUE;
03262   else
03263     return FALSE;
03264 }
03265 
03275 dbus_bool_t
03276 dbus_message_has_signature (DBusMessage   *message,
03277                             const char    *signature)
03278 {
03279   const char *s;
03280 
03281   _dbus_return_val_if_fail (message != NULL, FALSE);
03282   _dbus_return_val_if_fail (signature != NULL, FALSE);
03283   /* don't check that signature is valid since it would be expensive,
03284    * and not catch many common errors
03285    */
03286 
03287   s = dbus_message_get_signature (message);
03288 
03289   if (s && strcmp (s, signature) == 0)
03290     return TRUE;
03291   else
03292     return FALSE;
03293 }
03294 
03317 dbus_bool_t
03318 dbus_set_error_from_message (DBusError   *error,
03319                              DBusMessage *message)
03320 {
03321   const char *str;
03322 
03323   _dbus_return_val_if_fail (message != NULL, FALSE);
03324   _dbus_return_val_if_error_is_set (error, FALSE);
03325 
03326   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03327     return FALSE;
03328 
03329   str = NULL;
03330   dbus_message_get_args (message, NULL,
03331                          DBUS_TYPE_STRING, &str,
03332                          DBUS_TYPE_INVALID);
03333 
03334   dbus_set_error (error, dbus_message_get_error_name (message),
03335                   str ? "%s" : NULL, str);
03336 
03337   return TRUE;
03338 }
03339 
03358 #define INITIAL_LOADER_DATA_LEN 32
03359 
03366 DBusMessageLoader*
03367 _dbus_message_loader_new (void)
03368 {
03369   DBusMessageLoader *loader;
03370 
03371   loader = dbus_new0 (DBusMessageLoader, 1);
03372   if (loader == NULL)
03373     return NULL;
03374   
03375   loader->refcount = 1;
03376 
03377   loader->corrupted = FALSE;
03378   loader->corruption_reason = DBUS_VALID;
03379 
03380   /* this can be configured by the app, but defaults to the protocol max */
03381   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03382 
03383   if (!_dbus_string_init (&loader->data))
03384     {
03385       dbus_free (loader);
03386       return NULL;
03387     }
03388 
03389   /* preallocate the buffer for speed, ignore failure */
03390   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03391   _dbus_string_set_length (&loader->data, 0);
03392 
03393   return loader;
03394 }
03395 
03402 DBusMessageLoader *
03403 _dbus_message_loader_ref (DBusMessageLoader *loader)
03404 {
03405   loader->refcount += 1;
03406 
03407   return loader;
03408 }
03409 
03416 void
03417 _dbus_message_loader_unref (DBusMessageLoader *loader)
03418 {
03419   loader->refcount -= 1;
03420   if (loader->refcount == 0)
03421     {
03422       _dbus_list_foreach (&loader->messages,
03423                           (DBusForeachFunction) dbus_message_unref,
03424                           NULL);
03425       _dbus_list_clear (&loader->messages);
03426       _dbus_string_free (&loader->data);
03427       dbus_free (loader);
03428     }
03429 }
03430 
03449 void
03450 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03451                                  DBusString        **buffer)
03452 {
03453   _dbus_assert (!loader->buffer_outstanding);
03454 
03455   *buffer = &loader->data;
03456 
03457   loader->buffer_outstanding = TRUE;
03458 }
03459 
03470 void
03471 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03472                                     DBusString         *buffer,
03473                                     int                 bytes_read)
03474 {
03475   _dbus_assert (loader->buffer_outstanding);
03476   _dbus_assert (buffer == &loader->data);
03477 
03478   loader->buffer_outstanding = FALSE;
03479 }
03480 
03481 /*
03482  * FIXME when we move the header out of the buffer, that memmoves all
03483  * buffered messages. Kind of crappy.
03484  *
03485  * Also we copy the header and body, which is kind of crappy.  To
03486  * avoid this, we have to allow header and body to be in a single
03487  * memory block, which is good for messages we read and bad for
03488  * messages we are creating. But we could move_len() the buffer into
03489  * this single memory block, and move_len() will just swap the buffers
03490  * if you're moving the entire buffer replacing the dest string.
03491  *
03492  * We could also have the message loader tell the transport how many
03493  * bytes to read; so it would first ask for some arbitrary number like
03494  * 256, then if the message was incomplete it would use the
03495  * header/body len to ask for exactly the size of the message (or
03496  * blocks the size of a typical kernel buffer for the socket). That
03497  * way we don't get trailing bytes in the buffer that have to be
03498  * memmoved. Though I suppose we also don't have a chance of reading a
03499  * bunch of small messages at once, so the optimization may be stupid.
03500  *
03501  * Another approach would be to keep a "start" index into
03502  * loader->data and only delete it occasionally, instead of after
03503  * each message is loaded.
03504  *
03505  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03506  */
03507 static dbus_bool_t
03508 load_message (DBusMessageLoader *loader,
03509               DBusMessage       *message,
03510               int                byte_order,
03511               int                fields_array_len,
03512               int                header_len,
03513               int                body_len)
03514 {
03515   dbus_bool_t oom;
03516   DBusValidity validity;
03517   const DBusString *type_str;
03518   int type_pos;
03519   DBusValidationMode mode;
03520 
03521   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03522   
03523   oom = FALSE;
03524 
03525 #if 0
03526   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03527 #endif
03528 
03529   /* 1. VALIDATE AND COPY OVER HEADER */
03530   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03531   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03532 
03533   if (!_dbus_header_load (&message->header,
03534                           mode,
03535                           &validity,
03536                           byte_order,
03537                           fields_array_len,
03538                           header_len,
03539                           body_len,
03540                           &loader->data, 0,
03541                           _dbus_string_get_length (&loader->data)))
03542     {
03543       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03544 
03545       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03546          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03547       _dbus_assert (validity != DBUS_VALID);
03548 
03549       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03550         oom = TRUE;
03551       else
03552         {
03553           loader->corrupted = TRUE;
03554           loader->corruption_reason = validity;
03555         }
03556       goto failed;
03557     }
03558 
03559   _dbus_assert (validity == DBUS_VALID);
03560 
03561   message->byte_order = byte_order;
03562 
03563   /* 2. VALIDATE BODY */
03564   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
03565     {
03566       get_const_signature (&message->header, &type_str, &type_pos);
03567       
03568       /* Because the bytes_remaining arg is NULL, this validates that the
03569        * body is the right length
03570        */
03571       validity = _dbus_validate_body_with_reason (type_str,
03572                                                   type_pos,
03573                                                   byte_order,
03574                                                   NULL,
03575                                                   &loader->data,
03576                                                   header_len,
03577                                                   body_len);
03578       if (validity != DBUS_VALID)
03579         {
03580           _dbus_verbose ("Failed to validate message body code %d\n", validity);
03581 
03582           loader->corrupted = TRUE;
03583           loader->corruption_reason = validity;
03584           
03585           goto failed;
03586         }
03587     }
03588 
03589   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
03590 
03591   if (!_dbus_list_append (&loader->messages, message))
03592     {
03593       _dbus_verbose ("Failed to append new message to loader queue\n");
03594       oom = TRUE;
03595       goto failed;
03596     }
03597 
03598   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
03599   _dbus_assert (_dbus_string_get_length (&loader->data) >=
03600                 (header_len + body_len));
03601 
03602   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
03603     {
03604       _dbus_verbose ("Failed to move body into new message\n");
03605       oom = TRUE;
03606       goto failed;
03607     }
03608 
03609   _dbus_string_delete (&loader->data, 0, header_len + body_len);
03610 
03611   /* don't waste more than 2k of memory */
03612   _dbus_string_compact (&loader->data, 2048);
03613 
03614   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
03615   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
03616 
03617   _dbus_verbose ("Loaded message %p\n", message);
03618 
03619   _dbus_assert (!oom);
03620   _dbus_assert (!loader->corrupted);
03621   _dbus_assert (loader->messages != NULL);
03622   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03623 
03624   return TRUE;
03625 
03626  failed:
03627 
03628   /* Clean up */
03629 
03630   /* does nothing if the message isn't in the list */
03631   _dbus_list_remove_last (&loader->messages, message);
03632   
03633   if (oom)
03634     _dbus_assert (!loader->corrupted);
03635   else
03636     _dbus_assert (loader->corrupted);
03637 
03638   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
03639 
03640   return FALSE;
03641 }
03642 
03657 dbus_bool_t
03658 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
03659 {
03660   while (!loader->corrupted &&
03661          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
03662     {
03663       DBusValidity validity;
03664       int byte_order, fields_array_len, header_len, body_len;
03665 
03666       if (_dbus_header_have_message_untrusted (loader->max_message_size,
03667                                                &validity,
03668                                                &byte_order,
03669                                                &fields_array_len,
03670                                                &header_len,
03671                                                &body_len,
03672                                                &loader->data, 0,
03673                                                _dbus_string_get_length (&loader->data)))
03674         {
03675           DBusMessage *message;
03676 
03677           _dbus_assert (validity == DBUS_VALID);
03678 
03679           message = dbus_message_new_empty_header ();
03680           if (message == NULL)
03681             return FALSE;
03682 
03683           if (!load_message (loader, message,
03684                              byte_order, fields_array_len,
03685                              header_len, body_len))
03686             {
03687               dbus_message_unref (message);
03688               /* load_message() returns false if corrupted or OOM; if
03689                * corrupted then return TRUE for not OOM
03690                */
03691               return loader->corrupted;
03692             }
03693 
03694           _dbus_assert (loader->messages != NULL);
03695           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03696         }
03697       else
03698         {
03699           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
03700                          validity);
03701           if (validity != DBUS_VALID)
03702             {
03703               loader->corrupted = TRUE;
03704               loader->corruption_reason = validity;
03705             }
03706           return TRUE;
03707         }
03708     }
03709 
03710   return TRUE;
03711 }
03712 
03720 DBusMessage*
03721 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
03722 {
03723   if (loader->messages)
03724     return loader->messages->data;
03725   else
03726     return NULL;
03727 }
03728 
03737 DBusMessage*
03738 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
03739 {
03740   return _dbus_list_pop_first (&loader->messages);
03741 }
03742 
03751 DBusList*
03752 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
03753 {
03754   return _dbus_list_pop_first_link (&loader->messages);
03755 }
03756 
03763 void
03764 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
03765                                            DBusList           *link)
03766 {
03767   _dbus_list_prepend_link (&loader->messages, link);
03768 }
03769 
03779 dbus_bool_t
03780 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
03781 {
03782   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
03783                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
03784   return loader->corrupted;
03785 }
03786 
03793 DBusValidity
03794 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
03795 {
03796   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
03797                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
03798 
03799   return loader->corruption_reason;
03800 }
03801 
03808 void
03809 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
03810                                            long                size)
03811 {
03812   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
03813     {
03814       _dbus_verbose ("clamping requested max message size %ld to %d\n",
03815                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
03816       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03817     }
03818   loader->max_message_size = size;
03819 }
03820 
03827 long
03828 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
03829 {
03830   return loader->max_message_size;
03831 }
03832 
03833 static DBusDataSlotAllocator slot_allocator;
03834 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
03835 
03850 dbus_bool_t
03851 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
03852 {
03853   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03854                                           &_DBUS_LOCK_NAME (message_slots),
03855                                           slot_p);
03856 }
03857 
03869 void
03870 dbus_message_free_data_slot (dbus_int32_t *slot_p)
03871 {
03872   _dbus_return_if_fail (*slot_p >= 0);
03873 
03874   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03875 }
03876 
03890 dbus_bool_t
03891 dbus_message_set_data (DBusMessage     *message,
03892                        dbus_int32_t     slot,
03893                        void            *data,
03894                        DBusFreeFunction free_data_func)
03895 {
03896   DBusFreeFunction old_free_func;
03897   void *old_data;
03898   dbus_bool_t retval;
03899 
03900   _dbus_return_val_if_fail (message != NULL, FALSE);
03901   _dbus_return_val_if_fail (slot >= 0, FALSE);
03902 
03903   retval = _dbus_data_slot_list_set (&slot_allocator,
03904                                      &message->slot_list,
03905                                      slot, data, free_data_func,
03906                                      &old_free_func, &old_data);
03907 
03908   if (retval)
03909     {
03910       /* Do the actual free outside the message lock */
03911       if (old_free_func)
03912         (* old_free_func) (old_data);
03913     }
03914 
03915   return retval;
03916 }
03917 
03926 void*
03927 dbus_message_get_data (DBusMessage   *message,
03928                        dbus_int32_t   slot)
03929 {
03930   void *res;
03931 
03932   _dbus_return_val_if_fail (message != NULL, NULL);
03933 
03934   res = _dbus_data_slot_list_get (&slot_allocator,
03935                                   &message->slot_list,
03936                                   slot);
03937 
03938   return res;
03939 }
03940 
03954 int
03955 dbus_message_type_from_string (const char *type_str)
03956 {
03957   if (strcmp (type_str, "method_call") == 0)
03958     return DBUS_MESSAGE_TYPE_METHOD_CALL;
03959   if (strcmp (type_str, "method_return") == 0)
03960     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
03961   else if (strcmp (type_str, "signal") == 0)
03962     return DBUS_MESSAGE_TYPE_SIGNAL;
03963   else if (strcmp (type_str, "error") == 0)
03964     return DBUS_MESSAGE_TYPE_ERROR;
03965   else
03966     return DBUS_MESSAGE_TYPE_INVALID;
03967 }
03968 
03982 const char *
03983 dbus_message_type_to_string (int type)
03984 {
03985   switch (type)
03986     {
03987     case DBUS_MESSAGE_TYPE_METHOD_CALL:
03988       return "method_call";
03989     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
03990       return "method_return";
03991     case DBUS_MESSAGE_TYPE_SIGNAL:
03992       return "signal";
03993     case DBUS_MESSAGE_TYPE_ERROR:
03994       return "error";
03995     default:
03996       return "invalid";
03997     }
03998 }
03999 
04012 dbus_bool_t
04013 dbus_message_marshal (DBusMessage  *msg,
04014                       char        **marshalled_data_p,
04015                       int          *len_p)
04016 {
04017   DBusString tmp;
04018   dbus_bool_t was_locked;
04019 
04020   _dbus_return_val_if_fail (msg != NULL, FALSE);
04021   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04022   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04023   
04024   if (!_dbus_string_init (&tmp))
04025     return FALSE;
04026 
04027   /* Ensure the message is locked, to ensure the length header is filled in. */
04028   was_locked = msg->locked;
04029 
04030   if (!was_locked)
04031     dbus_message_lock (msg);
04032 
04033   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04034     goto fail;
04035 
04036   *len_p = _dbus_string_get_length (&tmp);
04037 
04038   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04039     goto fail;
04040 
04041   *len_p = _dbus_string_get_length (&tmp);
04042 
04043   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04044     goto fail;
04045 
04046   _dbus_string_free (&tmp);
04047 
04048   if (!was_locked)
04049     msg->locked = FALSE;
04050 
04051   return TRUE;
04052 
04053  fail:
04054   _dbus_string_free (&tmp);
04055 
04056   if (!was_locked)
04057     msg->locked = FALSE;
04058 
04059   return FALSE;
04060 }
04061 
04074 DBusMessage *
04075 dbus_message_demarshal (const char *str,
04076                         int         len,
04077                         DBusError  *error)
04078 {
04079   DBusMessageLoader *loader;
04080   DBusString *buffer;
04081   DBusMessage *msg;
04082 
04083   _dbus_return_val_if_fail (str != NULL, NULL);
04084 
04085   loader = _dbus_message_loader_new ();
04086 
04087   if (loader == NULL)
04088     return NULL;
04089 
04090   _dbus_message_loader_get_buffer (loader, &buffer);
04091   _dbus_string_append_len (buffer, str, len);
04092   _dbus_message_loader_return_buffer (loader, buffer, len);
04093 
04094   if (!_dbus_message_loader_queue_messages (loader))
04095     goto fail_oom;
04096 
04097   if (_dbus_message_loader_get_is_corrupted (loader))
04098     goto fail_corrupt;
04099 
04100   msg = _dbus_message_loader_pop_message (loader);
04101 
04102   if (!msg)
04103     goto fail_oom;
04104 
04105   _dbus_message_loader_unref (loader);
04106   return msg;
04107 
04108  fail_corrupt:
04109   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04110                   _dbus_validity_to_error_message (loader->corruption_reason));
04111   _dbus_message_loader_unref (loader);
04112   return NULL;
04113 
04114  fail_oom:
04115   _DBUS_SET_OOM (error);
04116   _dbus_message_loader_unref (loader);
04117   return NULL;
04118 }
04119 
04133 int 
04134 dbus_message_demarshal_bytes_needed(const char *buf, 
04135                                     int         len)
04136 {
04137   DBusString str;
04138   int byte_order, fields_array_len, header_len, body_len;
04139   DBusValidity validity = DBUS_VALID;
04140   int have_message;
04141 
04142   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04143     return 0;
04144 
04145   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04146     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04147   _dbus_string_init_const_len (&str, buf, len);
04148   
04149   validity = DBUS_VALID;
04150   have_message
04151     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04152                                           &validity, &byte_order,
04153                                           &fields_array_len,
04154                                           &header_len,
04155                                           &body_len,
04156                                           &str, 0,
04157                                           len);
04158   _dbus_string_free (&str);
04159 
04160   if (validity == DBUS_VALID)
04161     {
04162       _dbus_assert(have_message);
04163       return header_len + body_len;
04164     }
04165   else
04166     {
04167       return -1; /* broken! */
04168     }
04169 }
04170 
04173 /* tests in dbus-message-util.c */

Generated on Sun Feb 20 2011 22:49:19 for D-Bus by  doxygen 1.7.1