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., 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 
01872 void
01873 dbus_message_iter_recurse (DBusMessageIter  *iter,
01874                            DBusMessageIter  *sub)
01875 {
01876   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01877   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
01878 
01879   _dbus_return_if_fail (_dbus_message_iter_check (real));
01880   _dbus_return_if_fail (sub != NULL);
01881 
01882   *real_sub = *real;
01883   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
01884 }
01885 
01897 char *
01898 dbus_message_iter_get_signature (DBusMessageIter *iter)
01899 {
01900   const DBusString *sig;
01901   DBusString retstr;
01902   char *ret;
01903   int start, len;
01904   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01905 
01906   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
01907 
01908   if (!_dbus_string_init (&retstr))
01909     return NULL;
01910 
01911   _dbus_type_reader_get_signature (&real->u.reader, &sig,
01912                                    &start, &len);
01913   if (!_dbus_string_append_len (&retstr,
01914                                 _dbus_string_get_const_data (sig) + start,
01915                                 len))
01916     return NULL;
01917   if (!_dbus_string_steal_data (&retstr, &ret))
01918     return NULL;
01919   _dbus_string_free (&retstr);
01920   return ret;
01921 }
01922 
01963 void
01964 dbus_message_iter_get_basic (DBusMessageIter  *iter,
01965                              void             *value)
01966 {
01967   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01968 
01969   _dbus_return_if_fail (_dbus_message_iter_check (real));
01970   _dbus_return_if_fail (value != NULL);
01971 
01972   _dbus_type_reader_read_basic (&real->u.reader,
01973                                 value);
01974 }
01975 
01994 int
01995 dbus_message_iter_get_array_len (DBusMessageIter *iter)
01996 {
01997   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01998 
01999   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02000 
02001   return _dbus_type_reader_get_array_length (&real->u.reader);
02002 }
02003 
02035 void
02036 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02037                                    void             *value,
02038                                    int              *n_elements)
02039 {
02040   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02041   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02042 
02043   _dbus_return_if_fail (_dbus_message_iter_check (real));
02044   _dbus_return_if_fail (value != NULL);
02045   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02046                          dbus_type_is_fixed (subtype));
02047 
02048   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02049                                       value, n_elements);
02050 }
02051 
02063 void
02064 dbus_message_iter_init_append (DBusMessage     *message,
02065                                DBusMessageIter *iter)
02066 {
02067   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02068 
02069   _dbus_return_if_fail (message != NULL);
02070   _dbus_return_if_fail (iter != NULL);
02071 
02072   _dbus_message_iter_init_common (message, real,
02073                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02074 
02075   /* We create the signature string and point iterators at it "on demand"
02076    * when a value is actually appended. That means that init() never fails
02077    * due to OOM.
02078    */
02079   _dbus_type_writer_init_types_delayed (&real->u.writer,
02080                                         message->byte_order,
02081                                         &message->body,
02082                                         _dbus_string_get_length (&message->body));
02083 }
02084 
02093 static dbus_bool_t
02094 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02095 {
02096   DBusString *str;
02097   const DBusString *current_sig;
02098   int current_sig_pos;
02099 
02100   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02101 
02102   if (real->u.writer.type_str != NULL)
02103     {
02104       _dbus_assert (real->sig_refcount > 0);
02105       real->sig_refcount += 1;
02106       return TRUE;
02107     }
02108 
02109   str = dbus_new (DBusString, 1);
02110   if (str == NULL)
02111     return FALSE;
02112 
02113   if (!_dbus_header_get_field_raw (&real->message->header,
02114                                    DBUS_HEADER_FIELD_SIGNATURE,
02115                                    &current_sig, &current_sig_pos))
02116     current_sig = NULL;
02117 
02118   if (current_sig)
02119     {
02120       int current_len;
02121 
02122       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02123       current_sig_pos += 1; /* move on to sig data */
02124 
02125       if (!_dbus_string_init_preallocated (str, current_len + 4))
02126         {
02127           dbus_free (str);
02128           return FALSE;
02129         }
02130 
02131       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02132                                   str, 0))
02133         {
02134           _dbus_string_free (str);
02135           dbus_free (str);
02136           return FALSE;
02137         }
02138     }
02139   else
02140     {
02141       if (!_dbus_string_init_preallocated (str, 4))
02142         {
02143           dbus_free (str);
02144           return FALSE;
02145         }
02146     }
02147 
02148   real->sig_refcount = 1;
02149 
02150   _dbus_type_writer_add_types (&real->u.writer,
02151                                str, _dbus_string_get_length (str));
02152   return TRUE;
02153 }
02154 
02164 static dbus_bool_t
02165 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02166 {
02167   DBusString *str;
02168   const char *v_STRING;
02169   dbus_bool_t retval;
02170 
02171   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02172   _dbus_assert (real->u.writer.type_str != NULL);
02173   _dbus_assert (real->sig_refcount > 0);
02174 
02175   real->sig_refcount -= 1;
02176 
02177   if (real->sig_refcount > 0)
02178     return TRUE;
02179   _dbus_assert (real->sig_refcount == 0);
02180 
02181   retval = TRUE;
02182 
02183   str = real->u.writer.type_str;
02184 
02185   v_STRING = _dbus_string_get_const_data (str);
02186   if (!_dbus_header_set_field_basic (&real->message->header,
02187                                      DBUS_HEADER_FIELD_SIGNATURE,
02188                                      DBUS_TYPE_SIGNATURE,
02189                                      &v_STRING))
02190     retval = FALSE;
02191 
02192   _dbus_type_writer_remove_types (&real->u.writer);
02193   _dbus_string_free (str);
02194   dbus_free (str);
02195 
02196   return retval;
02197 }
02198 
02199 #ifndef DBUS_DISABLE_CHECKS
02200 static dbus_bool_t
02201 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02202 {
02203   if (!_dbus_message_iter_check (iter))
02204     return FALSE;
02205 
02206   if (iter->message->locked)
02207     {
02208       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02209       return FALSE;
02210     }
02211 
02212   return TRUE;
02213 }
02214 #endif /* DBUS_DISABLE_CHECKS */
02215 
02231 dbus_bool_t
02232 dbus_message_iter_append_basic (DBusMessageIter *iter,
02233                                 int              type,
02234                                 const void      *value)
02235 {
02236   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02237   dbus_bool_t ret;
02238 
02239   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02240   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02241   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02242   _dbus_return_val_if_fail (value != NULL, FALSE);
02243 
02244   if (!_dbus_message_iter_open_signature (real))
02245     return FALSE;
02246 
02247   ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02248 
02249   if (!_dbus_message_iter_close_signature (real))
02250     ret = FALSE;
02251 
02252   return ret;
02253 }
02254 
02290 dbus_bool_t
02291 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02292                                       int              element_type,
02293                                       const void      *value,
02294                                       int              n_elements)
02295 {
02296   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02297   dbus_bool_t ret;
02298 
02299   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02300   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02301   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type), FALSE);
02302   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02303   _dbus_return_val_if_fail (value != NULL, FALSE);
02304   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02305   _dbus_return_val_if_fail (n_elements <=
02306                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02307                             FALSE);
02308 
02309   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02310 
02311   return ret;
02312 }
02313 
02335 dbus_bool_t
02336 dbus_message_iter_open_container (DBusMessageIter *iter,
02337                                   int              type,
02338                                   const char      *contained_signature,
02339                                   DBusMessageIter *sub)
02340 {
02341   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02342   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02343   DBusString contained_str;
02344 
02345   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02346   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02347   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02348   _dbus_return_val_if_fail (sub != NULL, FALSE);
02349   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02350                              contained_signature == NULL) ||
02351                             (type == DBUS_TYPE_DICT_ENTRY &&
02352                              contained_signature == NULL) ||
02353                             (type == DBUS_TYPE_VARIANT &&
02354                              contained_signature != NULL) ||
02355                             (type == DBUS_TYPE_ARRAY &&
02356                              contained_signature != NULL), FALSE);
02357   
02358   /* this would fail if the contained_signature is a dict entry, since
02359    * dict entries are invalid signatures standalone (they must be in
02360    * an array)
02361    */
02362   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02363                             (contained_signature == NULL ||
02364                              _dbus_check_is_valid_signature (contained_signature)),
02365                             FALSE);
02366 
02367   if (!_dbus_message_iter_open_signature (real))
02368     return FALSE;
02369 
02370   *real_sub = *real;
02371 
02372   if (contained_signature != NULL)
02373     {
02374       _dbus_string_init_const (&contained_str, contained_signature);
02375 
02376       return _dbus_type_writer_recurse (&real->u.writer,
02377                                         type,
02378                                         &contained_str, 0,
02379                                         &real_sub->u.writer);
02380     }
02381   else
02382     {
02383       return _dbus_type_writer_recurse (&real->u.writer,
02384                                         type,
02385                                         NULL, 0,
02386                                         &real_sub->u.writer);
02387     } 
02388 }
02389 
02390 
02404 dbus_bool_t
02405 dbus_message_iter_close_container (DBusMessageIter *iter,
02406                                    DBusMessageIter *sub)
02407 {
02408   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02409   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02410   dbus_bool_t ret;
02411 
02412   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02413   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02414   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02415   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02416 
02417   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02418                                      &real_sub->u.writer);
02419 
02420   if (!_dbus_message_iter_close_signature (real))
02421     ret = FALSE;
02422 
02423   return ret;
02424 }
02425 
02442 void
02443 dbus_message_set_no_reply (DBusMessage *message,
02444                            dbus_bool_t  no_reply)
02445 {
02446   _dbus_return_if_fail (message != NULL);
02447   _dbus_return_if_fail (!message->locked);
02448 
02449   _dbus_header_toggle_flag (&message->header,
02450                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02451                             no_reply);
02452 }
02453 
02461 dbus_bool_t
02462 dbus_message_get_no_reply (DBusMessage *message)
02463 {
02464   _dbus_return_val_if_fail (message != NULL, FALSE);
02465 
02466   return _dbus_header_get_flag (&message->header,
02467                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02468 }
02469 
02484 void
02485 dbus_message_set_auto_start (DBusMessage *message,
02486                              dbus_bool_t  auto_start)
02487 {
02488   _dbus_return_if_fail (message != NULL);
02489   _dbus_return_if_fail (!message->locked);
02490 
02491   _dbus_header_toggle_flag (&message->header,
02492                             DBUS_HEADER_FLAG_NO_AUTO_START,
02493                             !auto_start);
02494 }
02495 
02503 dbus_bool_t
02504 dbus_message_get_auto_start (DBusMessage *message)
02505 {
02506   _dbus_return_val_if_fail (message != NULL, FALSE);
02507 
02508   return !_dbus_header_get_flag (&message->header,
02509                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02510 }
02511 
02512 
02525 dbus_bool_t
02526 dbus_message_set_path (DBusMessage   *message,
02527                        const char    *object_path)
02528 {
02529   _dbus_return_val_if_fail (message != NULL, FALSE);
02530   _dbus_return_val_if_fail (!message->locked, FALSE);
02531   _dbus_return_val_if_fail (object_path == NULL ||
02532                             _dbus_check_is_valid_path (object_path),
02533                             FALSE);
02534 
02535   return set_or_delete_string_field (message,
02536                                      DBUS_HEADER_FIELD_PATH,
02537                                      DBUS_TYPE_OBJECT_PATH,
02538                                      object_path);
02539 }
02540 
02554 const char*
02555 dbus_message_get_path (DBusMessage   *message)
02556 {
02557   const char *v;
02558 
02559   _dbus_return_val_if_fail (message != NULL, NULL);
02560 
02561   v = NULL; /* in case field doesn't exist */
02562   _dbus_header_get_field_basic (&message->header,
02563                                 DBUS_HEADER_FIELD_PATH,
02564                                 DBUS_TYPE_OBJECT_PATH,
02565                                 &v);
02566   return v;
02567 }
02568 
02578 dbus_bool_t
02579 dbus_message_has_path (DBusMessage   *message,
02580                        const char    *path)
02581 {
02582   const char *msg_path;
02583   msg_path = dbus_message_get_path (message);
02584   
02585   if (msg_path == NULL)
02586     {
02587       if (path == NULL)
02588         return TRUE;
02589       else
02590         return FALSE;
02591     }
02592 
02593   if (path == NULL)
02594     return FALSE;
02595    
02596   if (strcmp (msg_path, path) == 0)
02597     return TRUE;
02598 
02599   return FALSE;
02600 }
02601 
02622 dbus_bool_t
02623 dbus_message_get_path_decomposed (DBusMessage   *message,
02624                                   char        ***path)
02625 {
02626   const char *v;
02627 
02628   _dbus_return_val_if_fail (message != NULL, FALSE);
02629   _dbus_return_val_if_fail (path != NULL, FALSE);
02630 
02631   *path = NULL;
02632 
02633   v = dbus_message_get_path (message);
02634   if (v != NULL)
02635     {
02636       if (!_dbus_decompose_path (v, strlen (v),
02637                                  path, NULL))
02638         return FALSE;
02639     }
02640   return TRUE;
02641 }
02642 
02656 dbus_bool_t
02657 dbus_message_set_interface (DBusMessage  *message,
02658                             const char   *interface)
02659 {
02660   _dbus_return_val_if_fail (message != NULL, FALSE);
02661   _dbus_return_val_if_fail (!message->locked, FALSE);
02662   _dbus_return_val_if_fail (interface == NULL ||
02663                             _dbus_check_is_valid_interface (interface),
02664                             FALSE);
02665 
02666   return set_or_delete_string_field (message,
02667                                      DBUS_HEADER_FIELD_INTERFACE,
02668                                      DBUS_TYPE_STRING,
02669                                      interface);
02670 }
02671 
02685 const char*
02686 dbus_message_get_interface (DBusMessage *message)
02687 {
02688   const char *v;
02689 
02690   _dbus_return_val_if_fail (message != NULL, NULL);
02691 
02692   v = NULL; /* in case field doesn't exist */
02693   _dbus_header_get_field_basic (&message->header,
02694                                 DBUS_HEADER_FIELD_INTERFACE,
02695                                 DBUS_TYPE_STRING,
02696                                 &v);
02697   return v;
02698 }
02699 
02707 dbus_bool_t
02708 dbus_message_has_interface (DBusMessage   *message,
02709                             const char    *interface)
02710 {
02711   const char *msg_interface;
02712   msg_interface = dbus_message_get_interface (message);
02713    
02714   if (msg_interface == NULL)
02715     {
02716       if (interface == NULL)
02717         return TRUE;
02718       else
02719         return FALSE;
02720     }
02721 
02722   if (interface == NULL)
02723     return FALSE;
02724      
02725   if (strcmp (msg_interface, interface) == 0)
02726     return TRUE;
02727 
02728   return FALSE;
02729 
02730 }
02731 
02744 dbus_bool_t
02745 dbus_message_set_member (DBusMessage  *message,
02746                          const char   *member)
02747 {
02748   _dbus_return_val_if_fail (message != NULL, FALSE);
02749   _dbus_return_val_if_fail (!message->locked, FALSE);
02750   _dbus_return_val_if_fail (member == NULL ||
02751                             _dbus_check_is_valid_member (member),
02752                             FALSE);
02753 
02754   return set_or_delete_string_field (message,
02755                                      DBUS_HEADER_FIELD_MEMBER,
02756                                      DBUS_TYPE_STRING,
02757                                      member);
02758 }
02759 
02771 const char*
02772 dbus_message_get_member (DBusMessage *message)
02773 {
02774   const char *v;
02775 
02776   _dbus_return_val_if_fail (message != NULL, NULL);
02777 
02778   v = NULL; /* in case field doesn't exist */
02779   _dbus_header_get_field_basic (&message->header,
02780                                 DBUS_HEADER_FIELD_MEMBER,
02781                                 DBUS_TYPE_STRING,
02782                                 &v);
02783   return v;
02784 }
02785 
02793 dbus_bool_t
02794 dbus_message_has_member (DBusMessage   *message,
02795                          const char    *member)
02796 {
02797   const char *msg_member;
02798   msg_member = dbus_message_get_member (message);
02799  
02800   if (msg_member == NULL)
02801     {
02802       if (member == NULL)
02803         return TRUE;
02804       else
02805         return FALSE;
02806     }
02807 
02808   if (member == NULL)
02809     return FALSE;
02810     
02811   if (strcmp (msg_member, member) == 0)
02812     return TRUE;
02813 
02814   return FALSE;
02815 
02816 }
02817 
02829 dbus_bool_t
02830 dbus_message_set_error_name (DBusMessage  *message,
02831                              const char   *error_name)
02832 {
02833   _dbus_return_val_if_fail (message != NULL, FALSE);
02834   _dbus_return_val_if_fail (!message->locked, FALSE);
02835   _dbus_return_val_if_fail (error_name == NULL ||
02836                             _dbus_check_is_valid_error_name (error_name),
02837                             FALSE);
02838 
02839   return set_or_delete_string_field (message,
02840                                      DBUS_HEADER_FIELD_ERROR_NAME,
02841                                      DBUS_TYPE_STRING,
02842                                      error_name);
02843 }
02844 
02855 const char*
02856 dbus_message_get_error_name (DBusMessage *message)
02857 {
02858   const char *v;
02859 
02860   _dbus_return_val_if_fail (message != NULL, NULL);
02861 
02862   v = NULL; /* in case field doesn't exist */
02863   _dbus_header_get_field_basic (&message->header,
02864                                 DBUS_HEADER_FIELD_ERROR_NAME,
02865                                 DBUS_TYPE_STRING,
02866                                 &v);
02867   return v;
02868 }
02869 
02883 dbus_bool_t
02884 dbus_message_set_destination (DBusMessage  *message,
02885                               const char   *destination)
02886 {
02887   _dbus_return_val_if_fail (message != NULL, FALSE);
02888   _dbus_return_val_if_fail (!message->locked, FALSE);
02889   _dbus_return_val_if_fail (destination == NULL ||
02890                             _dbus_check_is_valid_bus_name (destination),
02891                             FALSE);
02892 
02893   return set_or_delete_string_field (message,
02894                                      DBUS_HEADER_FIELD_DESTINATION,
02895                                      DBUS_TYPE_STRING,
02896                                      destination);
02897 }
02898 
02908 const char*
02909 dbus_message_get_destination (DBusMessage *message)
02910 {
02911   const char *v;
02912 
02913   _dbus_return_val_if_fail (message != NULL, NULL);
02914 
02915   v = NULL; /* in case field doesn't exist */
02916   _dbus_header_get_field_basic (&message->header,
02917                                 DBUS_HEADER_FIELD_DESTINATION,
02918                                 DBUS_TYPE_STRING,
02919                                 &v);
02920   return v;
02921 }
02922 
02937 dbus_bool_t
02938 dbus_message_set_sender (DBusMessage  *message,
02939                          const char   *sender)
02940 {
02941   _dbus_return_val_if_fail (message != NULL, FALSE);
02942   _dbus_return_val_if_fail (!message->locked, FALSE);
02943   _dbus_return_val_if_fail (sender == NULL ||
02944                             _dbus_check_is_valid_bus_name (sender),
02945                             FALSE);
02946 
02947   return set_or_delete_string_field (message,
02948                                      DBUS_HEADER_FIELD_SENDER,
02949                                      DBUS_TYPE_STRING,
02950                                      sender);
02951 }
02952 
02968 const char*
02969 dbus_message_get_sender (DBusMessage *message)
02970 {
02971   const char *v;
02972 
02973   _dbus_return_val_if_fail (message != NULL, NULL);
02974 
02975   v = NULL; /* in case field doesn't exist */
02976   _dbus_header_get_field_basic (&message->header,
02977                                 DBUS_HEADER_FIELD_SENDER,
02978                                 DBUS_TYPE_STRING,
02979                                 &v);
02980   return v;
02981 }
02982 
03001 const char*
03002 dbus_message_get_signature (DBusMessage *message)
03003 {
03004   const DBusString *type_str;
03005   int type_pos;
03006 
03007   _dbus_return_val_if_fail (message != NULL, NULL);
03008 
03009   get_const_signature (&message->header, &type_str, &type_pos);
03010 
03011   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03012 }
03013 
03014 static dbus_bool_t
03015 _dbus_message_has_type_interface_member (DBusMessage *message,
03016                                          int          type,
03017                                          const char  *interface,
03018                                          const char  *member)
03019 {
03020   const char *n;
03021 
03022   _dbus_assert (message != NULL);
03023   _dbus_assert (interface != NULL);
03024   _dbus_assert (member != NULL);
03025 
03026   if (dbus_message_get_type (message) != type)
03027     return FALSE;
03028 
03029   /* Optimize by checking the short member name first
03030    * instead of the longer interface name
03031    */
03032 
03033   n = dbus_message_get_member (message);
03034 
03035   if (n && strcmp (n, member) == 0)
03036     {
03037       n = dbus_message_get_interface (message);
03038 
03039       if (n == NULL || strcmp (n, interface) == 0)
03040         return TRUE;
03041     }
03042 
03043   return FALSE;
03044 }
03045 
03060 dbus_bool_t
03061 dbus_message_is_method_call (DBusMessage *message,
03062                              const char  *interface,
03063                              const char  *method)
03064 {
03065   _dbus_return_val_if_fail (message != NULL, FALSE);
03066   _dbus_return_val_if_fail (interface != NULL, FALSE);
03067   _dbus_return_val_if_fail (method != NULL, FALSE);
03068   /* don't check that interface/method are valid since it would be
03069    * expensive, and not catch many common errors
03070    */
03071 
03072   return _dbus_message_has_type_interface_member (message,
03073                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03074                                                   interface, method);
03075 }
03076 
03088 dbus_bool_t
03089 dbus_message_is_signal (DBusMessage *message,
03090                         const char  *interface,
03091                         const char  *signal_name)
03092 {
03093   _dbus_return_val_if_fail (message != NULL, FALSE);
03094   _dbus_return_val_if_fail (interface != NULL, FALSE);
03095   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03096   /* don't check that interface/name are valid since it would be
03097    * expensive, and not catch many common errors
03098    */
03099 
03100   return _dbus_message_has_type_interface_member (message,
03101                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03102                                                   interface, signal_name);
03103 }
03104 
03115 dbus_bool_t
03116 dbus_message_is_error (DBusMessage *message,
03117                        const char  *error_name)
03118 {
03119   const char *n;
03120 
03121   _dbus_return_val_if_fail (message != NULL, FALSE);
03122   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03123   /* don't check that error_name is valid since it would be expensive,
03124    * and not catch many common errors
03125    */
03126 
03127   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03128     return FALSE;
03129 
03130   n = dbus_message_get_error_name (message);
03131 
03132   if (n && strcmp (n, error_name) == 0)
03133     return TRUE;
03134   else
03135     return FALSE;
03136 }
03137 
03148 dbus_bool_t
03149 dbus_message_has_destination (DBusMessage  *message,
03150                               const char   *name)
03151 {
03152   const char *s;
03153 
03154   _dbus_return_val_if_fail (message != NULL, FALSE);
03155   _dbus_return_val_if_fail (name != NULL, FALSE);
03156   /* don't check that name is valid since it would be expensive, and
03157    * not catch many common errors
03158    */
03159 
03160   s = dbus_message_get_destination (message);
03161 
03162   if (s && strcmp (s, name) == 0)
03163     return TRUE;
03164   else
03165     return FALSE;
03166 }
03167 
03183 dbus_bool_t
03184 dbus_message_has_sender (DBusMessage  *message,
03185                          const char   *name)
03186 {
03187   const char *s;
03188 
03189   _dbus_return_val_if_fail (message != NULL, FALSE);
03190   _dbus_return_val_if_fail (name != NULL, FALSE);
03191   /* don't check that name is valid since it would be expensive, and
03192    * not catch many common errors
03193    */
03194 
03195   s = dbus_message_get_sender (message);
03196 
03197   if (s && strcmp (s, name) == 0)
03198     return TRUE;
03199   else
03200     return FALSE;
03201 }
03202 
03212 dbus_bool_t
03213 dbus_message_has_signature (DBusMessage   *message,
03214                             const char    *signature)
03215 {
03216   const char *s;
03217 
03218   _dbus_return_val_if_fail (message != NULL, FALSE);
03219   _dbus_return_val_if_fail (signature != NULL, FALSE);
03220   /* don't check that signature is valid since it would be expensive,
03221    * and not catch many common errors
03222    */
03223 
03224   s = dbus_message_get_signature (message);
03225 
03226   if (s && strcmp (s, signature) == 0)
03227     return TRUE;
03228   else
03229     return FALSE;
03230 }
03231 
03254 dbus_bool_t
03255 dbus_set_error_from_message (DBusError   *error,
03256                              DBusMessage *message)
03257 {
03258   const char *str;
03259 
03260   _dbus_return_val_if_fail (message != NULL, FALSE);
03261   _dbus_return_val_if_error_is_set (error, FALSE);
03262 
03263   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03264     return FALSE;
03265 
03266   str = NULL;
03267   dbus_message_get_args (message, NULL,
03268                          DBUS_TYPE_STRING, &str,
03269                          DBUS_TYPE_INVALID);
03270 
03271   dbus_set_error (error, dbus_message_get_error_name (message),
03272                   str ? "%s" : NULL, str);
03273 
03274   return TRUE;
03275 }
03276 
03295 #define INITIAL_LOADER_DATA_LEN 32
03296 
03303 DBusMessageLoader*
03304 _dbus_message_loader_new (void)
03305 {
03306   DBusMessageLoader *loader;
03307 
03308   loader = dbus_new0 (DBusMessageLoader, 1);
03309   if (loader == NULL)
03310     return NULL;
03311   
03312   loader->refcount = 1;
03313 
03314   loader->corrupted = FALSE;
03315   loader->corruption_reason = DBUS_VALID;
03316 
03317   /* this can be configured by the app, but defaults to the protocol max */
03318   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03319 
03320   if (!_dbus_string_init (&loader->data))
03321     {
03322       dbus_free (loader);
03323       return NULL;
03324     }
03325 
03326   /* preallocate the buffer for speed, ignore failure */
03327   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03328   _dbus_string_set_length (&loader->data, 0);
03329 
03330   return loader;
03331 }
03332 
03339 DBusMessageLoader *
03340 _dbus_message_loader_ref (DBusMessageLoader *loader)
03341 {
03342   loader->refcount += 1;
03343 
03344   return loader;
03345 }
03346 
03353 void
03354 _dbus_message_loader_unref (DBusMessageLoader *loader)
03355 {
03356   loader->refcount -= 1;
03357   if (loader->refcount == 0)
03358     {
03359       _dbus_list_foreach (&loader->messages,
03360                           (DBusForeachFunction) dbus_message_unref,
03361                           NULL);
03362       _dbus_list_clear (&loader->messages);
03363       _dbus_string_free (&loader->data);
03364       dbus_free (loader);
03365     }
03366 }
03367 
03386 void
03387 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03388                                  DBusString        **buffer)
03389 {
03390   _dbus_assert (!loader->buffer_outstanding);
03391 
03392   *buffer = &loader->data;
03393 
03394   loader->buffer_outstanding = TRUE;
03395 }
03396 
03407 void
03408 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03409                                     DBusString         *buffer,
03410                                     int                 bytes_read)
03411 {
03412   _dbus_assert (loader->buffer_outstanding);
03413   _dbus_assert (buffer == &loader->data);
03414 
03415   loader->buffer_outstanding = FALSE;
03416 }
03417 
03418 /*
03419  * FIXME when we move the header out of the buffer, that memmoves all
03420  * buffered messages. Kind of crappy.
03421  *
03422  * Also we copy the header and body, which is kind of crappy.  To
03423  * avoid this, we have to allow header and body to be in a single
03424  * memory block, which is good for messages we read and bad for
03425  * messages we are creating. But we could move_len() the buffer into
03426  * this single memory block, and move_len() will just swap the buffers
03427  * if you're moving the entire buffer replacing the dest string.
03428  *
03429  * We could also have the message loader tell the transport how many
03430  * bytes to read; so it would first ask for some arbitrary number like
03431  * 256, then if the message was incomplete it would use the
03432  * header/body len to ask for exactly the size of the message (or
03433  * blocks the size of a typical kernel buffer for the socket). That
03434  * way we don't get trailing bytes in the buffer that have to be
03435  * memmoved. Though I suppose we also don't have a chance of reading a
03436  * bunch of small messages at once, so the optimization may be stupid.
03437  *
03438  * Another approach would be to keep a "start" index into
03439  * loader->data and only delete it occasionally, instead of after
03440  * each message is loaded.
03441  *
03442  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03443  */
03444 static dbus_bool_t
03445 load_message (DBusMessageLoader *loader,
03446               DBusMessage       *message,
03447               int                byte_order,
03448               int                fields_array_len,
03449               int                header_len,
03450               int                body_len)
03451 {
03452   dbus_bool_t oom;
03453   DBusValidity validity;
03454   const DBusString *type_str;
03455   int type_pos;
03456   DBusValidationMode mode;
03457 
03458   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03459   
03460   oom = FALSE;
03461 
03462 #if 0
03463   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03464 #endif
03465 
03466   /* 1. VALIDATE AND COPY OVER HEADER */
03467   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03468   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03469 
03470   if (!_dbus_header_load (&message->header,
03471                           mode,
03472                           &validity,
03473                           byte_order,
03474                           fields_array_len,
03475                           header_len,
03476                           body_len,
03477                           &loader->data, 0,
03478                           _dbus_string_get_length (&loader->data)))
03479     {
03480       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03481 
03482       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03483          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03484       _dbus_assert (validity != DBUS_VALID);
03485 
03486       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03487         oom = TRUE;
03488       else
03489         {
03490           loader->corrupted = TRUE;
03491           loader->corruption_reason = validity;
03492         }
03493       goto failed;
03494     }
03495 
03496   _dbus_assert (validity == DBUS_VALID);
03497 
03498   message->byte_order = byte_order;
03499 
03500   /* 2. VALIDATE BODY */
03501   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
03502     {
03503       get_const_signature (&message->header, &type_str, &type_pos);
03504       
03505       /* Because the bytes_remaining arg is NULL, this validates that the
03506        * body is the right length
03507        */
03508       validity = _dbus_validate_body_with_reason (type_str,
03509                                                   type_pos,
03510                                                   byte_order,
03511                                                   NULL,
03512                                                   &loader->data,
03513                                                   header_len,
03514                                                   body_len);
03515       if (validity != DBUS_VALID)
03516         {
03517           _dbus_verbose ("Failed to validate message body code %d\n", validity);
03518 
03519           loader->corrupted = TRUE;
03520           loader->corruption_reason = validity;
03521           
03522           goto failed;
03523         }
03524     }
03525 
03526   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
03527 
03528   if (!_dbus_list_append (&loader->messages, message))
03529     {
03530       _dbus_verbose ("Failed to append new message to loader queue\n");
03531       oom = TRUE;
03532       goto failed;
03533     }
03534 
03535   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
03536   _dbus_assert (_dbus_string_get_length (&loader->data) >=
03537                 (header_len + body_len));
03538 
03539   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
03540     {
03541       _dbus_verbose ("Failed to move body into new message\n");
03542       oom = TRUE;
03543       goto failed;
03544     }
03545 
03546   _dbus_string_delete (&loader->data, 0, header_len + body_len);
03547 
03548   /* don't waste more than 2k of memory */
03549   _dbus_string_compact (&loader->data, 2048);
03550 
03551   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
03552   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
03553 
03554   _dbus_verbose ("Loaded message %p\n", message);
03555 
03556   _dbus_assert (!oom);
03557   _dbus_assert (!loader->corrupted);
03558   _dbus_assert (loader->messages != NULL);
03559   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03560 
03561   return TRUE;
03562 
03563  failed:
03564 
03565   /* Clean up */
03566 
03567   /* does nothing if the message isn't in the list */
03568   _dbus_list_remove_last (&loader->messages, message);
03569   
03570   if (oom)
03571     _dbus_assert (!loader->corrupted);
03572   else
03573     _dbus_assert (loader->corrupted);
03574 
03575   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
03576 
03577   return FALSE;
03578 }
03579 
03594 dbus_bool_t
03595 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
03596 {
03597   while (!loader->corrupted &&
03598          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
03599     {
03600       DBusValidity validity;
03601       int byte_order, fields_array_len, header_len, body_len;
03602 
03603       if (_dbus_header_have_message_untrusted (loader->max_message_size,
03604                                                &validity,
03605                                                &byte_order,
03606                                                &fields_array_len,
03607                                                &header_len,
03608                                                &body_len,
03609                                                &loader->data, 0,
03610                                                _dbus_string_get_length (&loader->data)))
03611         {
03612           DBusMessage *message;
03613 
03614           _dbus_assert (validity == DBUS_VALID);
03615 
03616           message = dbus_message_new_empty_header ();
03617           if (message == NULL)
03618             return FALSE;
03619 
03620           if (!load_message (loader, message,
03621                              byte_order, fields_array_len,
03622                              header_len, body_len))
03623             {
03624               dbus_message_unref (message);
03625               /* load_message() returns false if corrupted or OOM; if
03626                * corrupted then return TRUE for not OOM
03627                */
03628               return loader->corrupted;
03629             }
03630 
03631           _dbus_assert (loader->messages != NULL);
03632           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03633         }
03634       else
03635         {
03636           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
03637                          validity);
03638           if (validity != DBUS_VALID)
03639             {
03640               loader->corrupted = TRUE;
03641               loader->corruption_reason = validity;
03642             }
03643           return TRUE;
03644         }
03645     }
03646 
03647   return TRUE;
03648 }
03649 
03657 DBusMessage*
03658 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
03659 {
03660   if (loader->messages)
03661     return loader->messages->data;
03662   else
03663     return NULL;
03664 }
03665 
03674 DBusMessage*
03675 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
03676 {
03677   return _dbus_list_pop_first (&loader->messages);
03678 }
03679 
03688 DBusList*
03689 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
03690 {
03691   return _dbus_list_pop_first_link (&loader->messages);
03692 }
03693 
03700 void
03701 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
03702                                            DBusList           *link)
03703 {
03704   _dbus_list_prepend_link (&loader->messages, link);
03705 }
03706 
03716 dbus_bool_t
03717 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
03718 {
03719   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
03720                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
03721   return loader->corrupted;
03722 }
03723 
03730 void
03731 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
03732                                            long                size)
03733 {
03734   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
03735     {
03736       _dbus_verbose ("clamping requested max message size %ld to %d\n",
03737                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
03738       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03739     }
03740   loader->max_message_size = size;
03741 }
03742 
03749 long
03750 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
03751 {
03752   return loader->max_message_size;
03753 }
03754 
03755 static DBusDataSlotAllocator slot_allocator;
03756 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
03757 
03772 dbus_bool_t
03773 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
03774 {
03775   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03776                                           &_DBUS_LOCK_NAME (message_slots),
03777                                           slot_p);
03778 }
03779 
03791 void
03792 dbus_message_free_data_slot (dbus_int32_t *slot_p)
03793 {
03794   _dbus_return_if_fail (*slot_p >= 0);
03795 
03796   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03797 }
03798 
03812 dbus_bool_t
03813 dbus_message_set_data (DBusMessage     *message,
03814                        dbus_int32_t     slot,
03815                        void            *data,
03816                        DBusFreeFunction free_data_func)
03817 {
03818   DBusFreeFunction old_free_func;
03819   void *old_data;
03820   dbus_bool_t retval;
03821 
03822   _dbus_return_val_if_fail (message != NULL, FALSE);
03823   _dbus_return_val_if_fail (slot >= 0, FALSE);
03824 
03825   retval = _dbus_data_slot_list_set (&slot_allocator,
03826                                      &message->slot_list,
03827                                      slot, data, free_data_func,
03828                                      &old_free_func, &old_data);
03829 
03830   if (retval)
03831     {
03832       /* Do the actual free outside the message lock */
03833       if (old_free_func)
03834         (* old_free_func) (old_data);
03835     }
03836 
03837   return retval;
03838 }
03839 
03848 void*
03849 dbus_message_get_data (DBusMessage   *message,
03850                        dbus_int32_t   slot)
03851 {
03852   void *res;
03853 
03854   _dbus_return_val_if_fail (message != NULL, NULL);
03855 
03856   res = _dbus_data_slot_list_get (&slot_allocator,
03857                                   &message->slot_list,
03858                                   slot);
03859 
03860   return res;
03861 }
03862 
03876 int
03877 dbus_message_type_from_string (const char *type_str)
03878 {
03879   if (strcmp (type_str, "method_call") == 0)
03880     return DBUS_MESSAGE_TYPE_METHOD_CALL;
03881   if (strcmp (type_str, "method_return") == 0)
03882     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
03883   else if (strcmp (type_str, "signal") == 0)
03884     return DBUS_MESSAGE_TYPE_SIGNAL;
03885   else if (strcmp (type_str, "error") == 0)
03886     return DBUS_MESSAGE_TYPE_ERROR;
03887   else
03888     return DBUS_MESSAGE_TYPE_INVALID;
03889 }
03890 
03904 const char *
03905 dbus_message_type_to_string (int type)
03906 {
03907   switch (type)
03908     {
03909     case DBUS_MESSAGE_TYPE_METHOD_CALL:
03910       return "method_call";
03911     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
03912       return "method_return";
03913     case DBUS_MESSAGE_TYPE_SIGNAL:
03914       return "signal";
03915     case DBUS_MESSAGE_TYPE_ERROR:
03916       return "error";
03917     default:
03918       return "invalid";
03919     }
03920 }
03921 
03934 dbus_bool_t
03935 dbus_message_marshal (DBusMessage  *msg,
03936                       char        **marshalled_data_p,
03937                       int          *len_p)
03938 {
03939   DBusString tmp;
03940 
03941   _dbus_return_val_if_fail (msg != NULL, FALSE);
03942   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
03943   _dbus_return_val_if_fail (len_p != NULL, FALSE);
03944 
03945   if (!_dbus_string_init (&tmp))
03946     return FALSE;
03947 
03948   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
03949     goto fail;
03950 
03951   *len_p = _dbus_string_get_length (&tmp);
03952 
03953   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
03954     goto fail;
03955 
03956   *len_p = _dbus_string_get_length (&tmp);
03957 
03958   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
03959     goto fail;
03960 
03961   _dbus_string_free (&tmp);
03962   return TRUE;
03963 
03964  fail:
03965   _dbus_string_free (&tmp);
03966   return FALSE;
03967 }
03968 
03981 DBusMessage *
03982 dbus_message_demarshal (const char *str,
03983                         int         len,
03984                         DBusError  *error)
03985 {
03986   DBusMessageLoader *loader;
03987   DBusString *buffer;
03988   DBusMessage *msg;
03989 
03990   _dbus_return_val_if_fail (str != NULL, NULL);
03991 
03992   loader = _dbus_message_loader_new ();
03993 
03994   if (loader == NULL)
03995     return NULL;
03996 
03997   _dbus_message_loader_get_buffer (loader, &buffer);
03998   _dbus_string_append_len (buffer, str, len);
03999   _dbus_message_loader_return_buffer (loader, buffer, len);
04000 
04001   if (!_dbus_message_loader_queue_messages (loader))
04002     goto fail_oom;
04003 
04004   if (_dbus_message_loader_get_is_corrupted (loader))
04005     goto fail_corrupt;
04006 
04007   msg = _dbus_message_loader_pop_message (loader);
04008 
04009   if (!msg)
04010     goto fail_oom;
04011 
04012   _dbus_message_loader_unref (loader);
04013   return msg;
04014 
04015  fail_corrupt:
04016   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted");
04017   _dbus_message_loader_unref (loader);
04018   return NULL;
04019 
04020  fail_oom:
04021   _DBUS_SET_OOM (error);
04022   _dbus_message_loader_unref (loader);
04023   return NULL;
04024 }
04025 
04028 /* tests in dbus-message-util.c */

Generated on Tue Feb 24 16:40:39 2009 for D-Bus by  doxygen 1.5.1