dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 
00169 void
00170 _dbus_message_set_serial (DBusMessage   *message,
00171                           dbus_uint32_t  serial)
00172 {
00173   _dbus_assert (message != NULL);
00174   _dbus_assert (!message->locked);
00175   _dbus_assert (dbus_message_get_serial (message) == 0);
00176 
00177   _dbus_header_set_serial (&message->header, serial);
00178 }
00179 
00192 void
00193 _dbus_message_add_size_counter_link (DBusMessage  *message,
00194                                      DBusList     *link)
00195 {
00196   /* right now we don't recompute the delta when message
00197    * size changes, and that's OK for current purposes
00198    * I think, but could be important to change later.
00199    * Do recompute it whenever there are no outstanding counters,
00200    * since it's basically free.
00201    */
00202   if (message->size_counters == NULL)
00203     {
00204       message->size_counter_delta =
00205         _dbus_string_get_length (&message->header.data) +
00206         _dbus_string_get_length (&message->body);
00207 
00208 #if 0
00209       _dbus_verbose ("message has size %ld\n",
00210                      message->size_counter_delta);
00211 #endif
00212     }
00213 
00214   _dbus_list_append_link (&message->size_counters, link);
00215 
00216   _dbus_counter_adjust (link->data, message->size_counter_delta);
00217 }
00218 
00228 dbus_bool_t
00229 _dbus_message_add_size_counter (DBusMessage *message,
00230                                 DBusCounter *counter)
00231 {
00232   DBusList *link;
00233 
00234   link = _dbus_list_alloc_link (counter);
00235   if (link == NULL)
00236     return FALSE;
00237 
00238   _dbus_counter_ref (counter);
00239   _dbus_message_add_size_counter_link (message, link);
00240 
00241   return TRUE;
00242 }
00243 
00252 void
00253 _dbus_message_remove_size_counter (DBusMessage  *message,
00254                                    DBusCounter  *counter,
00255                                    DBusList    **link_return)
00256 {
00257   DBusList *link;
00258 
00259   link = _dbus_list_find_last (&message->size_counters,
00260                                counter);
00261   _dbus_assert (link != NULL);
00262 
00263   _dbus_list_unlink (&message->size_counters,
00264                      link);
00265   if (link_return)
00266     *link_return = link;
00267   else
00268     _dbus_list_free_link (link);
00269 
00270   _dbus_counter_adjust (counter, - message->size_counter_delta);
00271 
00272   _dbus_counter_unref (counter);
00273 }
00274 
00284 void
00285 _dbus_message_lock (DBusMessage  *message)
00286 {
00287   if (!message->locked)
00288     {
00289       _dbus_header_update_lengths (&message->header,
00290                                    _dbus_string_get_length (&message->body));
00291 
00292       /* must have a signature if you have a body */
00293       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00294                     dbus_message_get_signature (message) != NULL);
00295 
00296       message->locked = TRUE;
00297     }
00298 }
00299 
00300 static dbus_bool_t
00301 set_or_delete_string_field (DBusMessage *message,
00302                             int          field,
00303                             int          typecode,
00304                             const char  *value)
00305 {
00306   if (value == NULL)
00307     return _dbus_header_delete_field (&message->header, field);
00308   else
00309     return _dbus_header_set_field_basic (&message->header,
00310                                          field,
00311                                          typecode,
00312                                          &value);
00313 }
00314 
00315 #if 0
00316 /* Probably we don't need to use this */
00340 static dbus_bool_t
00341 _dbus_message_set_signature (DBusMessage *message,
00342                              const char  *signature)
00343 {
00344   _dbus_return_val_if_fail (message != NULL, FALSE);
00345   _dbus_return_val_if_fail (!message->locked, FALSE);
00346   _dbus_return_val_if_fail (signature == NULL ||
00347                             _dbus_check_is_valid_signature (signature));
00348   /* can't delete the signature if you have a message body */
00349   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00350                             signature != NULL);
00351 
00352   return set_or_delete_string_field (message,
00353                                      DBUS_HEADER_FIELD_SIGNATURE,
00354                                      DBUS_TYPE_SIGNATURE,
00355                                      signature);
00356 }
00357 #endif
00358 
00359 /* Message Cache
00360  *
00361  * We cache some DBusMessage to reduce the overhead of allocating
00362  * them.  In my profiling this consistently made about an 8%
00363  * difference.  It avoids the malloc for the message, the malloc for
00364  * the slot list, the malloc for the header string and body string,
00365  * and the associated free() calls. It does introduce another global
00366  * lock which could be a performance issue in certain cases.
00367  *
00368  * For the echo client/server the round trip time goes from around
00369  * .000077 to .000069 with the message cache on my laptop. The sysprof
00370  * change is as follows (numbers are cumulative percentage):
00371  *
00372  *  with message cache implemented as array as it is now (0.000069 per):
00373  *    new_empty_header           1.46
00374  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00375  *      mutex_unlock             0.25
00376  *      self                     0.41
00377  *    unref                      2.24
00378  *      self                     0.68
00379  *      list_clear               0.43
00380  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00381  *      mutex_unlock             0.25
00382  *
00383  *  with message cache implemented as list (0.000070 per roundtrip):
00384  *    new_empty_header           2.72
00385  *      list_pop_first           1.88
00386  *    unref                      3.3
00387  *      list_prepend             1.63
00388  *
00389  * without cache (0.000077 per roundtrip):
00390  *    new_empty_header           6.7
00391  *      string_init_preallocated 3.43
00392  *        dbus_malloc            2.43
00393  *      dbus_malloc0             2.59
00394  *
00395  *    unref                      4.02
00396  *      string_free              1.82
00397  *        dbus_free              1.63
00398  *      dbus_free                0.71
00399  *
00400  * If you implement the message_cache with a list, the primary reason
00401  * it's slower is that you add another thread lock (on the DBusList
00402  * mempool).
00403  */
00404 
00406 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00407 
00409 #define MAX_MESSAGE_CACHE_SIZE    5
00410 
00411 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00412 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00413 static int message_cache_count = 0;
00414 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00415 
00416 static void
00417 dbus_message_cache_shutdown (void *data)
00418 {
00419   int i;
00420 
00421   _DBUS_LOCK (message_cache);
00422 
00423   i = 0;
00424   while (i < MAX_MESSAGE_CACHE_SIZE)
00425     {
00426       if (message_cache[i])
00427         dbus_message_finalize (message_cache[i]);
00428 
00429       ++i;
00430     }
00431 
00432   message_cache_count = 0;
00433   message_cache_shutdown_registered = FALSE;
00434 
00435   _DBUS_UNLOCK (message_cache);
00436 }
00437 
00445 static DBusMessage*
00446 dbus_message_get_cached (void)
00447 {
00448   DBusMessage *message;
00449   int i;
00450 
00451   message = NULL;
00452 
00453   _DBUS_LOCK (message_cache);
00454 
00455   _dbus_assert (message_cache_count >= 0);
00456 
00457   if (message_cache_count == 0)
00458     {
00459       _DBUS_UNLOCK (message_cache);
00460       return NULL;
00461     }
00462 
00463   /* This is not necessarily true unless count > 0, and
00464    * message_cache is uninitialized until the shutdown is
00465    * registered
00466    */
00467   _dbus_assert (message_cache_shutdown_registered);
00468 
00469   i = 0;
00470   while (i < MAX_MESSAGE_CACHE_SIZE)
00471     {
00472       if (message_cache[i])
00473         {
00474           message = message_cache[i];
00475           message_cache[i] = NULL;
00476           message_cache_count -= 1;
00477           break;
00478         }
00479       ++i;
00480     }
00481   _dbus_assert (message_cache_count >= 0);
00482   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00483   _dbus_assert (message != NULL);
00484 
00485   _dbus_assert (message->refcount.value == 0);
00486   _dbus_assert (message->size_counters == NULL);
00487   
00488   _DBUS_UNLOCK (message_cache);
00489 
00490   return message;
00491 }
00492 
00493 static void
00494 free_size_counter (void *element,
00495                    void *data)
00496 {
00497   DBusCounter *counter = element;
00498   DBusMessage *message = data;
00499 
00500   _dbus_counter_adjust (counter, - message->size_counter_delta);
00501 
00502   _dbus_counter_unref (counter);
00503 }
00504 
00510 static void
00511 dbus_message_cache_or_finalize (DBusMessage *message)
00512 {
00513   dbus_bool_t was_cached;
00514   int i;
00515   
00516   _dbus_assert (message->refcount.value == 0);
00517 
00518   /* This calls application code and has to be done first thing
00519    * without holding the lock
00520    */
00521   _dbus_data_slot_list_clear (&message->slot_list);
00522 
00523   _dbus_list_foreach (&message->size_counters,
00524                       free_size_counter, message);
00525   _dbus_list_clear (&message->size_counters);
00526 
00527   was_cached = FALSE;
00528 
00529   _DBUS_LOCK (message_cache);
00530 
00531   if (!message_cache_shutdown_registered)
00532     {
00533       _dbus_assert (message_cache_count == 0);
00534 
00535       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00536         goto out;
00537 
00538       i = 0;
00539       while (i < MAX_MESSAGE_CACHE_SIZE)
00540         {
00541           message_cache[i] = NULL;
00542           ++i;
00543         }
00544 
00545       message_cache_shutdown_registered = TRUE;
00546     }
00547 
00548   _dbus_assert (message_cache_count >= 0);
00549 
00550   if ((_dbus_string_get_length (&message->header.data) +
00551        _dbus_string_get_length (&message->body)) >
00552       MAX_MESSAGE_SIZE_TO_CACHE)
00553     goto out;
00554 
00555   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00556     goto out;
00557 
00558   /* Find empty slot */
00559   i = 0;
00560   while (message_cache[i] != NULL)
00561     ++i;
00562 
00563   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00564 
00565   _dbus_assert (message_cache[i] == NULL);
00566   message_cache[i] = message;
00567   message_cache_count += 1;
00568   was_cached = TRUE;
00569 #ifndef DBUS_DISABLE_CHECKS
00570   message->in_cache = TRUE;
00571 #endif
00572 
00573  out:
00574   _dbus_assert (message->refcount.value == 0);
00575   
00576   _DBUS_UNLOCK (message_cache);
00577   
00578   if (!was_cached)
00579     dbus_message_finalize (message);
00580 }
00581 
00582 #ifndef DBUS_DISABLE_CHECKS
00583 static dbus_bool_t
00584 _dbus_message_iter_check (DBusMessageRealIter *iter)
00585 {
00586   if (iter == NULL)
00587     {
00588       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00589       return FALSE;
00590     }
00591 
00592   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00593     {
00594       if (iter->u.reader.byte_order != iter->message->byte_order)
00595         {
00596           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00597           return FALSE;
00598         }
00599       /* because we swap the message into compiler order when you init an iter */
00600       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00601     }
00602   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00603     {
00604       if (iter->u.writer.byte_order != iter->message->byte_order)
00605         {
00606           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00607           return FALSE;
00608         }
00609       /* because we swap the message into compiler order when you init an iter */
00610       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00611     }
00612   else
00613     {
00614       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00615       return FALSE;
00616     }
00617 
00618   if (iter->changed_stamp != iter->message->changed_stamp)
00619     {
00620       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00621       return FALSE;
00622     }
00623 
00624   return TRUE;
00625 }
00626 #endif /* DBUS_DISABLE_CHECKS */
00627 
00640 dbus_bool_t
00641 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00642                                     DBusError       *error,
00643                                     int              first_arg_type,
00644                                     va_list          var_args)
00645 {
00646   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00647   int spec_type, msg_type, i;
00648   dbus_bool_t retval;
00649 
00650   _dbus_assert (_dbus_message_iter_check (real));
00651 
00652   retval = FALSE;
00653 
00654   spec_type = first_arg_type;
00655   i = 0;
00656 
00657   while (spec_type != DBUS_TYPE_INVALID)
00658     {
00659       msg_type = dbus_message_iter_get_arg_type (iter);
00660 
00661       if (msg_type != spec_type)
00662         {
00663           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00664                           "Argument %d is specified to be of type \"%s\", but "
00665                           "is actually of type \"%s\"\n", i,
00666                           _dbus_type_to_string (spec_type),
00667                           _dbus_type_to_string (msg_type));
00668 
00669           goto out;
00670         }
00671 
00672       if (dbus_type_is_basic (spec_type))
00673         {
00674           DBusBasicValue *ptr;
00675 
00676           ptr = va_arg (var_args, DBusBasicValue*);
00677 
00678           _dbus_assert (ptr != NULL);
00679 
00680           _dbus_type_reader_read_basic (&real->u.reader,
00681                                         ptr);
00682         }
00683       else if (spec_type == DBUS_TYPE_ARRAY)
00684         {
00685           int element_type;
00686           int spec_element_type;
00687           const DBusBasicValue **ptr;
00688           int *n_elements_p;
00689           DBusTypeReader array;
00690 
00691           spec_element_type = va_arg (var_args, int);
00692           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00693 
00694           if (spec_element_type != element_type)
00695             {
00696               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00697                               "Argument %d is specified to be an array of \"%s\", but "
00698                               "is actually an array of \"%s\"\n",
00699                               i,
00700                               _dbus_type_to_string (spec_element_type),
00701                               _dbus_type_to_string (element_type));
00702 
00703               goto out;
00704             }
00705 
00706           if (dbus_type_is_fixed (spec_element_type))
00707             {
00708               ptr = va_arg (var_args, const DBusBasicValue**);
00709               n_elements_p = va_arg (var_args, int*);
00710 
00711               _dbus_assert (ptr != NULL);
00712               _dbus_assert (n_elements_p != NULL);
00713 
00714               _dbus_type_reader_recurse (&real->u.reader, &array);
00715 
00716               _dbus_type_reader_read_fixed_multi (&array,
00717                                                   ptr, n_elements_p);
00718             }
00719           else if (spec_element_type == DBUS_TYPE_STRING ||
00720                    spec_element_type == DBUS_TYPE_SIGNATURE ||
00721                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
00722             {
00723               char ***str_array_p;
00724               int n_elements;
00725               char **str_array;
00726 
00727               str_array_p = va_arg (var_args, char***);
00728               n_elements_p = va_arg (var_args, int*);
00729 
00730               _dbus_assert (str_array_p != NULL);
00731               _dbus_assert (n_elements_p != NULL);
00732 
00733               /* Count elements in the array */
00734               _dbus_type_reader_recurse (&real->u.reader, &array);
00735 
00736               n_elements = 0;
00737               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00738                 {
00739                   ++n_elements;
00740                   _dbus_type_reader_next (&array);
00741                 }
00742 
00743               str_array = dbus_new0 (char*, n_elements + 1);
00744               if (str_array == NULL)
00745                 {
00746                   _DBUS_SET_OOM (error);
00747                   goto out;
00748                 }
00749 
00750               /* Now go through and dup each string */
00751               _dbus_type_reader_recurse (&real->u.reader, &array);
00752 
00753               i = 0;
00754               while (i < n_elements)
00755                 {
00756                   const char *s;
00757                   _dbus_type_reader_read_basic (&array,
00758                                                 &s);
00759                   
00760                   str_array[i] = _dbus_strdup (s);
00761                   if (str_array[i] == NULL)
00762                     {
00763                       dbus_free_string_array (str_array);
00764                       _DBUS_SET_OOM (error);
00765                       goto out;
00766                     }
00767                   
00768                   ++i;
00769                   
00770                   if (!_dbus_type_reader_next (&array))
00771                     _dbus_assert (i == n_elements);
00772                 }
00773 
00774               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00775               _dbus_assert (i == n_elements);
00776               _dbus_assert (str_array[i] == NULL);
00777 
00778               *str_array_p = str_array;
00779               *n_elements_p = n_elements;
00780             }
00781 #ifndef DBUS_DISABLE_CHECKS
00782           else
00783             {
00784               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00785                           _DBUS_FUNCTION_NAME);
00786               goto out;
00787             }
00788 #endif
00789         }
00790 #ifndef DBUS_DISABLE_CHECKS
00791       else
00792         {
00793           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00794                       _DBUS_FUNCTION_NAME);
00795           goto out;
00796         }
00797 #endif
00798 
00799       spec_type = va_arg (var_args, int);
00800       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00801         {
00802           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00803                           "Message has only %d arguments, but more were expected", i);
00804           goto out;
00805         }
00806 
00807       i++;
00808     }
00809 
00810   retval = TRUE;
00811 
00812  out:
00813 
00814   return retval;
00815 }
00816 
00875 dbus_uint32_t
00876 dbus_message_get_serial (DBusMessage *message)
00877 {
00878   _dbus_return_val_if_fail (message != NULL, 0);
00879 
00880   return _dbus_header_get_serial (&message->header);
00881 }
00882 
00891 dbus_bool_t
00892 dbus_message_set_reply_serial (DBusMessage   *message,
00893                                dbus_uint32_t  reply_serial)
00894 {
00895   _dbus_return_val_if_fail (message != NULL, FALSE);
00896   _dbus_return_val_if_fail (!message->locked, FALSE);
00897   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
00898 
00899   return _dbus_header_set_field_basic (&message->header,
00900                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
00901                                        DBUS_TYPE_UINT32,
00902                                        &reply_serial);
00903 }
00904 
00911 dbus_uint32_t
00912 dbus_message_get_reply_serial  (DBusMessage *message)
00913 {
00914   dbus_uint32_t v_UINT32;
00915 
00916   _dbus_return_val_if_fail (message != NULL, 0);
00917 
00918   if (_dbus_header_get_field_basic (&message->header,
00919                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
00920                                     DBUS_TYPE_UINT32,
00921                                     &v_UINT32))
00922     return v_UINT32;
00923   else
00924     return 0;
00925 }
00926 
00927 static void
00928 dbus_message_finalize (DBusMessage *message)
00929 {
00930   _dbus_assert (message->refcount.value == 0);
00931 
00932   /* This calls application callbacks! */
00933   _dbus_data_slot_list_free (&message->slot_list);
00934 
00935   _dbus_list_foreach (&message->size_counters,
00936                       free_size_counter, message);
00937   _dbus_list_clear (&message->size_counters);
00938 
00939   _dbus_header_free (&message->header);
00940   _dbus_string_free (&message->body);
00941 
00942   _dbus_assert (message->refcount.value == 0);
00943   
00944   dbus_free (message);
00945 }
00946 
00947 static DBusMessage*
00948 dbus_message_new_empty_header (void)
00949 {
00950   DBusMessage *message;
00951   dbus_bool_t from_cache;
00952 
00953   message = dbus_message_get_cached ();
00954 
00955   if (message != NULL)
00956     {
00957       from_cache = TRUE;
00958     }
00959   else
00960     {
00961       from_cache = FALSE;
00962       message = dbus_new (DBusMessage, 1);
00963       if (message == NULL)
00964         return NULL;
00965 #ifndef DBUS_DISABLE_CHECKS
00966       message->generation = _dbus_current_generation;
00967 #endif
00968     }
00969   
00970   message->refcount.value = 1;
00971   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00972   message->locked = FALSE;
00973 #ifndef DBUS_DISABLE_CHECKS
00974   message->in_cache = FALSE;
00975 #endif
00976   message->size_counters = NULL;
00977   message->size_counter_delta = 0;
00978   message->changed_stamp = 0;
00979 
00980   if (!from_cache)
00981     _dbus_data_slot_list_init (&message->slot_list);
00982 
00983   if (from_cache)
00984     {
00985       _dbus_header_reinit (&message->header, message->byte_order);
00986       _dbus_string_set_length (&message->body, 0);
00987     }
00988   else
00989     {
00990       if (!_dbus_header_init (&message->header, message->byte_order))
00991         {
00992           dbus_free (message);
00993           return NULL;
00994         }
00995 
00996       if (!_dbus_string_init_preallocated (&message->body, 32))
00997         {
00998           _dbus_header_free (&message->header);
00999           dbus_free (message);
01000           return NULL;
01001         }
01002     }
01003 
01004   return message;
01005 }
01006 
01019 DBusMessage*
01020 dbus_message_new (int message_type)
01021 {
01022   DBusMessage *message;
01023 
01024   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01025 
01026   message = dbus_message_new_empty_header ();
01027   if (message == NULL)
01028     return NULL;
01029 
01030   if (!_dbus_header_create (&message->header,
01031                             message_type,
01032                             NULL, NULL, NULL, NULL, NULL))
01033     {
01034       dbus_message_unref (message);
01035       return NULL;
01036     }
01037 
01038   return message;
01039 }
01040 
01062 DBusMessage*
01063 dbus_message_new_method_call (const char *destination,
01064                               const char *path,
01065                               const char *interface,
01066                               const char *method)
01067 {
01068   DBusMessage *message;
01069 
01070   _dbus_return_val_if_fail (path != NULL, NULL);
01071   _dbus_return_val_if_fail (method != NULL, NULL);
01072   _dbus_return_val_if_fail (destination == NULL ||
01073                             _dbus_check_is_valid_bus_name (destination), NULL);
01074   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01075   _dbus_return_val_if_fail (interface == NULL ||
01076                             _dbus_check_is_valid_interface (interface), NULL);
01077   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01078 
01079   message = dbus_message_new_empty_header ();
01080   if (message == NULL)
01081     return NULL;
01082 
01083   if (!_dbus_header_create (&message->header,
01084                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01085                             destination, path, interface, method, NULL))
01086     {
01087       dbus_message_unref (message);
01088       return NULL;
01089     }
01090 
01091   return message;
01092 }
01093 
01101 DBusMessage*
01102 dbus_message_new_method_return (DBusMessage *method_call)
01103 {
01104   DBusMessage *message;
01105   const char *sender;
01106 
01107   _dbus_return_val_if_fail (method_call != NULL, NULL);
01108 
01109   sender = dbus_message_get_sender (method_call);
01110 
01111   /* sender is allowed to be null here in peer-to-peer case */
01112 
01113   message = dbus_message_new_empty_header ();
01114   if (message == NULL)
01115     return NULL;
01116 
01117   if (!_dbus_header_create (&message->header,
01118                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01119                             sender, NULL, NULL, NULL, NULL))
01120     {
01121       dbus_message_unref (message);
01122       return NULL;
01123     }
01124 
01125   dbus_message_set_no_reply (message, TRUE);
01126 
01127   if (!dbus_message_set_reply_serial (message,
01128                                       dbus_message_get_serial (method_call)))
01129     {
01130       dbus_message_unref (message);
01131       return NULL;
01132     }
01133 
01134   return message;
01135 }
01136 
01151 DBusMessage*
01152 dbus_message_new_signal (const char *path,
01153                          const char *interface,
01154                          const char *name)
01155 {
01156   DBusMessage *message;
01157 
01158   _dbus_return_val_if_fail (path != NULL, NULL);
01159   _dbus_return_val_if_fail (interface != NULL, NULL);
01160   _dbus_return_val_if_fail (name != NULL, NULL);
01161   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01162   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
01163   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01164 
01165   message = dbus_message_new_empty_header ();
01166   if (message == NULL)
01167     return NULL;
01168 
01169   if (!_dbus_header_create (&message->header,
01170                             DBUS_MESSAGE_TYPE_SIGNAL,
01171                             NULL, path, interface, name, NULL))
01172     {
01173       dbus_message_unref (message);
01174       return NULL;
01175     }
01176 
01177   dbus_message_set_no_reply (message, TRUE);
01178 
01179   return message;
01180 }
01181 
01196 DBusMessage*
01197 dbus_message_new_error (DBusMessage *reply_to,
01198                         const char  *error_name,
01199                         const char  *error_message)
01200 {
01201   DBusMessage *message;
01202   const char *sender;
01203   DBusMessageIter iter;
01204 
01205   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01206   _dbus_return_val_if_fail (error_name != NULL, NULL);
01207   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01208 
01209   sender = dbus_message_get_sender (reply_to);
01210 
01211   /* sender may be NULL for non-message-bus case or
01212    * when the message bus is dealing with an unregistered
01213    * connection.
01214    */
01215   message = dbus_message_new_empty_header ();
01216   if (message == NULL)
01217     return NULL;
01218 
01219   if (!_dbus_header_create (&message->header,
01220                             DBUS_MESSAGE_TYPE_ERROR,
01221                             sender, NULL, NULL, NULL, error_name))
01222     {
01223       dbus_message_unref (message);
01224       return NULL;
01225     }
01226 
01227   dbus_message_set_no_reply (message, TRUE);
01228 
01229   if (!dbus_message_set_reply_serial (message,
01230                                       dbus_message_get_serial (reply_to)))
01231     {
01232       dbus_message_unref (message);
01233       return NULL;
01234     }
01235 
01236   if (error_message != NULL)
01237     {
01238       dbus_message_iter_init_append (message, &iter);
01239       if (!dbus_message_iter_append_basic (&iter,
01240                                            DBUS_TYPE_STRING,
01241                                            &error_message))
01242         {
01243           dbus_message_unref (message);
01244           return NULL;
01245         }
01246     }
01247 
01248   return message;
01249 }
01250 
01267 DBusMessage*
01268 dbus_message_new_error_printf (DBusMessage *reply_to,
01269                                const char  *error_name,
01270                                const char  *error_format,
01271                                ...)
01272 {
01273   va_list args;
01274   DBusString str;
01275   DBusMessage *message;
01276 
01277   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01278   _dbus_return_val_if_fail (error_name != NULL, NULL);
01279   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01280 
01281   if (!_dbus_string_init (&str))
01282     return NULL;
01283 
01284   va_start (args, error_format);
01285 
01286   if (_dbus_string_append_printf_valist (&str, error_format, args))
01287     message = dbus_message_new_error (reply_to, error_name,
01288                                       _dbus_string_get_const_data (&str));
01289   else
01290     message = NULL;
01291 
01292   _dbus_string_free (&str);
01293 
01294   va_end (args);
01295 
01296   return message;
01297 }
01298 
01299 
01310 DBusMessage *
01311 dbus_message_copy (const DBusMessage *message)
01312 {
01313   DBusMessage *retval;
01314 
01315   _dbus_return_val_if_fail (message != NULL, NULL);
01316 
01317   retval = dbus_new0 (DBusMessage, 1);
01318   if (retval == NULL)
01319     return NULL;
01320 
01321   retval->refcount.value = 1;
01322   retval->byte_order = message->byte_order;
01323   retval->locked = FALSE;
01324 #ifndef DBUS_DISABLE_CHECKS
01325   retval->generation = message->generation;
01326 #endif
01327 
01328   if (!_dbus_header_copy (&message->header, &retval->header))
01329     {
01330       dbus_free (retval);
01331       return NULL;
01332     }
01333 
01334   if (!_dbus_string_init_preallocated (&retval->body,
01335                                        _dbus_string_get_length (&message->body)))
01336     {
01337       _dbus_header_free (&retval->header);
01338       dbus_free (retval);
01339       return NULL;
01340     }
01341 
01342   if (!_dbus_string_copy (&message->body, 0,
01343                           &retval->body, 0))
01344     goto failed_copy;
01345 
01346   return retval;
01347 
01348  failed_copy:
01349   _dbus_header_free (&retval->header);
01350   _dbus_string_free (&retval->body);
01351   dbus_free (retval);
01352 
01353   return NULL;
01354 }
01355 
01356 
01364 DBusMessage *
01365 dbus_message_ref (DBusMessage *message)
01366 {
01367   dbus_int32_t old_refcount;
01368 
01369   _dbus_return_val_if_fail (message != NULL, NULL);
01370   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01371   _dbus_return_val_if_fail (!message->in_cache, NULL);
01372   
01373   old_refcount = _dbus_atomic_inc (&message->refcount);
01374   _dbus_assert (old_refcount >= 1);
01375 
01376   return message;
01377 }
01378 
01386 void
01387 dbus_message_unref (DBusMessage *message)
01388 {
01389  dbus_int32_t old_refcount;
01390 
01391   _dbus_return_if_fail (message != NULL);
01392   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01393   _dbus_return_if_fail (!message->in_cache);
01394 
01395   old_refcount = _dbus_atomic_dec (&message->refcount);
01396 
01397   _dbus_assert (old_refcount >= 0);
01398 
01399   if (old_refcount == 1)
01400     {
01401       /* Calls application callbacks! */
01402       dbus_message_cache_or_finalize (message);
01403     }
01404 }
01405 
01416 int
01417 dbus_message_get_type (DBusMessage *message)
01418 {
01419   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01420 
01421   return _dbus_header_get_message_type (&message->header);
01422 }
01423 
01481 dbus_bool_t
01482 dbus_message_append_args (DBusMessage *message,
01483                           int          first_arg_type,
01484                           ...)
01485 {
01486   dbus_bool_t retval;
01487   va_list var_args;
01488 
01489   _dbus_return_val_if_fail (message != NULL, FALSE);
01490 
01491   va_start (var_args, first_arg_type);
01492   retval = dbus_message_append_args_valist (message,
01493                                             first_arg_type,
01494                                             var_args);
01495   va_end (var_args);
01496 
01497   return retval;
01498 }
01499 
01513 dbus_bool_t
01514 dbus_message_append_args_valist (DBusMessage *message,
01515                                  int          first_arg_type,
01516                                  va_list      var_args)
01517 {
01518   int type;
01519   DBusMessageIter iter;
01520 
01521   _dbus_return_val_if_fail (message != NULL, FALSE);
01522 
01523   type = first_arg_type;
01524 
01525   dbus_message_iter_init_append (message, &iter);
01526 
01527   while (type != DBUS_TYPE_INVALID)
01528     {
01529       if (dbus_type_is_basic (type))
01530         {
01531           const DBusBasicValue *value;
01532           value = va_arg (var_args, const DBusBasicValue*);
01533 
01534           if (!dbus_message_iter_append_basic (&iter,
01535                                                type,
01536                                                value))
01537             goto failed;
01538         }
01539       else if (type == DBUS_TYPE_ARRAY)
01540         {
01541           int element_type;
01542           DBusMessageIter array;
01543           char buf[2];
01544 
01545           element_type = va_arg (var_args, int);
01546               
01547           buf[0] = element_type;
01548           buf[1] = '\0';
01549           if (!dbus_message_iter_open_container (&iter,
01550                                                  DBUS_TYPE_ARRAY,
01551                                                  buf,
01552                                                  &array))
01553             goto failed;
01554           
01555           if (dbus_type_is_fixed (element_type))
01556             {
01557               const DBusBasicValue **value;
01558               int n_elements;
01559 
01560               value = va_arg (var_args, const DBusBasicValue**);
01561               n_elements = va_arg (var_args, int);
01562               
01563               if (!dbus_message_iter_append_fixed_array (&array,
01564                                                          element_type,
01565                                                          value,
01566                                                          n_elements))
01567                 goto failed;
01568             }
01569           else if (element_type == DBUS_TYPE_STRING ||
01570                    element_type == DBUS_TYPE_SIGNATURE ||
01571                    element_type == DBUS_TYPE_OBJECT_PATH)
01572             {
01573               const char ***value_p;
01574               const char **value;
01575               int n_elements;
01576               int i;
01577               
01578               value_p = va_arg (var_args, const char***);
01579               n_elements = va_arg (var_args, int);
01580 
01581               value = *value_p;
01582               
01583               i = 0;
01584               while (i < n_elements)
01585                 {
01586                   if (!dbus_message_iter_append_basic (&array,
01587                                                        element_type,
01588                                                        &value[i]))
01589                     goto failed;
01590                   ++i;
01591                 }
01592             }
01593           else
01594             {
01595               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01596                           _dbus_type_to_string (element_type),
01597                           _DBUS_FUNCTION_NAME);
01598               goto failed;
01599             }
01600 
01601           if (!dbus_message_iter_close_container (&iter, &array))
01602             goto failed;
01603         }
01604 #ifndef DBUS_DISABLE_CHECKS
01605       else
01606         {
01607           _dbus_warn ("type %s isn't supported yet in %s\n",
01608                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01609           goto failed;
01610         }
01611 #endif
01612 
01613       type = va_arg (var_args, int);
01614     }
01615 
01616   return TRUE;
01617 
01618  failed:
01619   return FALSE;
01620 }
01621 
01657 dbus_bool_t
01658 dbus_message_get_args (DBusMessage     *message,
01659                        DBusError       *error,
01660                        int              first_arg_type,
01661                        ...)
01662 {
01663   dbus_bool_t retval;
01664   va_list var_args;
01665 
01666   _dbus_return_val_if_fail (message != NULL, FALSE);
01667   _dbus_return_val_if_error_is_set (error, FALSE);
01668 
01669   va_start (var_args, first_arg_type);
01670   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01671   va_end (var_args);
01672 
01673   return retval;
01674 }
01675 
01686 dbus_bool_t
01687 dbus_message_get_args_valist (DBusMessage     *message,
01688                               DBusError       *error,
01689                               int              first_arg_type,
01690                               va_list          var_args)
01691 {
01692   DBusMessageIter iter;
01693 
01694   _dbus_return_val_if_fail (message != NULL, FALSE);
01695   _dbus_return_val_if_error_is_set (error, FALSE);
01696 
01697   dbus_message_iter_init (message, &iter);
01698   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01699 }
01700 
01701 static void
01702 _dbus_message_iter_init_common (DBusMessage         *message,
01703                                 DBusMessageRealIter *real,
01704                                 int                  iter_type)
01705 {
01706   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01707 
01708   /* Since the iterator will read or write who-knows-what from the
01709    * message, we need to get in the right byte order
01710    */
01711   ensure_byte_order (message);
01712   
01713   real->message = message;
01714   real->changed_stamp = message->changed_stamp;
01715   real->iter_type = iter_type;
01716   real->sig_refcount = 0;
01717 }
01718 
01741 dbus_bool_t
01742 dbus_message_iter_init (DBusMessage     *message,
01743                         DBusMessageIter *iter)
01744 {
01745   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01746   const DBusString *type_str;
01747   int type_pos;
01748 
01749   _dbus_return_val_if_fail (message != NULL, FALSE);
01750   _dbus_return_val_if_fail (iter != NULL, FALSE);
01751 
01752   get_const_signature (&message->header, &type_str, &type_pos);
01753 
01754   _dbus_message_iter_init_common (message, real,
01755                                   DBUS_MESSAGE_ITER_TYPE_READER);
01756 
01757   _dbus_type_reader_init (&real->u.reader,
01758                           message->byte_order,
01759                           type_str, type_pos,
01760                           &message->body,
01761                           0);
01762 
01763   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
01764 }
01765 
01772 dbus_bool_t
01773 dbus_message_iter_has_next (DBusMessageIter *iter)
01774 {
01775   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01776 
01777   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01778   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01779 
01780   return _dbus_type_reader_has_next (&real->u.reader);
01781 }
01782 
01791 dbus_bool_t
01792 dbus_message_iter_next (DBusMessageIter *iter)
01793 {
01794   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01795 
01796   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01797   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01798 
01799   return _dbus_type_reader_next (&real->u.reader);
01800 }
01801 
01816 int
01817 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
01818 {
01819   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01820 
01821   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01822   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01823 
01824   return _dbus_type_reader_get_current_type (&real->u.reader);
01825 }
01826 
01835 int
01836 dbus_message_iter_get_element_type (DBusMessageIter *iter)
01837 {
01838   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01839 
01840   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01841   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
01842   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
01843 
01844   return _dbus_type_reader_get_element_type (&real->u.reader);
01845 }
01846 
01862 void
01863 dbus_message_iter_recurse (DBusMessageIter  *iter,
01864                            DBusMessageIter  *sub)
01865 {
01866   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01867   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
01868 
01869   _dbus_return_if_fail (_dbus_message_iter_check (real));
01870   _dbus_return_if_fail (sub != NULL);
01871 
01872   *real_sub = *real;
01873   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
01874 }
01875 
01887 char *
01888 dbus_message_iter_get_signature (DBusMessageIter *iter)
01889 {
01890   const DBusString *sig;
01891   DBusString retstr;
01892   char *ret;
01893   int start, len;
01894   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01895 
01896   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
01897 
01898   if (!_dbus_string_init (&retstr))
01899     return NULL;
01900 
01901   _dbus_type_reader_get_signature (&real->u.reader, &sig,
01902                                    &start, &len);
01903   if (!_dbus_string_append_len (&retstr,
01904                                 _dbus_string_get_const_data (sig) + start,
01905                                 len))
01906     return NULL;
01907   if (!_dbus_string_steal_data (&retstr, &ret))
01908     return NULL;
01909   _dbus_string_free (&retstr);
01910   return ret;
01911 }
01912 
01950 void
01951 dbus_message_iter_get_basic (DBusMessageIter  *iter,
01952                              void             *value)
01953 {
01954   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01955 
01956   _dbus_return_if_fail (_dbus_message_iter_check (real));
01957   _dbus_return_if_fail (value != NULL);
01958 
01959   _dbus_type_reader_read_basic (&real->u.reader,
01960                                 value);
01961 }
01962 
01981 int
01982 dbus_message_iter_get_array_len (DBusMessageIter *iter)
01983 {
01984   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01985 
01986   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
01987 
01988   return _dbus_type_reader_get_array_length (&real->u.reader);
01989 }
01990 
02012 void
02013 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02014                                    void             *value,
02015                                    int              *n_elements)
02016 {
02017   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02018   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02019 
02020   _dbus_return_if_fail (_dbus_message_iter_check (real));
02021   _dbus_return_if_fail (value != NULL);
02022   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02023                          dbus_type_is_fixed (subtype));
02024 
02025   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02026                                       value, n_elements);
02027 }
02028 
02040 void
02041 dbus_message_iter_init_append (DBusMessage     *message,
02042                                DBusMessageIter *iter)
02043 {
02044   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02045 
02046   _dbus_return_if_fail (message != NULL);
02047   _dbus_return_if_fail (iter != NULL);
02048 
02049   _dbus_message_iter_init_common (message, real,
02050                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02051 
02052   /* We create the signature string and point iterators at it "on demand"
02053    * when a value is actually appended. That means that init() never fails
02054    * due to OOM.
02055    */
02056   _dbus_type_writer_init_types_delayed (&real->u.writer,
02057                                         message->byte_order,
02058                                         &message->body,
02059                                         _dbus_string_get_length (&message->body));
02060 }
02061 
02070 static dbus_bool_t
02071 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02072 {
02073   DBusString *str;
02074   const DBusString *current_sig;
02075   int current_sig_pos;
02076 
02077   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02078 
02079   if (real->u.writer.type_str != NULL)
02080     {
02081       _dbus_assert (real->sig_refcount > 0);
02082       real->sig_refcount += 1;
02083       return TRUE;
02084     }
02085 
02086   str = dbus_new (DBusString, 1);
02087   if (str == NULL)
02088     return FALSE;
02089 
02090   if (!_dbus_header_get_field_raw (&real->message->header,
02091                                    DBUS_HEADER_FIELD_SIGNATURE,
02092                                    &current_sig, &current_sig_pos))
02093     current_sig = NULL;
02094 
02095   if (current_sig)
02096     {
02097       int current_len;
02098 
02099       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02100       current_sig_pos += 1; /* move on to sig data */
02101 
02102       if (!_dbus_string_init_preallocated (str, current_len + 4))
02103         {
02104           dbus_free (str);
02105           return FALSE;
02106         }
02107 
02108       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02109                                   str, 0))
02110         {
02111           _dbus_string_free (str);
02112           dbus_free (str);
02113           return FALSE;
02114         }
02115     }
02116   else
02117     {
02118       if (!_dbus_string_init_preallocated (str, 4))
02119         {
02120           dbus_free (str);
02121           return FALSE;
02122         }
02123     }
02124 
02125   real->sig_refcount = 1;
02126 
02127   _dbus_type_writer_add_types (&real->u.writer,
02128                                str, _dbus_string_get_length (str));
02129   return TRUE;
02130 }
02131 
02141 static dbus_bool_t
02142 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02143 {
02144   DBusString *str;
02145   const char *v_STRING;
02146   dbus_bool_t retval;
02147 
02148   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02149   _dbus_assert (real->u.writer.type_str != NULL);
02150   _dbus_assert (real->sig_refcount > 0);
02151 
02152   real->sig_refcount -= 1;
02153 
02154   if (real->sig_refcount > 0)
02155     return TRUE;
02156   _dbus_assert (real->sig_refcount == 0);
02157 
02158   retval = TRUE;
02159 
02160   str = real->u.writer.type_str;
02161 
02162   v_STRING = _dbus_string_get_const_data (str);
02163   if (!_dbus_header_set_field_basic (&real->message->header,
02164                                      DBUS_HEADER_FIELD_SIGNATURE,
02165                                      DBUS_TYPE_SIGNATURE,
02166                                      &v_STRING))
02167     retval = FALSE;
02168 
02169   _dbus_type_writer_remove_types (&real->u.writer);
02170   _dbus_string_free (str);
02171   dbus_free (str);
02172 
02173   return retval;
02174 }
02175 
02176 #ifndef DBUS_DISABLE_CHECKS
02177 static dbus_bool_t
02178 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02179 {
02180   if (!_dbus_message_iter_check (iter))
02181     return FALSE;
02182 
02183   if (iter->message->locked)
02184     {
02185       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02186       return FALSE;
02187     }
02188 
02189   return TRUE;
02190 }
02191 #endif /* DBUS_DISABLE_CHECKS */
02192 
02208 dbus_bool_t
02209 dbus_message_iter_append_basic (DBusMessageIter *iter,
02210                                 int              type,
02211                                 const void      *value)
02212 {
02213   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02214   dbus_bool_t ret;
02215 
02216   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02217   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02218   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02219   _dbus_return_val_if_fail (value != NULL, FALSE);
02220 
02221   if (!_dbus_message_iter_open_signature (real))
02222     return FALSE;
02223 
02224   ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02225 
02226   if (!_dbus_message_iter_close_signature (real))
02227     ret = FALSE;
02228 
02229   return ret;
02230 }
02231 
02267 dbus_bool_t
02268 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02269                                       int              element_type,
02270                                       const void      *value,
02271                                       int              n_elements)
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_fixed (element_type), FALSE);
02279   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02280   _dbus_return_val_if_fail (value != NULL, FALSE);
02281   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02282   _dbus_return_val_if_fail (n_elements <=
02283                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02284                             FALSE);
02285 
02286   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02287 
02288   return ret;
02289 }
02290 
02312 dbus_bool_t
02313 dbus_message_iter_open_container (DBusMessageIter *iter,
02314                                   int              type,
02315                                   const char      *contained_signature,
02316                                   DBusMessageIter *sub)
02317 {
02318   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02319   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02320   DBusString contained_str;
02321 
02322   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02323   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02324   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02325   _dbus_return_val_if_fail (sub != NULL, FALSE);
02326   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02327                              contained_signature == NULL) ||
02328                             (type == DBUS_TYPE_DICT_ENTRY &&
02329                              contained_signature == NULL) ||
02330                             contained_signature != NULL, FALSE);
02331   
02332 #if 0
02333   /* FIXME this would fail if the contained_signature is a dict entry,
02334    * since dict entries are invalid signatures standalone (they must be in
02335    * an array)
02336    */
02337   _dbus_return_val_if_fail (contained_signature == NULL ||
02338                             _dbus_check_is_valid_signature (contained_signature));
02339 #endif
02340 
02341   if (!_dbus_message_iter_open_signature (real))
02342     return FALSE;
02343 
02344   *real_sub = *real;
02345 
02346   if (contained_signature != NULL)
02347     {
02348       _dbus_string_init_const (&contained_str, contained_signature);
02349 
02350       return _dbus_type_writer_recurse (&real->u.writer,
02351                                         type,
02352                                         &contained_str, 0,
02353                                         &real_sub->u.writer);
02354     }
02355   else
02356     {
02357       return _dbus_type_writer_recurse (&real->u.writer,
02358                                         type,
02359                                         NULL, 0,
02360                                         &real_sub->u.writer);
02361     } 
02362 }
02363 
02364 
02378 dbus_bool_t
02379 dbus_message_iter_close_container (DBusMessageIter *iter,
02380                                    DBusMessageIter *sub)
02381 {
02382   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02383   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02384   dbus_bool_t ret;
02385 
02386   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02387   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02388   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02389   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02390 
02391   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02392                                      &real_sub->u.writer);
02393 
02394   if (!_dbus_message_iter_close_signature (real))
02395     ret = FALSE;
02396 
02397   return ret;
02398 }
02399 
02416 void
02417 dbus_message_set_no_reply (DBusMessage *message,
02418                            dbus_bool_t  no_reply)
02419 {
02420   _dbus_return_if_fail (message != NULL);
02421   _dbus_return_if_fail (!message->locked);
02422 
02423   _dbus_header_toggle_flag (&message->header,
02424                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02425                             no_reply);
02426 }
02427 
02435 dbus_bool_t
02436 dbus_message_get_no_reply (DBusMessage *message)
02437 {
02438   _dbus_return_val_if_fail (message != NULL, FALSE);
02439 
02440   return _dbus_header_get_flag (&message->header,
02441                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02442 }
02443 
02458 void
02459 dbus_message_set_auto_start (DBusMessage *message,
02460                              dbus_bool_t  auto_start)
02461 {
02462   _dbus_return_if_fail (message != NULL);
02463   _dbus_return_if_fail (!message->locked);
02464 
02465   _dbus_header_toggle_flag (&message->header,
02466                             DBUS_HEADER_FLAG_NO_AUTO_START,
02467                             !auto_start);
02468 }
02469 
02477 dbus_bool_t
02478 dbus_message_get_auto_start (DBusMessage *message)
02479 {
02480   _dbus_return_val_if_fail (message != NULL, FALSE);
02481 
02482   return !_dbus_header_get_flag (&message->header,
02483                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02484 }
02485 
02486 
02499 dbus_bool_t
02500 dbus_message_set_path (DBusMessage   *message,
02501                        const char    *object_path)
02502 {
02503   _dbus_return_val_if_fail (message != NULL, FALSE);
02504   _dbus_return_val_if_fail (!message->locked, FALSE);
02505   _dbus_return_val_if_fail (object_path == NULL ||
02506                             _dbus_check_is_valid_path (object_path),
02507                             FALSE);
02508 
02509   return set_or_delete_string_field (message,
02510                                      DBUS_HEADER_FIELD_PATH,
02511                                      DBUS_TYPE_OBJECT_PATH,
02512                                      object_path);
02513 }
02514 
02528 const char*
02529 dbus_message_get_path (DBusMessage   *message)
02530 {
02531   const char *v;
02532 
02533   _dbus_return_val_if_fail (message != NULL, NULL);
02534 
02535   v = NULL; /* in case field doesn't exist */
02536   _dbus_header_get_field_basic (&message->header,
02537                                 DBUS_HEADER_FIELD_PATH,
02538                                 DBUS_TYPE_OBJECT_PATH,
02539                                 &v);
02540   return v;
02541 }
02542 
02552 dbus_bool_t
02553 dbus_message_has_path (DBusMessage   *message,
02554                        const char    *path)
02555 {
02556   const char *msg_path;
02557   msg_path = dbus_message_get_path (message);
02558   
02559   if (msg_path == NULL)
02560     {
02561       if (path == NULL)
02562         return TRUE;
02563       else
02564         return FALSE;
02565     }
02566 
02567   if (path == NULL)
02568     return FALSE;
02569    
02570   if (strcmp (msg_path, path) == 0)
02571     return TRUE;
02572 
02573   return FALSE;
02574 }
02575 
02596 dbus_bool_t
02597 dbus_message_get_path_decomposed (DBusMessage   *message,
02598                                   char        ***path)
02599 {
02600   const char *v;
02601 
02602   _dbus_return_val_if_fail (message != NULL, FALSE);
02603   _dbus_return_val_if_fail (path != NULL, FALSE);
02604 
02605   *path = NULL;
02606 
02607   v = dbus_message_get_path (message);
02608   if (v != NULL)
02609     {
02610       if (!_dbus_decompose_path (v, strlen (v),
02611                                  path, NULL))
02612         return FALSE;
02613     }
02614   return TRUE;
02615 }
02616 
02630 dbus_bool_t
02631 dbus_message_set_interface (DBusMessage  *message,
02632                             const char   *interface)
02633 {
02634   _dbus_return_val_if_fail (message != NULL, FALSE);
02635   _dbus_return_val_if_fail (!message->locked, FALSE);
02636   _dbus_return_val_if_fail (interface == NULL ||
02637                             _dbus_check_is_valid_interface (interface),
02638                             FALSE);
02639 
02640   return set_or_delete_string_field (message,
02641                                      DBUS_HEADER_FIELD_INTERFACE,
02642                                      DBUS_TYPE_STRING,
02643                                      interface);
02644 }
02645 
02659 const char*
02660 dbus_message_get_interface (DBusMessage *message)
02661 {
02662   const char *v;
02663 
02664   _dbus_return_val_if_fail (message != NULL, NULL);
02665 
02666   v = NULL; /* in case field doesn't exist */
02667   _dbus_header_get_field_basic (&message->header,
02668                                 DBUS_HEADER_FIELD_INTERFACE,
02669                                 DBUS_TYPE_STRING,
02670                                 &v);
02671   return v;
02672 }
02673 
02681 dbus_bool_t
02682 dbus_message_has_interface (DBusMessage   *message,
02683                             const char    *interface)
02684 {
02685   const char *msg_interface;
02686   msg_interface = dbus_message_get_interface (message);
02687    
02688   if (msg_interface == NULL)
02689     {
02690       if (interface == NULL)
02691         return TRUE;
02692       else
02693         return FALSE;
02694     }
02695 
02696   if (interface == NULL)
02697     return FALSE;
02698      
02699   if (strcmp (msg_interface, interface) == 0)
02700     return TRUE;
02701 
02702   return FALSE;
02703 
02704 }
02705 
02718 dbus_bool_t
02719 dbus_message_set_member (DBusMessage  *message,
02720                          const char   *member)
02721 {
02722   _dbus_return_val_if_fail (message != NULL, FALSE);
02723   _dbus_return_val_if_fail (!message->locked, FALSE);
02724   _dbus_return_val_if_fail (member == NULL ||
02725                             _dbus_check_is_valid_member (member),
02726                             FALSE);
02727 
02728   return set_or_delete_string_field (message,
02729                                      DBUS_HEADER_FIELD_MEMBER,
02730                                      DBUS_TYPE_STRING,
02731                                      member);
02732 }
02733 
02745 const char*
02746 dbus_message_get_member (DBusMessage *message)
02747 {
02748   const char *v;
02749 
02750   _dbus_return_val_if_fail (message != NULL, NULL);
02751 
02752   v = NULL; /* in case field doesn't exist */
02753   _dbus_header_get_field_basic (&message->header,
02754                                 DBUS_HEADER_FIELD_MEMBER,
02755                                 DBUS_TYPE_STRING,
02756                                 &v);
02757   return v;
02758 }
02759 
02767 dbus_bool_t
02768 dbus_message_has_member (DBusMessage   *message,
02769                          const char    *member)
02770 {
02771   const char *msg_member;
02772   msg_member = dbus_message_get_member (message);
02773  
02774   if (msg_member == NULL)
02775     {
02776       if (member == NULL)
02777         return TRUE;
02778       else
02779         return FALSE;
02780     }
02781 
02782   if (member == NULL)
02783     return FALSE;
02784     
02785   if (strcmp (msg_member, member) == 0)
02786     return TRUE;
02787 
02788   return FALSE;
02789 
02790 }
02791 
02803 dbus_bool_t
02804 dbus_message_set_error_name (DBusMessage  *message,
02805                              const char   *error_name)
02806 {
02807   _dbus_return_val_if_fail (message != NULL, FALSE);
02808   _dbus_return_val_if_fail (!message->locked, FALSE);
02809   _dbus_return_val_if_fail (error_name == NULL ||
02810                             _dbus_check_is_valid_error_name (error_name),
02811                             FALSE);
02812 
02813   return set_or_delete_string_field (message,
02814                                      DBUS_HEADER_FIELD_ERROR_NAME,
02815                                      DBUS_TYPE_STRING,
02816                                      error_name);
02817 }
02818 
02829 const char*
02830 dbus_message_get_error_name (DBusMessage *message)
02831 {
02832   const char *v;
02833 
02834   _dbus_return_val_if_fail (message != NULL, NULL);
02835 
02836   v = NULL; /* in case field doesn't exist */
02837   _dbus_header_get_field_basic (&message->header,
02838                                 DBUS_HEADER_FIELD_ERROR_NAME,
02839                                 DBUS_TYPE_STRING,
02840                                 &v);
02841   return v;
02842 }
02843 
02857 dbus_bool_t
02858 dbus_message_set_destination (DBusMessage  *message,
02859                               const char   *destination)
02860 {
02861   _dbus_return_val_if_fail (message != NULL, FALSE);
02862   _dbus_return_val_if_fail (!message->locked, FALSE);
02863   _dbus_return_val_if_fail (destination == NULL ||
02864                             _dbus_check_is_valid_bus_name (destination),
02865                             FALSE);
02866 
02867   return set_or_delete_string_field (message,
02868                                      DBUS_HEADER_FIELD_DESTINATION,
02869                                      DBUS_TYPE_STRING,
02870                                      destination);
02871 }
02872 
02882 const char*
02883 dbus_message_get_destination (DBusMessage *message)
02884 {
02885   const char *v;
02886 
02887   _dbus_return_val_if_fail (message != NULL, NULL);
02888 
02889   v = NULL; /* in case field doesn't exist */
02890   _dbus_header_get_field_basic (&message->header,
02891                                 DBUS_HEADER_FIELD_DESTINATION,
02892                                 DBUS_TYPE_STRING,
02893                                 &v);
02894   return v;
02895 }
02896 
02911 dbus_bool_t
02912 dbus_message_set_sender (DBusMessage  *message,
02913                          const char   *sender)
02914 {
02915   _dbus_return_val_if_fail (message != NULL, FALSE);
02916   _dbus_return_val_if_fail (!message->locked, FALSE);
02917   _dbus_return_val_if_fail (sender == NULL ||
02918                             _dbus_check_is_valid_bus_name (sender),
02919                             FALSE);
02920 
02921   return set_or_delete_string_field (message,
02922                                      DBUS_HEADER_FIELD_SENDER,
02923                                      DBUS_TYPE_STRING,
02924                                      sender);
02925 }
02926 
02942 const char*
02943 dbus_message_get_sender (DBusMessage *message)
02944 {
02945   const char *v;
02946 
02947   _dbus_return_val_if_fail (message != NULL, NULL);
02948 
02949   v = NULL; /* in case field doesn't exist */
02950   _dbus_header_get_field_basic (&message->header,
02951                                 DBUS_HEADER_FIELD_SENDER,
02952                                 DBUS_TYPE_STRING,
02953                                 &v);
02954   return v;
02955 }
02956 
02975 const char*
02976 dbus_message_get_signature (DBusMessage *message)
02977 {
02978   const DBusString *type_str;
02979   int type_pos;
02980 
02981   _dbus_return_val_if_fail (message != NULL, NULL);
02982 
02983   get_const_signature (&message->header, &type_str, &type_pos);
02984 
02985   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
02986 }
02987 
02988 static dbus_bool_t
02989 _dbus_message_has_type_interface_member (DBusMessage *message,
02990                                          int          type,
02991                                          const char  *interface,
02992                                          const char  *member)
02993 {
02994   const char *n;
02995 
02996   _dbus_assert (message != NULL);
02997   _dbus_assert (interface != NULL);
02998   _dbus_assert (member != NULL);
02999 
03000   if (dbus_message_get_type (message) != type)
03001     return FALSE;
03002 
03003   /* Optimize by checking the short member name first
03004    * instead of the longer interface name
03005    */
03006 
03007   n = dbus_message_get_member (message);
03008 
03009   if (n && strcmp (n, member) == 0)
03010     {
03011       n = dbus_message_get_interface (message);
03012 
03013       if (n == NULL || strcmp (n, interface) == 0)
03014         return TRUE;
03015     }
03016 
03017   return FALSE;
03018 }
03019 
03034 dbus_bool_t
03035 dbus_message_is_method_call (DBusMessage *message,
03036                              const char  *interface,
03037                              const char  *method)
03038 {
03039   _dbus_return_val_if_fail (message != NULL, FALSE);
03040   _dbus_return_val_if_fail (interface != NULL, FALSE);
03041   _dbus_return_val_if_fail (method != NULL, FALSE);
03042   /* don't check that interface/method are valid since it would be
03043    * expensive, and not catch many common errors
03044    */
03045 
03046   return _dbus_message_has_type_interface_member (message,
03047                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03048                                                   interface, method);
03049 }
03050 
03062 dbus_bool_t
03063 dbus_message_is_signal (DBusMessage *message,
03064                         const char  *interface,
03065                         const char  *signal_name)
03066 {
03067   _dbus_return_val_if_fail (message != NULL, FALSE);
03068   _dbus_return_val_if_fail (interface != NULL, FALSE);
03069   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03070   /* don't check that interface/name are valid since it would be
03071    * expensive, and not catch many common errors
03072    */
03073 
03074   return _dbus_message_has_type_interface_member (message,
03075                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03076                                                   interface, signal_name);
03077 }
03078 
03089 dbus_bool_t
03090 dbus_message_is_error (DBusMessage *message,
03091                        const char  *error_name)
03092 {
03093   const char *n;
03094 
03095   _dbus_return_val_if_fail (message != NULL, FALSE);
03096   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03097   /* don't check that error_name is valid since it would be expensive,
03098    * and not catch many common errors
03099    */
03100 
03101   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03102     return FALSE;
03103 
03104   n = dbus_message_get_error_name (message);
03105 
03106   if (n && strcmp (n, error_name) == 0)
03107     return TRUE;
03108   else
03109     return FALSE;
03110 }
03111 
03122 dbus_bool_t
03123 dbus_message_has_destination (DBusMessage  *message,
03124                               const char   *name)
03125 {
03126   const char *s;
03127 
03128   _dbus_return_val_if_fail (message != NULL, FALSE);
03129   _dbus_return_val_if_fail (name != NULL, FALSE);
03130   /* don't check that name is valid since it would be expensive, and
03131    * not catch many common errors
03132    */
03133 
03134   s = dbus_message_get_destination (message);
03135 
03136   if (s && strcmp (s, name) == 0)
03137     return TRUE;
03138   else
03139     return FALSE;
03140 }
03141 
03157 dbus_bool_t
03158 dbus_message_has_sender (DBusMessage  *message,
03159                          const char   *name)
03160 {
03161   const char *s;
03162 
03163   _dbus_return_val_if_fail (message != NULL, FALSE);
03164   _dbus_return_val_if_fail (name != NULL, FALSE);
03165   /* don't check that name is valid since it would be expensive, and
03166    * not catch many common errors
03167    */
03168 
03169   s = dbus_message_get_sender (message);
03170 
03171   if (s && strcmp (s, name) == 0)
03172     return TRUE;
03173   else
03174     return FALSE;
03175 }
03176 
03186 dbus_bool_t
03187 dbus_message_has_signature (DBusMessage   *message,
03188                             const char    *signature)
03189 {
03190   const char *s;
03191 
03192   _dbus_return_val_if_fail (message != NULL, FALSE);
03193   _dbus_return_val_if_fail (signature != NULL, FALSE);
03194   /* don't check that signature is valid since it would be expensive,
03195    * and not catch many common errors
03196    */
03197 
03198   s = dbus_message_get_signature (message);
03199 
03200   if (s && strcmp (s, signature) == 0)
03201     return TRUE;
03202   else
03203     return FALSE;
03204 }
03205 
03228 dbus_bool_t
03229 dbus_set_error_from_message (DBusError   *error,
03230                              DBusMessage *message)
03231 {
03232   const char *str;
03233 
03234   _dbus_return_val_if_fail (message != NULL, FALSE);
03235   _dbus_return_val_if_error_is_set (error, FALSE);
03236 
03237   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03238     return FALSE;
03239 
03240   str = NULL;
03241   dbus_message_get_args (message, NULL,
03242                          DBUS_TYPE_STRING, &str,
03243                          DBUS_TYPE_INVALID);
03244 
03245   dbus_set_error (error, dbus_message_get_error_name (message),
03246                   str ? "%s" : NULL, str);
03247 
03248   return TRUE;
03249 }
03250 
03269 #define INITIAL_LOADER_DATA_LEN 32
03270 
03277 DBusMessageLoader*
03278 _dbus_message_loader_new (void)
03279 {
03280   DBusMessageLoader *loader;
03281 
03282   loader = dbus_new0 (DBusMessageLoader, 1);
03283   if (loader == NULL)
03284     return NULL;
03285   
03286   loader->refcount = 1;
03287 
03288   loader->corrupted = FALSE;
03289   loader->corruption_reason = DBUS_VALID;
03290 
03291   /* this can be configured by the app, but defaults to the protocol max */
03292   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03293 
03294   if (!_dbus_string_init (&loader->data))
03295     {
03296       dbus_free (loader);
03297       return NULL;
03298     }
03299 
03300   /* preallocate the buffer for speed, ignore failure */
03301   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03302   _dbus_string_set_length (&loader->data, 0);
03303 
03304   return loader;
03305 }
03306 
03313 DBusMessageLoader *
03314 _dbus_message_loader_ref (DBusMessageLoader *loader)
03315 {
03316   loader->refcount += 1;
03317 
03318   return loader;
03319 }
03320 
03327 void
03328 _dbus_message_loader_unref (DBusMessageLoader *loader)
03329 {
03330   loader->refcount -= 1;
03331   if (loader->refcount == 0)
03332     {
03333       _dbus_list_foreach (&loader->messages,
03334                           (DBusForeachFunction) dbus_message_unref,
03335                           NULL);
03336       _dbus_list_clear (&loader->messages);
03337       _dbus_string_free (&loader->data);
03338       dbus_free (loader);
03339     }
03340 }
03341 
03360 void
03361 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03362                                  DBusString        **buffer)
03363 {
03364   _dbus_assert (!loader->buffer_outstanding);
03365 
03366   *buffer = &loader->data;
03367 
03368   loader->buffer_outstanding = TRUE;
03369 }
03370 
03381 void
03382 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03383                                     DBusString         *buffer,
03384                                     int                 bytes_read)
03385 {
03386   _dbus_assert (loader->buffer_outstanding);
03387   _dbus_assert (buffer == &loader->data);
03388 
03389   loader->buffer_outstanding = FALSE;
03390 }
03391 
03392 /*
03393  * FIXME when we move the header out of the buffer, that memmoves all
03394  * buffered messages. Kind of crappy.
03395  *
03396  * Also we copy the header and body, which is kind of crappy.  To
03397  * avoid this, we have to allow header and body to be in a single
03398  * memory block, which is good for messages we read and bad for
03399  * messages we are creating. But we could move_len() the buffer into
03400  * this single memory block, and move_len() will just swap the buffers
03401  * if you're moving the entire buffer replacing the dest string.
03402  *
03403  * We could also have the message loader tell the transport how many
03404  * bytes to read; so it would first ask for some arbitrary number like
03405  * 256, then if the message was incomplete it would use the
03406  * header/body len to ask for exactly the size of the message (or
03407  * blocks the size of a typical kernel buffer for the socket). That
03408  * way we don't get trailing bytes in the buffer that have to be
03409  * memmoved. Though I suppose we also don't have a chance of reading a
03410  * bunch of small messages at once, so the optimization may be stupid.
03411  *
03412  * Another approach would be to keep a "start" index into
03413  * loader->data and only delete it occasionally, instead of after
03414  * each message is loaded.
03415  *
03416  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03417  */
03418 static dbus_bool_t
03419 load_message (DBusMessageLoader *loader,
03420               DBusMessage       *message,
03421               int                byte_order,
03422               int                fields_array_len,
03423               int                header_len,
03424               int                body_len)
03425 {
03426   dbus_bool_t oom;
03427   DBusValidity validity;
03428   const DBusString *type_str;
03429   int type_pos;
03430   DBusValidationMode mode;
03431 
03432   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03433   
03434   oom = FALSE;
03435 
03436 #if 0
03437   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03438 #endif
03439 
03440   /* 1. VALIDATE AND COPY OVER HEADER */
03441   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03442   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03443 
03444   if (!_dbus_header_load (&message->header,
03445                           mode,
03446                           &validity,
03447                           byte_order,
03448                           fields_array_len,
03449                           header_len,
03450                           body_len,
03451                           &loader->data, 0,
03452                           _dbus_string_get_length (&loader->data)))
03453     {
03454       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03455 
03456       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03457          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03458       _dbus_assert (validity != DBUS_VALID);
03459 
03460       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03461         oom = TRUE;
03462       else
03463         {
03464           loader->corrupted = TRUE;
03465           loader->corruption_reason = validity;
03466         }
03467       goto failed;
03468     }
03469 
03470   _dbus_assert (validity == DBUS_VALID);
03471 
03472   message->byte_order = byte_order;
03473 
03474   /* 2. VALIDATE BODY */
03475   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
03476     {
03477       get_const_signature (&message->header, &type_str, &type_pos);
03478       
03479       /* Because the bytes_remaining arg is NULL, this validates that the
03480        * body is the right length
03481        */
03482       validity = _dbus_validate_body_with_reason (type_str,
03483                                                   type_pos,
03484                                                   byte_order,
03485                                                   NULL,
03486                                                   &loader->data,
03487                                                   header_len,
03488                                                   body_len);
03489       if (validity != DBUS_VALID)
03490         {
03491           _dbus_verbose ("Failed to validate message body code %d\n", validity);
03492 
03493           loader->corrupted = TRUE;
03494           loader->corruption_reason = validity;
03495           
03496           goto failed;
03497         }
03498     }
03499 
03500   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
03501 
03502   if (!_dbus_list_append (&loader->messages, message))
03503     {
03504       _dbus_verbose ("Failed to append new message to loader queue\n");
03505       oom = TRUE;
03506       goto failed;
03507     }
03508 
03509   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
03510   _dbus_assert (_dbus_string_get_length (&loader->data) >=
03511                 (header_len + body_len));
03512 
03513   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
03514     {
03515       _dbus_verbose ("Failed to move body into new message\n");
03516       oom = TRUE;
03517       goto failed;
03518     }
03519 
03520   _dbus_string_delete (&loader->data, 0, header_len + body_len);
03521 
03522   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
03523   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
03524 
03525   _dbus_verbose ("Loaded message %p\n", message);
03526 
03527   _dbus_assert (!oom);
03528   _dbus_assert (!loader->corrupted);
03529   _dbus_assert (loader->messages != NULL);
03530   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03531 
03532   return TRUE;
03533 
03534  failed:
03535 
03536   /* Clean up */
03537 
03538   /* does nothing if the message isn't in the list */
03539   _dbus_list_remove_last (&loader->messages, message);
03540   
03541   if (oom)
03542     _dbus_assert (!loader->corrupted);
03543   else
03544     _dbus_assert (loader->corrupted);
03545 
03546   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
03547 
03548   return FALSE;
03549 }
03550 
03565 dbus_bool_t
03566 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
03567 {
03568   while (!loader->corrupted &&
03569          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
03570     {
03571       DBusValidity validity;
03572       int byte_order, fields_array_len, header_len, body_len;
03573 
03574       if (_dbus_header_have_message_untrusted (loader->max_message_size,
03575                                                &validity,
03576                                                &byte_order,
03577                                                &fields_array_len,
03578                                                &header_len,
03579                                                &body_len,
03580                                                &loader->data, 0,
03581                                                _dbus_string_get_length (&loader->data)))
03582         {
03583           DBusMessage *message;
03584 
03585           _dbus_assert (validity == DBUS_VALID);
03586 
03587           message = dbus_message_new_empty_header ();
03588           if (message == NULL)
03589             return FALSE;
03590 
03591           if (!load_message (loader, message,
03592                              byte_order, fields_array_len,
03593                              header_len, body_len))
03594             {
03595               dbus_message_unref (message);
03596               /* load_message() returns false if corrupted or OOM; if
03597                * corrupted then return TRUE for not OOM
03598                */
03599               return loader->corrupted;
03600             }
03601 
03602           _dbus_assert (loader->messages != NULL);
03603           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03604         }
03605       else
03606         {
03607           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
03608                          validity);
03609           if (validity != DBUS_VALID)
03610             {
03611               loader->corrupted = TRUE;
03612               loader->corruption_reason = validity;
03613             }
03614           return TRUE;
03615         }
03616     }
03617 
03618   return TRUE;
03619 }
03620 
03628 DBusMessage*
03629 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
03630 {
03631   if (loader->messages)
03632     return loader->messages->data;
03633   else
03634     return NULL;
03635 }
03636 
03645 DBusMessage*
03646 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
03647 {
03648   return _dbus_list_pop_first (&loader->messages);
03649 }
03650 
03659 DBusList*
03660 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
03661 {
03662   return _dbus_list_pop_first_link (&loader->messages);
03663 }
03664 
03671 void
03672 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
03673                                            DBusList           *link)
03674 {
03675   _dbus_list_prepend_link (&loader->messages, link);
03676 }
03677 
03687 dbus_bool_t
03688 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
03689 {
03690   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
03691                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
03692   return loader->corrupted;
03693 }
03694 
03701 void
03702 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
03703                                            long                size)
03704 {
03705   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
03706     {
03707       _dbus_verbose ("clamping requested max message size %ld to %d\n",
03708                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
03709       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03710     }
03711   loader->max_message_size = size;
03712 }
03713 
03720 long
03721 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
03722 {
03723   return loader->max_message_size;
03724 }
03725 
03726 static DBusDataSlotAllocator slot_allocator;
03727 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
03728 
03743 dbus_bool_t
03744 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
03745 {
03746   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03747                                           &_DBUS_LOCK_NAME (message_slots),
03748                                           slot_p);
03749 }
03750 
03762 void
03763 dbus_message_free_data_slot (dbus_int32_t *slot_p)
03764 {
03765   _dbus_return_if_fail (*slot_p >= 0);
03766 
03767   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03768 }
03769 
03783 dbus_bool_t
03784 dbus_message_set_data (DBusMessage     *message,
03785                        dbus_int32_t     slot,
03786                        void            *data,
03787                        DBusFreeFunction free_data_func)
03788 {
03789   DBusFreeFunction old_free_func;
03790   void *old_data;
03791   dbus_bool_t retval;
03792 
03793   _dbus_return_val_if_fail (message != NULL, FALSE);
03794   _dbus_return_val_if_fail (slot >= 0, FALSE);
03795 
03796   retval = _dbus_data_slot_list_set (&slot_allocator,
03797                                      &message->slot_list,
03798                                      slot, data, free_data_func,
03799                                      &old_free_func, &old_data);
03800 
03801   if (retval)
03802     {
03803       /* Do the actual free outside the message lock */
03804       if (old_free_func)
03805         (* old_free_func) (old_data);
03806     }
03807 
03808   return retval;
03809 }
03810 
03819 void*
03820 dbus_message_get_data (DBusMessage   *message,
03821                        dbus_int32_t   slot)
03822 {
03823   void *res;
03824 
03825   _dbus_return_val_if_fail (message != NULL, NULL);
03826 
03827   res = _dbus_data_slot_list_get (&slot_allocator,
03828                                   &message->slot_list,
03829                                   slot);
03830 
03831   return res;
03832 }
03833 
03847 int
03848 dbus_message_type_from_string (const char *type_str)
03849 {
03850   if (strcmp (type_str, "method_call") == 0)
03851     return DBUS_MESSAGE_TYPE_METHOD_CALL;
03852   if (strcmp (type_str, "method_return") == 0)
03853     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
03854   else if (strcmp (type_str, "signal") == 0)
03855     return DBUS_MESSAGE_TYPE_SIGNAL;
03856   else if (strcmp (type_str, "error") == 0)
03857     return DBUS_MESSAGE_TYPE_ERROR;
03858   else
03859     return DBUS_MESSAGE_TYPE_INVALID;
03860 }
03861 
03875 const char *
03876 dbus_message_type_to_string (int type)
03877 {
03878   switch (type)
03879     {
03880     case DBUS_MESSAGE_TYPE_METHOD_CALL:
03881       return "method_call";
03882     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
03883       return "method_return";
03884     case DBUS_MESSAGE_TYPE_SIGNAL:
03885       return "signal";
03886     case DBUS_MESSAGE_TYPE_ERROR:
03887       return "error";
03888     default:
03889       return "invalid";
03890     }
03891 }
03892 
03895 /* tests in dbus-message-util.c */

Generated on Tue Apr 15 15:54:00 2008 for D-Bus by  doxygen 1.5.1