Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-marshal-recursive.h"
00027 #include "dbus-marshal-validate.h"
00028 #include "dbus-marshal-byteswap.h"
00029 #include "dbus-marshal-header.h"
00030 #include "dbus-signature.h"
00031 #include "dbus-message-private.h"
00032 #include "dbus-object-tree.h"
00033 #include "dbus-memory.h"
00034 #include "dbus-list.h"
00035 #include "dbus-threads-internal.h"
00036 #include <string.h>
00037 
00048 /* Not thread locked, but strictly const/read-only so should be OK
00049  */
00051 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
00052 
00053 /* these have wacky values to help trap uninitialized iterators;
00054  * but has to fit in 3 bits
00055  */
00056 enum {
00057   DBUS_MESSAGE_ITER_TYPE_READER = 3,
00058   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
00059 };
00060 
00062 typedef struct DBusMessageRealIter DBusMessageRealIter;
00063 
00069 struct DBusMessageRealIter
00070 {
00071   DBusMessage *message; 
00072   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 
00073   dbus_uint32_t iter_type : 3;      
00074   dbus_uint32_t sig_refcount : 8;   
00075   union
00076   {
00077     DBusTypeWriter writer; 
00078     DBusTypeReader reader; 
00079   } u; 
00080 };
00081 
00082 static void
00083 get_const_signature (DBusHeader        *header,
00084                      const DBusString **type_str_p,
00085                      int               *type_pos_p)
00086 {
00087   if (_dbus_header_get_field_raw (header,
00088                                   DBUS_HEADER_FIELD_SIGNATURE,
00089                                   type_str_p,
00090                                   type_pos_p))
00091     {
00092       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00093     }
00094   else
00095     {
00096       *type_str_p = &_dbus_empty_signature_str;
00097       *type_pos_p = 0;
00098     }
00099 }
00100 
00106 static void
00107 _dbus_message_byteswap (DBusMessage *message)
00108 {
00109   const DBusString *type_str;
00110   int type_pos;
00111   
00112   if (message->byte_order == DBUS_COMPILER_BYTE_ORDER)
00113     return;
00114 
00115   _dbus_verbose ("Swapping message into compiler byte order\n");
00116   
00117   get_const_signature (&message->header, &type_str, &type_pos);
00118   
00119   _dbus_marshal_byteswap (type_str, type_pos,
00120                           message->byte_order,
00121                           DBUS_COMPILER_BYTE_ORDER,
00122                           &message->body, 0);
00123 
00124   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00125   
00126   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00127 }
00128 
00129 #define ensure_byte_order(message)                      \
00130  if (message->byte_order != DBUS_COMPILER_BYTE_ORDER)   \
00131    _dbus_message_byteswap (message)
00132 
00143 void
00144 _dbus_message_get_network_data (DBusMessage          *message,
00145                                 const DBusString    **header,
00146                                 const DBusString    **body)
00147 {
00148   _dbus_assert (message->locked);
00149 
00150   *header = &message->header.data;
00151   *body = &message->body;
00152 }
00153 
00161 void
00162 _dbus_message_set_serial (DBusMessage   *message,
00163                           dbus_uint32_t  serial)
00164 {
00165   _dbus_assert (message != NULL);
00166   _dbus_assert (!message->locked);
00167   _dbus_assert (dbus_message_get_serial (message) == 0);
00168 
00169   _dbus_header_set_serial (&message->header, serial);
00170 }
00171 
00184 void
00185 _dbus_message_add_size_counter_link (DBusMessage  *message,
00186                                      DBusList     *link)
00187 {
00188   /* right now we don't recompute the delta when message
00189    * size changes, and that's OK for current purposes
00190    * I think, but could be important to change later.
00191    * Do recompute it whenever there are no outstanding counters,
00192    * since it's basically free.
00193    */
00194   if (message->size_counters == NULL)
00195     {
00196       message->size_counter_delta =
00197         _dbus_string_get_length (&message->header.data) +
00198         _dbus_string_get_length (&message->body);
00199 
00200 #if 0
00201       _dbus_verbose ("message has size %ld\n",
00202                      message->size_counter_delta);
00203 #endif
00204     }
00205 
00206   _dbus_list_append_link (&message->size_counters, link);
00207 
00208   _dbus_counter_adjust (link->data, message->size_counter_delta);
00209 }
00210 
00220 dbus_bool_t
00221 _dbus_message_add_size_counter (DBusMessage *message,
00222                                 DBusCounter *counter)
00223 {
00224   DBusList *link;
00225 
00226   link = _dbus_list_alloc_link (counter);
00227   if (link == NULL)
00228     return FALSE;
00229 
00230   _dbus_counter_ref (counter);
00231   _dbus_message_add_size_counter_link (message, link);
00232 
00233   return TRUE;
00234 }
00235 
00244 void
00245 _dbus_message_remove_size_counter (DBusMessage  *message,
00246                                    DBusCounter  *counter,
00247                                    DBusList    **link_return)
00248 {
00249   DBusList *link;
00250 
00251   link = _dbus_list_find_last (&message->size_counters,
00252                                counter);
00253   _dbus_assert (link != NULL);
00254 
00255   _dbus_list_unlink (&message->size_counters,
00256                      link);
00257   if (link_return)
00258     *link_return = link;
00259   else
00260     _dbus_list_free_link (link);
00261 
00262   _dbus_counter_adjust (counter, - message->size_counter_delta);
00263 
00264   _dbus_counter_unref (counter);
00265 }
00266 
00276 void
00277 _dbus_message_lock (DBusMessage  *message)
00278 {
00279   if (!message->locked)
00280     {
00281       _dbus_header_update_lengths (&message->header,
00282                                    _dbus_string_get_length (&message->body));
00283 
00284       /* must have a signature if you have a body */
00285       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00286                     dbus_message_get_signature (message) != NULL);
00287 
00288       message->locked = TRUE;
00289     }
00290 }
00291 
00292 static dbus_bool_t
00293 set_or_delete_string_field (DBusMessage *message,
00294                             int          field,
00295                             int          typecode,
00296                             const char  *value)
00297 {
00298   if (value == NULL)
00299     return _dbus_header_delete_field (&message->header, field);
00300   else
00301     return _dbus_header_set_field_basic (&message->header,
00302                                          field,
00303                                          typecode,
00304                                          &value);
00305 }
00306 
00307 #if 0
00308 /* Probably we don't need to use this */
00332 static dbus_bool_t
00333 _dbus_message_set_signature (DBusMessage *message,
00334                              const char  *signature)
00335 {
00336   _dbus_return_val_if_fail (message != NULL, FALSE);
00337   _dbus_return_val_if_fail (!message->locked, FALSE);
00338   _dbus_return_val_if_fail (signature == NULL ||
00339                             _dbus_check_is_valid_signature (signature));
00340   /* can't delete the signature if you have a message body */
00341   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00342                             signature != NULL);
00343 
00344   return set_or_delete_string_field (message,
00345                                      DBUS_HEADER_FIELD_SIGNATURE,
00346                                      DBUS_TYPE_SIGNATURE,
00347                                      signature);
00348 }
00349 #endif
00350 
00383 dbus_uint32_t
00384 dbus_message_get_serial (DBusMessage *message)
00385 {
00386   _dbus_return_val_if_fail (message != NULL, 0);
00387 
00388   return _dbus_header_get_serial (&message->header);
00389 }
00390 
00399 dbus_bool_t
00400 dbus_message_set_reply_serial (DBusMessage   *message,
00401                                dbus_uint32_t  reply_serial)
00402 {
00403   _dbus_return_val_if_fail (message != NULL, FALSE);
00404   _dbus_return_val_if_fail (!message->locked, FALSE);
00405   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
00406 
00407   return _dbus_header_set_field_basic (&message->header,
00408                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
00409                                        DBUS_TYPE_UINT32,
00410                                        &reply_serial);
00411 }
00412 
00419 dbus_uint32_t
00420 dbus_message_get_reply_serial  (DBusMessage *message)
00421 {
00422   dbus_uint32_t v_UINT32;
00423 
00424   _dbus_return_val_if_fail (message != NULL, 0);
00425 
00426   if (_dbus_header_get_field_basic (&message->header,
00427                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
00428                                     DBUS_TYPE_UINT32,
00429                                     &v_UINT32))
00430     return v_UINT32;
00431   else
00432     return 0;
00433 }
00434 
00435 static void
00436 free_size_counter (void *element,
00437                    void *data)
00438 {
00439   DBusCounter *counter = element;
00440   DBusMessage *message = data;
00441 
00442   _dbus_counter_adjust (counter, - message->size_counter_delta);
00443 
00444   _dbus_counter_unref (counter);
00445 }
00446 
00447 static void
00448 dbus_message_finalize (DBusMessage *message)
00449 {
00450   _dbus_assert (message->refcount.value == 0);
00451 
00452   /* This calls application callbacks! */
00453   _dbus_data_slot_list_free (&message->slot_list);
00454 
00455   _dbus_list_foreach (&message->size_counters,
00456                       free_size_counter, message);
00457   _dbus_list_clear (&message->size_counters);
00458 
00459   _dbus_header_free (&message->header);
00460   _dbus_string_free (&message->body);
00461 
00462   _dbus_assert (message->refcount.value == 0);
00463   
00464   dbus_free (message);
00465 }
00466 
00467 /* Message Cache
00468  *
00469  * We cache some DBusMessage to reduce the overhead of allocating
00470  * them.  In my profiling this consistently made about an 8%
00471  * difference.  It avoids the malloc for the message, the malloc for
00472  * the slot list, the malloc for the header string and body string,
00473  * and the associated free() calls. It does introduce another global
00474  * lock which could be a performance issue in certain cases.
00475  *
00476  * For the echo client/server the round trip time goes from around
00477  * .000077 to .000069 with the message cache on my laptop. The sysprof
00478  * change is as follows (numbers are cumulative percentage):
00479  *
00480  *  with message cache implemented as array as it is now (0.000069 per):
00481  *    new_empty_header           1.46
00482  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00483  *      mutex_unlock             0.25
00484  *      self                     0.41
00485  *    unref                      2.24
00486  *      self                     0.68
00487  *      list_clear               0.43
00488  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00489  *      mutex_unlock             0.25
00490  *
00491  *  with message cache implemented as list (0.000070 per roundtrip):
00492  *    new_empty_header           2.72
00493  *      list_pop_first           1.88
00494  *    unref                      3.3
00495  *      list_prepend             1.63
00496  *
00497  * without cache (0.000077 per roundtrip):
00498  *    new_empty_header           6.7
00499  *      string_init_preallocated 3.43
00500  *        dbus_malloc            2.43
00501  *      dbus_malloc0             2.59
00502  *
00503  *    unref                      4.02
00504  *      string_free              1.82
00505  *        dbus_free              1.63
00506  *      dbus_free                0.71
00507  *
00508  * If you implement the message_cache with a list, the primary reason
00509  * it's slower is that you add another thread lock (on the DBusList
00510  * mempool).
00511  */
00512 
00514 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00515 
00517 #define MAX_MESSAGE_CACHE_SIZE    5
00518 
00519 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00520 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00521 static int message_cache_count = 0;
00522 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00523 
00524 static void
00525 dbus_message_cache_shutdown (void *data)
00526 {
00527   int i;
00528 
00529   _DBUS_LOCK (message_cache);
00530 
00531   i = 0;
00532   while (i < MAX_MESSAGE_CACHE_SIZE)
00533     {
00534       if (message_cache[i])
00535         dbus_message_finalize (message_cache[i]);
00536 
00537       ++i;
00538     }
00539 
00540   message_cache_count = 0;
00541   message_cache_shutdown_registered = FALSE;
00542 
00543   _DBUS_UNLOCK (message_cache);
00544 }
00545 
00553 static DBusMessage*
00554 dbus_message_get_cached (void)
00555 {
00556   DBusMessage *message;
00557   int i;
00558 
00559   message = NULL;
00560 
00561   _DBUS_LOCK (message_cache);
00562 
00563   _dbus_assert (message_cache_count >= 0);
00564 
00565   if (message_cache_count == 0)
00566     {
00567       _DBUS_UNLOCK (message_cache);
00568       return NULL;
00569     }
00570 
00571   /* This is not necessarily true unless count > 0, and
00572    * message_cache is uninitialized until the shutdown is
00573    * registered
00574    */
00575   _dbus_assert (message_cache_shutdown_registered);
00576 
00577   i = 0;
00578   while (i < MAX_MESSAGE_CACHE_SIZE)
00579     {
00580       if (message_cache[i])
00581         {
00582           message = message_cache[i];
00583           message_cache[i] = NULL;
00584           message_cache_count -= 1;
00585           break;
00586         }
00587       ++i;
00588     }
00589   _dbus_assert (message_cache_count >= 0);
00590   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00591   _dbus_assert (message != NULL);
00592 
00593   _DBUS_UNLOCK (message_cache);
00594 
00595   _dbus_assert (message->refcount.value == 0);
00596   _dbus_assert (message->size_counters == NULL);
00597 
00598   return message;
00599 }
00600 
00606 static void
00607 dbus_message_cache_or_finalize (DBusMessage *message)
00608 {
00609   dbus_bool_t was_cached;
00610   int i;
00611   
00612   _dbus_assert (message->refcount.value == 0);
00613 
00614   /* This calls application code and has to be done first thing
00615    * without holding the lock
00616    */
00617   _dbus_data_slot_list_clear (&message->slot_list);
00618 
00619   _dbus_list_foreach (&message->size_counters,
00620                       free_size_counter, message);
00621   _dbus_list_clear (&message->size_counters);
00622 
00623   was_cached = FALSE;
00624 
00625   _DBUS_LOCK (message_cache);
00626 
00627   if (!message_cache_shutdown_registered)
00628     {
00629       _dbus_assert (message_cache_count == 0);
00630 
00631       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00632         goto out;
00633 
00634       i = 0;
00635       while (i < MAX_MESSAGE_CACHE_SIZE)
00636         {
00637           message_cache[i] = NULL;
00638           ++i;
00639         }
00640 
00641       message_cache_shutdown_registered = TRUE;
00642     }
00643 
00644   _dbus_assert (message_cache_count >= 0);
00645 
00646   if ((_dbus_string_get_length (&message->header.data) +
00647        _dbus_string_get_length (&message->body)) >
00648       MAX_MESSAGE_SIZE_TO_CACHE)
00649     goto out;
00650 
00651   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00652     goto out;
00653 
00654   /* Find empty slot */
00655   i = 0;
00656   while (message_cache[i] != NULL)
00657     ++i;
00658 
00659   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00660 
00661   _dbus_assert (message_cache[i] == NULL);
00662   message_cache[i] = message;
00663   message_cache_count += 1;
00664   was_cached = TRUE;
00665 #ifndef DBUS_DISABLE_CHECKS
00666   message->in_cache = TRUE;
00667 #endif
00668 
00669  out:
00670   _DBUS_UNLOCK (message_cache);
00671 
00672   _dbus_assert (message->refcount.value == 0);
00673   
00674   if (!was_cached)
00675     dbus_message_finalize (message);
00676 }
00677 
00678 static DBusMessage*
00679 dbus_message_new_empty_header (void)
00680 {
00681   DBusMessage *message;
00682   dbus_bool_t from_cache;
00683 
00684   message = dbus_message_get_cached ();
00685 
00686   if (message != NULL)
00687     {
00688       from_cache = TRUE;
00689     }
00690   else
00691     {
00692       from_cache = FALSE;
00693       message = dbus_new (DBusMessage, 1);
00694       if (message == NULL)
00695         return NULL;
00696 #ifndef DBUS_DISABLE_CHECKS
00697       message->generation = _dbus_current_generation;
00698 #endif
00699     }
00700   
00701   message->refcount.value = 1;
00702   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00703   message->locked = FALSE;
00704 #ifndef DBUS_DISABLE_CHECKS
00705   message->in_cache = FALSE;
00706 #endif
00707   message->size_counters = NULL;
00708   message->size_counter_delta = 0;
00709   message->changed_stamp = 0;
00710 
00711   if (!from_cache)
00712     _dbus_data_slot_list_init (&message->slot_list);
00713 
00714   if (from_cache)
00715     {
00716       _dbus_header_reinit (&message->header, message->byte_order);
00717       _dbus_string_set_length (&message->body, 0);
00718     }
00719   else
00720     {
00721       if (!_dbus_header_init (&message->header, message->byte_order))
00722         {
00723           dbus_free (message);
00724           return NULL;
00725         }
00726 
00727       if (!_dbus_string_init_preallocated (&message->body, 32))
00728         {
00729           _dbus_header_free (&message->header);
00730           dbus_free (message);
00731           return NULL;
00732         }
00733     }
00734 
00735   return message;
00736 }
00737 
00746 DBusMessage*
00747 dbus_message_new (int message_type)
00748 {
00749   DBusMessage *message;
00750 
00751   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
00752 
00753   message = dbus_message_new_empty_header ();
00754   if (message == NULL)
00755     return NULL;
00756 
00757   if (!_dbus_header_create (&message->header,
00758                             message_type,
00759                             NULL, NULL, NULL, NULL, NULL))
00760     {
00761       dbus_message_unref (message);
00762       return NULL;
00763     }
00764 
00765   return message;
00766 }
00767 
00785 DBusMessage*
00786 dbus_message_new_method_call (const char *destination,
00787                               const char *path,
00788                               const char *interface,
00789                               const char *method)
00790 {
00791   DBusMessage *message;
00792 
00793   _dbus_return_val_if_fail (path != NULL, NULL);
00794   _dbus_return_val_if_fail (method != NULL, NULL);
00795   _dbus_return_val_if_fail (destination == NULL ||
00796                             _dbus_check_is_valid_bus_name (destination), NULL);
00797   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
00798   _dbus_return_val_if_fail (interface == NULL ||
00799                             _dbus_check_is_valid_interface (interface), NULL);
00800   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
00801 
00802   message = dbus_message_new_empty_header ();
00803   if (message == NULL)
00804     return NULL;
00805 
00806   if (!_dbus_header_create (&message->header,
00807                             DBUS_MESSAGE_TYPE_METHOD_CALL,
00808                             destination, path, interface, method, NULL))
00809     {
00810       dbus_message_unref (message);
00811       return NULL;
00812     }
00813 
00814   return message;
00815 }
00816 
00826 DBusMessage*
00827 dbus_message_new_method_return (DBusMessage *method_call)
00828 {
00829   DBusMessage *message;
00830   const char *sender;
00831 
00832   _dbus_return_val_if_fail (method_call != NULL, NULL);
00833 
00834   sender = dbus_message_get_sender (method_call);
00835 
00836   /* sender is allowed to be null here in peer-to-peer case */
00837 
00838   message = dbus_message_new_empty_header ();
00839   if (message == NULL)
00840     return NULL;
00841 
00842   if (!_dbus_header_create (&message->header,
00843                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
00844                             sender, NULL, NULL, NULL, NULL))
00845     {
00846       dbus_message_unref (message);
00847       return NULL;
00848     }
00849 
00850   dbus_message_set_no_reply (message, TRUE);
00851 
00852   if (!dbus_message_set_reply_serial (message,
00853                                       dbus_message_get_serial (method_call)))
00854     {
00855       dbus_message_unref (message);
00856       return NULL;
00857     }
00858 
00859   return message;
00860 }
00861 
00874 DBusMessage*
00875 dbus_message_new_signal (const char *path,
00876                          const char *interface,
00877                          const char *name)
00878 {
00879   DBusMessage *message;
00880 
00881   _dbus_return_val_if_fail (path != NULL, NULL);
00882   _dbus_return_val_if_fail (interface != NULL, NULL);
00883   _dbus_return_val_if_fail (name != NULL, NULL);
00884   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
00885   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
00886   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
00887 
00888   message = dbus_message_new_empty_header ();
00889   if (message == NULL)
00890     return NULL;
00891 
00892   if (!_dbus_header_create (&message->header,
00893                             DBUS_MESSAGE_TYPE_SIGNAL,
00894                             NULL, path, interface, name, NULL))
00895     {
00896       dbus_message_unref (message);
00897       return NULL;
00898     }
00899 
00900   dbus_message_set_no_reply (message, TRUE);
00901 
00902   return message;
00903 }
00904 
00914 DBusMessage*
00915 dbus_message_new_error (DBusMessage *reply_to,
00916                         const char  *error_name,
00917                         const char  *error_message)
00918 {
00919   DBusMessage *message;
00920   const char *sender;
00921   DBusMessageIter iter;
00922 
00923   _dbus_return_val_if_fail (reply_to != NULL, NULL);
00924   _dbus_return_val_if_fail (error_name != NULL, NULL);
00925   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
00926 
00927   sender = dbus_message_get_sender (reply_to);
00928 
00929   /* sender may be NULL for non-message-bus case or
00930    * when the message bus is dealing with an unregistered
00931    * connection.
00932    */
00933   message = dbus_message_new_empty_header ();
00934   if (message == NULL)
00935     return NULL;
00936 
00937   if (!_dbus_header_create (&message->header,
00938                             DBUS_MESSAGE_TYPE_ERROR,
00939                             sender, NULL, NULL, NULL, error_name))
00940     {
00941       dbus_message_unref (message);
00942       return NULL;
00943     }
00944 
00945   dbus_message_set_no_reply (message, TRUE);
00946 
00947   if (!dbus_message_set_reply_serial (message,
00948                                       dbus_message_get_serial (reply_to)))
00949     {
00950       dbus_message_unref (message);
00951       return NULL;
00952     }
00953 
00954   if (error_message != NULL)
00955     {
00956       dbus_message_iter_init_append (message, &iter);
00957       if (!dbus_message_iter_append_basic (&iter,
00958                                            DBUS_TYPE_STRING,
00959                                            &error_message))
00960         {
00961           dbus_message_unref (message);
00962           return NULL;
00963         }
00964     }
00965 
00966   return message;
00967 }
00968 
00979 DBusMessage*
00980 dbus_message_new_error_printf (DBusMessage *reply_to,
00981                                const char  *error_name,
00982                                const char  *error_format,
00983                                ...)
00984 {
00985   va_list args;
00986   DBusString str;
00987   DBusMessage *message;
00988 
00989   _dbus_return_val_if_fail (reply_to != NULL, NULL);
00990   _dbus_return_val_if_fail (error_name != NULL, NULL);
00991   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
00992 
00993   if (!_dbus_string_init (&str))
00994     return NULL;
00995 
00996   va_start (args, error_format);
00997 
00998   if (_dbus_string_append_printf_valist (&str, error_format, args))
00999     message = dbus_message_new_error (reply_to, error_name,
01000                                       _dbus_string_get_const_data (&str));
01001   else
01002     message = NULL;
01003 
01004   _dbus_string_free (&str);
01005 
01006   va_end (args);
01007 
01008   return message;
01009 }
01010 
01011 
01022 DBusMessage *
01023 dbus_message_copy (const DBusMessage *message)
01024 {
01025   DBusMessage *retval;
01026 
01027   _dbus_return_val_if_fail (message != NULL, NULL);
01028 
01029   retval = dbus_new0 (DBusMessage, 1);
01030   if (retval == NULL)
01031     return NULL;
01032 
01033   retval->refcount.value = 1;
01034   retval->byte_order = message->byte_order;
01035   retval->locked = FALSE;
01036 #ifndef DBUS_DISABLE_CHECKS
01037   retval->generation = message->generation;
01038 #endif
01039 
01040   if (!_dbus_header_copy (&message->header, &retval->header))
01041     {
01042       dbus_free (retval);
01043       return NULL;
01044     }
01045 
01046   if (!_dbus_string_init_preallocated (&retval->body,
01047                                        _dbus_string_get_length (&message->body)))
01048     {
01049       _dbus_header_free (&retval->header);
01050       dbus_free (retval);
01051       return NULL;
01052     }
01053 
01054   if (!_dbus_string_copy (&message->body, 0,
01055                           &retval->body, 0))
01056     goto failed_copy;
01057 
01058   return retval;
01059 
01060  failed_copy:
01061   _dbus_header_free (&retval->header);
01062   _dbus_string_free (&retval->body);
01063   dbus_free (retval);
01064 
01065   return NULL;
01066 }
01067 
01068 
01076 DBusMessage *
01077 dbus_message_ref (DBusMessage *message)
01078 {
01079   dbus_int32_t old_refcount;
01080 
01081   _dbus_return_val_if_fail (message != NULL, NULL);
01082   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01083   _dbus_return_val_if_fail (!message->in_cache, NULL);
01084   
01085   old_refcount = _dbus_atomic_inc (&message->refcount);
01086   _dbus_assert (old_refcount >= 1);
01087 
01088   return message;
01089 }
01090 
01097 void
01098 dbus_message_unref (DBusMessage *message)
01099 {
01100  dbus_int32_t old_refcount;
01101 
01102   _dbus_return_if_fail (message != NULL);
01103   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01104   _dbus_return_if_fail (!message->in_cache);
01105 
01106   old_refcount = _dbus_atomic_dec (&message->refcount);
01107 
01108   _dbus_assert (old_refcount >= 0);
01109 
01110   if (old_refcount == 1)
01111     {
01112       /* Calls application callbacks! */
01113       dbus_message_cache_or_finalize (message);
01114     }
01115 }
01116 
01129 int
01130 dbus_message_get_type (DBusMessage *message)
01131 {
01132   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01133 
01134   return _dbus_header_get_message_type (&message->header);
01135 }
01136 
01189 dbus_bool_t
01190 dbus_message_append_args (DBusMessage *message,
01191                           int          first_arg_type,
01192                           ...)
01193 {
01194   dbus_bool_t retval;
01195   va_list var_args;
01196 
01197   _dbus_return_val_if_fail (message != NULL, FALSE);
01198 
01199   va_start (var_args, first_arg_type);
01200   retval = dbus_message_append_args_valist (message,
01201                                             first_arg_type,
01202                                             var_args);
01203   va_end (var_args);
01204 
01205   return retval;
01206 }
01207 
01222 dbus_bool_t
01223 dbus_message_append_args_valist (DBusMessage *message,
01224                                  int          first_arg_type,
01225                                  va_list      var_args)
01226 {
01227   int type;
01228   DBusMessageIter iter;
01229 
01230   _dbus_return_val_if_fail (message != NULL, FALSE);
01231 
01232   type = first_arg_type;
01233 
01234   dbus_message_iter_init_append (message, &iter);
01235 
01236   while (type != DBUS_TYPE_INVALID)
01237     {
01238       if (dbus_type_is_basic (type))
01239         {
01240           const DBusBasicValue *value;
01241           value = va_arg (var_args, const DBusBasicValue*);
01242 
01243           if (!dbus_message_iter_append_basic (&iter,
01244                                                type,
01245                                                value))
01246             goto failed;
01247         }
01248       else if (type == DBUS_TYPE_ARRAY)
01249         {
01250           int element_type;
01251           DBusMessageIter array;
01252           char buf[2];
01253 
01254           element_type = va_arg (var_args, int);
01255               
01256           buf[0] = element_type;
01257           buf[1] = '\0';
01258           if (!dbus_message_iter_open_container (&iter,
01259                                                  DBUS_TYPE_ARRAY,
01260                                                  buf,
01261                                                  &array))
01262             goto failed;
01263           
01264           if (dbus_type_is_fixed (element_type))
01265             {
01266               const DBusBasicValue **value;
01267               int n_elements;
01268 
01269               value = va_arg (var_args, const DBusBasicValue**);
01270               n_elements = va_arg (var_args, int);
01271               
01272               if (!dbus_message_iter_append_fixed_array (&array,
01273                                                          element_type,
01274                                                          value,
01275                                                          n_elements))
01276                 goto failed;
01277             }
01278           else if (element_type == DBUS_TYPE_STRING ||
01279                    element_type == DBUS_TYPE_SIGNATURE ||
01280                    element_type == DBUS_TYPE_OBJECT_PATH)
01281             {
01282               const char ***value_p;
01283               const char **value;
01284               int n_elements;
01285               int i;
01286               
01287               value_p = va_arg (var_args, const char***);
01288               n_elements = va_arg (var_args, int);
01289 
01290               value = *value_p;
01291               
01292               i = 0;
01293               while (i < n_elements)
01294                 {
01295                   if (!dbus_message_iter_append_basic (&array,
01296                                                        element_type,
01297                                                        &value[i]))
01298                     goto failed;
01299                   ++i;
01300                 }
01301             }
01302           else
01303             {
01304               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01305                           _dbus_type_to_string (element_type),
01306                           _DBUS_FUNCTION_NAME);
01307               goto failed;
01308             }
01309 
01310           if (!dbus_message_iter_close_container (&iter, &array))
01311             goto failed;
01312         }
01313 #ifndef DBUS_DISABLE_CHECKS
01314       else
01315         {
01316           _dbus_warn ("type %s isn't supported yet in %s\n",
01317                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01318           goto failed;
01319         }
01320 #endif
01321 
01322       type = va_arg (var_args, int);
01323     }
01324 
01325   return TRUE;
01326 
01327  failed:
01328   return FALSE;
01329 }
01330 
01363 dbus_bool_t
01364 dbus_message_get_args (DBusMessage     *message,
01365                        DBusError       *error,
01366                        int              first_arg_type,
01367                        ...)
01368 {
01369   dbus_bool_t retval;
01370   va_list var_args;
01371 
01372   _dbus_return_val_if_fail (message != NULL, FALSE);
01373   _dbus_return_val_if_error_is_set (error, FALSE);
01374 
01375   va_start (var_args, first_arg_type);
01376   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01377   va_end (var_args);
01378 
01379   return retval;
01380 }
01381 
01393 dbus_bool_t
01394 dbus_message_get_args_valist (DBusMessage     *message,
01395                               DBusError       *error,
01396                               int              first_arg_type,
01397                               va_list          var_args)
01398 {
01399   DBusMessageIter iter;
01400 
01401   _dbus_return_val_if_fail (message != NULL, FALSE);
01402   _dbus_return_val_if_error_is_set (error, FALSE);
01403 
01404   dbus_message_iter_init (message, &iter);
01405   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01406 }
01407 
01408 static void
01409 _dbus_message_iter_init_common (DBusMessage         *message,
01410                                 DBusMessageRealIter *real,
01411                                 int                  iter_type)
01412 {
01413   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01414 
01415   /* Since the iterator will read or write who-knows-what from the
01416    * message, we need to get in the right byte order
01417    */
01418   ensure_byte_order (message);
01419   
01420   real->message = message;
01421   real->changed_stamp = message->changed_stamp;
01422   real->iter_type = iter_type;
01423   real->sig_refcount = 0;
01424 }
01425 
01434 dbus_bool_t
01435 dbus_message_iter_init (DBusMessage     *message,
01436                         DBusMessageIter *iter)
01437 {
01438   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01439   const DBusString *type_str;
01440   int type_pos;
01441 
01442   _dbus_return_val_if_fail (message != NULL, FALSE);
01443   _dbus_return_val_if_fail (iter != NULL, FALSE);
01444 
01445   get_const_signature (&message->header, &type_str, &type_pos);
01446 
01447   _dbus_message_iter_init_common (message, real,
01448                                   DBUS_MESSAGE_ITER_TYPE_READER);
01449 
01450   _dbus_type_reader_init (&real->u.reader,
01451                           message->byte_order,
01452                           type_str, type_pos,
01453                           &message->body,
01454                           0);
01455 
01456   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
01457 }
01458 
01459 #ifndef DBUS_DISABLE_CHECKS
01460 static dbus_bool_t
01461 _dbus_message_iter_check (DBusMessageRealIter *iter)
01462 {
01463   if (iter == NULL)
01464     {
01465       _dbus_warn ("dbus message iterator is NULL\n");
01466       return FALSE;
01467     }
01468 
01469   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
01470     {
01471       if (iter->u.reader.byte_order != iter->message->byte_order)
01472         {
01473           _dbus_warn ("dbus message changed byte order since iterator was created\n");
01474           return FALSE;
01475         }
01476       /* because we swap the message into compiler order when you init an iter */
01477       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
01478     }
01479   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
01480     {
01481       if (iter->u.writer.byte_order != iter->message->byte_order)
01482         {
01483           _dbus_warn ("dbus message changed byte order since append iterator was created\n");
01484           return FALSE;
01485         }
01486       /* because we swap the message into compiler order when you init an iter */
01487       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
01488     }
01489   else
01490     {
01491       _dbus_warn ("dbus message iterator looks uninitialized or corrupted\n");
01492       return FALSE;
01493     }
01494 
01495   if (iter->changed_stamp != iter->message->changed_stamp)
01496     {
01497       _dbus_warn ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
01498       return FALSE;
01499     }
01500 
01501   return TRUE;
01502 }
01503 #endif /* DBUS_DISABLE_CHECKS */
01504 
01512 dbus_bool_t
01513 dbus_message_iter_has_next (DBusMessageIter *iter)
01514 {
01515   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01516 
01517   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01518   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01519 
01520   return _dbus_type_reader_has_next (&real->u.reader);
01521 }
01522 
01531 dbus_bool_t
01532 dbus_message_iter_next (DBusMessageIter *iter)
01533 {
01534   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01535 
01536   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01537   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01538 
01539   return _dbus_type_reader_next (&real->u.reader);
01540 }
01541 
01556 int
01557 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
01558 {
01559   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01560 
01561   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01562   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01563 
01564   return _dbus_type_reader_get_current_type (&real->u.reader);
01565 }
01566 
01575 int
01576 dbus_message_iter_get_element_type (DBusMessageIter *iter)
01577 {
01578   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01579 
01580   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01581   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
01582   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
01583 
01584   return _dbus_type_reader_get_element_type (&real->u.reader);
01585 }
01586 
01602 void
01603 dbus_message_iter_recurse (DBusMessageIter  *iter,
01604                            DBusMessageIter  *sub)
01605 {
01606   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01607   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
01608 
01609   _dbus_return_if_fail (_dbus_message_iter_check (real));
01610   _dbus_return_if_fail (sub != NULL);
01611 
01612   *real_sub = *real;
01613   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
01614 }
01615 
01625 char *
01626 dbus_message_iter_get_signature (DBusMessageIter *iter)
01627 {
01628   const DBusString *sig;
01629   DBusString retstr;
01630   char *ret;
01631   int start, len;
01632   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01633 
01634   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
01635 
01636   if (!_dbus_string_init (&retstr))
01637     return NULL;
01638 
01639   _dbus_type_reader_get_signature (&real->u.reader, &sig,
01640                                    &start, &len);
01641   if (!_dbus_string_append_len (&retstr,
01642                                 _dbus_string_get_const_data (sig) + start,
01643                                 len))
01644     return NULL;
01645   if (!_dbus_string_steal_data (&retstr, &ret))
01646     return NULL;
01647   _dbus_string_free (&retstr);
01648   return ret;
01649 }
01650 
01686 void
01687 dbus_message_iter_get_basic (DBusMessageIter  *iter,
01688                              void             *value)
01689 {
01690   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01691 
01692   _dbus_return_if_fail (_dbus_message_iter_check (real));
01693   _dbus_return_if_fail (value != NULL);
01694 
01695   _dbus_type_reader_read_basic (&real->u.reader,
01696                                 value);
01697 }
01698 
01705 int
01706 dbus_message_iter_get_array_len (DBusMessageIter *iter)
01707 {
01708   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01709 
01710   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
01711 
01712   return _dbus_type_reader_get_array_length (&real->u.reader);
01713 }
01714 
01732 void
01733 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
01734                                    void             *value,
01735                                    int              *n_elements)
01736 {
01737   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01738 
01739   _dbus_return_if_fail (_dbus_message_iter_check (real));
01740   _dbus_return_if_fail (value != NULL);
01741   _dbus_return_if_fail (dbus_type_is_fixed (_dbus_type_reader_get_current_type (&real->u.reader)));
01742 
01743   _dbus_type_reader_read_fixed_multi (&real->u.reader,
01744                                       value, n_elements);
01745 }
01746 
01760 dbus_bool_t
01761 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
01762                                     DBusError       *error,
01763                                     int              first_arg_type,
01764                                     va_list          var_args)
01765 {
01766   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01767   int spec_type, msg_type, i;
01768   dbus_bool_t retval;
01769 
01770   _dbus_assert (_dbus_message_iter_check (real));
01771 
01772   retval = FALSE;
01773 
01774   spec_type = first_arg_type;
01775   i = 0;
01776 
01777   while (spec_type != DBUS_TYPE_INVALID)
01778     {
01779       msg_type = dbus_message_iter_get_arg_type (iter);
01780 
01781       if (msg_type != spec_type)
01782         {
01783           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01784                           "Argument %d is specified to be of type \"%s\", but "
01785                           "is actually of type \"%s\"\n", i,
01786                           _dbus_type_to_string (spec_type),
01787                           _dbus_type_to_string (msg_type));
01788 
01789           goto out;
01790         }
01791 
01792       if (dbus_type_is_basic (spec_type))
01793         {
01794           DBusBasicValue *ptr;
01795 
01796           ptr = va_arg (var_args, DBusBasicValue*);
01797 
01798           _dbus_assert (ptr != NULL);
01799 
01800           _dbus_type_reader_read_basic (&real->u.reader,
01801                                         ptr);
01802         }
01803       else if (spec_type == DBUS_TYPE_ARRAY)
01804         {
01805           int element_type;
01806           int spec_element_type;
01807           const DBusBasicValue **ptr;
01808           int *n_elements_p;
01809           DBusTypeReader array;
01810 
01811           spec_element_type = va_arg (var_args, int);
01812           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
01813 
01814           if (spec_element_type != element_type)
01815             {
01816               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01817                               "Argument %d is specified to be an array of \"%s\", but "
01818                               "is actually an array of \"%s\"\n",
01819                               i,
01820                               _dbus_type_to_string (spec_element_type),
01821                               _dbus_type_to_string (element_type));
01822 
01823               goto out;
01824             }
01825 
01826           if (dbus_type_is_fixed (spec_element_type))
01827             {
01828               ptr = va_arg (var_args, const DBusBasicValue**);
01829               n_elements_p = va_arg (var_args, int*);
01830 
01831               _dbus_assert (ptr != NULL);
01832               _dbus_assert (n_elements_p != NULL);
01833 
01834               _dbus_type_reader_recurse (&real->u.reader, &array);
01835 
01836               _dbus_type_reader_read_fixed_multi (&array,
01837                                                   ptr, n_elements_p);
01838             }
01839           else if (spec_element_type == DBUS_TYPE_STRING ||
01840                    spec_element_type == DBUS_TYPE_SIGNATURE ||
01841                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
01842             {
01843               char ***str_array_p;
01844               int n_elements;
01845               char **str_array;
01846 
01847               str_array_p = va_arg (var_args, char***);
01848               n_elements_p = va_arg (var_args, int*);
01849 
01850               _dbus_assert (str_array_p != NULL);
01851               _dbus_assert (n_elements_p != NULL);
01852 
01853               /* Count elements in the array */
01854               _dbus_type_reader_recurse (&real->u.reader, &array);
01855 
01856               n_elements = 0;
01857               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
01858                 {
01859                   ++n_elements;
01860                   _dbus_type_reader_next (&array);
01861                 }
01862 
01863               str_array = dbus_new0 (char*, n_elements + 1);
01864               if (str_array == NULL)
01865                 {
01866                   _DBUS_SET_OOM (error);
01867                   goto out;
01868                 }
01869 
01870               /* Now go through and dup each string */
01871               _dbus_type_reader_recurse (&real->u.reader, &array);
01872 
01873               i = 0;
01874               while (i < n_elements)
01875                 {
01876                   const char *s;
01877                   _dbus_type_reader_read_basic (&array,
01878                                                 &s);
01879                   
01880                   str_array[i] = _dbus_strdup (s);
01881                   if (str_array[i] == NULL)
01882                     {
01883                       dbus_free_string_array (str_array);
01884                       _DBUS_SET_OOM (error);
01885                       goto out;
01886                     }
01887                   
01888                   ++i;
01889                   
01890                   if (!_dbus_type_reader_next (&array))
01891                     _dbus_assert (i == n_elements);
01892                 }
01893 
01894               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
01895               _dbus_assert (i == n_elements);
01896               _dbus_assert (str_array[i] == NULL);
01897 
01898               *str_array_p = str_array;
01899               *n_elements_p = n_elements;
01900             }
01901 #ifndef DBUS_DISABLE_CHECKS
01902           else
01903             {
01904               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
01905                           _DBUS_FUNCTION_NAME);
01906               goto out;
01907             }
01908 #endif
01909         }
01910 #ifndef DBUS_DISABLE_CHECKS
01911       else
01912         {
01913           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
01914                       _DBUS_FUNCTION_NAME);
01915           goto out;
01916         }
01917 #endif
01918 
01919       spec_type = va_arg (var_args, int);
01920       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
01921         {
01922           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01923                           "Message has only %d arguments, but more were expected", i);
01924           goto out;
01925         }
01926 
01927       i++;
01928     }
01929 
01930   retval = TRUE;
01931 
01932  out:
01933 
01934   return retval;
01935 }
01936 
01948 void
01949 dbus_message_iter_init_append (DBusMessage     *message,
01950                                DBusMessageIter *iter)
01951 {
01952   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01953 
01954   _dbus_return_if_fail (message != NULL);
01955   _dbus_return_if_fail (iter != NULL);
01956 
01957   _dbus_message_iter_init_common (message, real,
01958                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
01959 
01960   /* We create the signature string and point iterators at it "on demand"
01961    * when a value is actually appended. That means that init() never fails
01962    * due to OOM.
01963    */
01964   _dbus_type_writer_init_types_delayed (&real->u.writer,
01965                                         message->byte_order,
01966                                         &message->body,
01967                                         _dbus_string_get_length (&message->body));
01968 }
01969 
01978 static dbus_bool_t
01979 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
01980 {
01981   DBusString *str;
01982   const DBusString *current_sig;
01983   int current_sig_pos;
01984 
01985   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
01986 
01987   if (real->u.writer.type_str != NULL)
01988     {
01989       _dbus_assert (real->sig_refcount > 0);
01990       real->sig_refcount += 1;
01991       return TRUE;
01992     }
01993 
01994   str = dbus_new (DBusString, 1);
01995   if (str == NULL)
01996     return FALSE;
01997 
01998   if (!_dbus_header_get_field_raw (&real->message->header,
01999                                    DBUS_HEADER_FIELD_SIGNATURE,
02000                                    &current_sig, &current_sig_pos))
02001     current_sig = NULL;
02002 
02003   if (current_sig)
02004     {
02005       int current_len;
02006 
02007       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02008       current_sig_pos += 1; /* move on to sig data */
02009 
02010       if (!_dbus_string_init_preallocated (str, current_len + 4))
02011         {
02012           dbus_free (str);
02013           return FALSE;
02014         }
02015 
02016       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02017                                   str, 0))
02018         {
02019           _dbus_string_free (str);
02020           dbus_free (str);
02021           return FALSE;
02022         }
02023     }
02024   else
02025     {
02026       if (!_dbus_string_init_preallocated (str, 4))
02027         {
02028           dbus_free (str);
02029           return FALSE;
02030         }
02031     }
02032 
02033   real->sig_refcount = 1;
02034 
02035   _dbus_type_writer_add_types (&real->u.writer,
02036                                str, _dbus_string_get_length (str));
02037   return TRUE;
02038 }
02039 
02049 static dbus_bool_t
02050 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02051 {
02052   DBusString *str;
02053   const char *v_STRING;
02054   dbus_bool_t retval;
02055 
02056   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02057   _dbus_assert (real->u.writer.type_str != NULL);
02058   _dbus_assert (real->sig_refcount > 0);
02059 
02060   real->sig_refcount -= 1;
02061 
02062   if (real->sig_refcount > 0)
02063     return TRUE;
02064   _dbus_assert (real->sig_refcount == 0);
02065 
02066   retval = TRUE;
02067 
02068   str = real->u.writer.type_str;
02069 
02070   v_STRING = _dbus_string_get_const_data (str);
02071   if (!_dbus_header_set_field_basic (&real->message->header,
02072                                      DBUS_HEADER_FIELD_SIGNATURE,
02073                                      DBUS_TYPE_SIGNATURE,
02074                                      &v_STRING))
02075     retval = FALSE;
02076 
02077   _dbus_type_writer_remove_types (&real->u.writer);
02078   _dbus_string_free (str);
02079   dbus_free (str);
02080 
02081   return retval;
02082 }
02083 
02084 #ifndef DBUS_DISABLE_CHECKS
02085 static dbus_bool_t
02086 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02087 {
02088   if (!_dbus_message_iter_check (iter))
02089     return FALSE;
02090 
02091   if (iter->message->locked)
02092     {
02093       _dbus_warn ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02094       return FALSE;
02095     }
02096 
02097   return TRUE;
02098 }
02099 #endif /* DBUS_DISABLE_CHECKS */
02100 
02116 dbus_bool_t
02117 dbus_message_iter_append_basic (DBusMessageIter *iter,
02118                                 int              type,
02119                                 const void      *value)
02120 {
02121   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02122   dbus_bool_t ret;
02123 
02124   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02125   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02126   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02127   _dbus_return_val_if_fail (value != NULL, FALSE);
02128 
02129   if (!_dbus_message_iter_open_signature (real))
02130     return FALSE;
02131 
02132   ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02133 
02134   if (!_dbus_message_iter_close_signature (real))
02135     ret = FALSE;
02136 
02137   return ret;
02138 }
02139 
02175 dbus_bool_t
02176 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02177                                       int              element_type,
02178                                       const void      *value,
02179                                       int              n_elements)
02180 {
02181   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02182   dbus_bool_t ret;
02183 
02184   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02185   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02186   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type), FALSE);
02187   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02188   _dbus_return_val_if_fail (value != NULL, FALSE);
02189   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02190   _dbus_return_val_if_fail (n_elements <=
02191                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02192                             FALSE);
02193 
02194   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02195 
02196   return ret;
02197 }
02198 
02220 dbus_bool_t
02221 dbus_message_iter_open_container (DBusMessageIter *iter,
02222                                   int              type,
02223                                   const char      *contained_signature,
02224                                   DBusMessageIter *sub)
02225 {
02226   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02227   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02228   DBusString contained_str;
02229 
02230   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02231   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02232   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02233   _dbus_return_val_if_fail (sub != NULL, FALSE);
02234   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02235                              contained_signature == NULL) ||
02236                             (type == DBUS_TYPE_DICT_ENTRY &&
02237                              contained_signature == NULL) ||
02238                             contained_signature != NULL, FALSE);
02239   
02240 #if 0
02241   /* FIXME this would fail if the contained_signature is a dict entry,
02242    * since dict entries are invalid signatures standalone (they must be in
02243    * an array)
02244    */
02245   _dbus_return_val_if_fail (contained_signature == NULL ||
02246                             _dbus_check_is_valid_signature (contained_signature));
02247 #endif
02248 
02249   if (!_dbus_message_iter_open_signature (real))
02250     return FALSE;
02251 
02252   *real_sub = *real;
02253 
02254   if (contained_signature != NULL)
02255     {
02256       _dbus_string_init_const (&contained_str, contained_signature);
02257 
02258       return _dbus_type_writer_recurse (&real->u.writer,
02259                                         type,
02260                                         &contained_str, 0,
02261                                         &real_sub->u.writer);
02262     }
02263   else
02264     {
02265       return _dbus_type_writer_recurse (&real->u.writer,
02266                                         type,
02267                                         NULL, 0,
02268                                         &real_sub->u.writer);
02269     } 
02270 }
02271 
02272 
02286 dbus_bool_t
02287 dbus_message_iter_close_container (DBusMessageIter *iter,
02288                                    DBusMessageIter *sub)
02289 {
02290   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02291   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02292   dbus_bool_t ret;
02293 
02294   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02295   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02296   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02297   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02298 
02299   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02300                                      &real_sub->u.writer);
02301 
02302   if (!_dbus_message_iter_close_signature (real))
02303     ret = FALSE;
02304 
02305   return ret;
02306 }
02307 
02319 void
02320 dbus_message_set_no_reply (DBusMessage *message,
02321                            dbus_bool_t  no_reply)
02322 {
02323   _dbus_return_if_fail (message != NULL);
02324   _dbus_return_if_fail (!message->locked);
02325 
02326   _dbus_header_toggle_flag (&message->header,
02327                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02328                             no_reply);
02329 }
02330 
02338 dbus_bool_t
02339 dbus_message_get_no_reply (DBusMessage *message)
02340 {
02341   _dbus_return_val_if_fail (message != NULL, FALSE);
02342 
02343   return _dbus_header_get_flag (&message->header,
02344                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02345 }
02346 
02357 void
02358 dbus_message_set_auto_start (DBusMessage *message,
02359                              dbus_bool_t  auto_start)
02360 {
02361   _dbus_return_if_fail (message != NULL);
02362   _dbus_return_if_fail (!message->locked);
02363 
02364   _dbus_header_toggle_flag (&message->header,
02365                             DBUS_HEADER_FLAG_NO_AUTO_START,
02366                             !auto_start);
02367 }
02368 
02376 dbus_bool_t
02377 dbus_message_get_auto_start (DBusMessage *message)
02378 {
02379   _dbus_return_val_if_fail (message != NULL, FALSE);
02380 
02381   return !_dbus_header_get_flag (&message->header,
02382                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02383 }
02384 
02385 
02395 dbus_bool_t
02396 dbus_message_set_path (DBusMessage   *message,
02397                        const char    *object_path)
02398 {
02399   _dbus_return_val_if_fail (message != NULL, FALSE);
02400   _dbus_return_val_if_fail (!message->locked, FALSE);
02401   _dbus_return_val_if_fail (object_path == NULL ||
02402                             _dbus_check_is_valid_path (object_path),
02403                             FALSE);
02404 
02405   return set_or_delete_string_field (message,
02406                                      DBUS_HEADER_FIELD_PATH,
02407                                      DBUS_TYPE_OBJECT_PATH,
02408                                      object_path);
02409 }
02410 
02419 const char*
02420 dbus_message_get_path (DBusMessage   *message)
02421 {
02422   const char *v;
02423 
02424   _dbus_return_val_if_fail (message != NULL, NULL);
02425 
02426   v = NULL; /* in case field doesn't exist */
02427   _dbus_header_get_field_basic (&message->header,
02428                                 DBUS_HEADER_FIELD_PATH,
02429                                 DBUS_TYPE_OBJECT_PATH,
02430                                 &v);
02431   return v;
02432 }
02433 
02441 dbus_bool_t
02442 dbus_message_has_path (DBusMessage   *message,
02443                        const char    *path)
02444 {
02445   const char *msg_path;
02446   msg_path = dbus_message_get_path (message);
02447   
02448   if (msg_path == NULL)
02449     {
02450       if (path == NULL)
02451         return TRUE;
02452       else
02453         return FALSE;
02454     }
02455 
02456   if (path == NULL)
02457     return FALSE;
02458    
02459   if (strcmp (msg_path, path) == 0)
02460     return TRUE;
02461 
02462   return FALSE;
02463 }
02464 
02483 dbus_bool_t
02484 dbus_message_get_path_decomposed (DBusMessage   *message,
02485                                   char        ***path)
02486 {
02487   const char *v;
02488 
02489   _dbus_return_val_if_fail (message != NULL, FALSE);
02490   _dbus_return_val_if_fail (path != NULL, FALSE);
02491 
02492   *path = NULL;
02493 
02494   v = dbus_message_get_path (message);
02495   if (v != NULL)
02496     {
02497       if (!_dbus_decompose_path (v, strlen (v),
02498                                  path, NULL))
02499         return FALSE;
02500     }
02501   return TRUE;
02502 }
02503 
02514 dbus_bool_t
02515 dbus_message_set_interface (DBusMessage  *message,
02516                             const char   *interface)
02517 {
02518   _dbus_return_val_if_fail (message != NULL, FALSE);
02519   _dbus_return_val_if_fail (!message->locked, FALSE);
02520   _dbus_return_val_if_fail (interface == NULL ||
02521                             _dbus_check_is_valid_interface (interface),
02522                             FALSE);
02523 
02524   return set_or_delete_string_field (message,
02525                                      DBUS_HEADER_FIELD_INTERFACE,
02526                                      DBUS_TYPE_STRING,
02527                                      interface);
02528 }
02529 
02540 const char*
02541 dbus_message_get_interface (DBusMessage *message)
02542 {
02543   const char *v;
02544 
02545   _dbus_return_val_if_fail (message != NULL, NULL);
02546 
02547   v = NULL; /* in case field doesn't exist */
02548   _dbus_header_get_field_basic (&message->header,
02549                                 DBUS_HEADER_FIELD_INTERFACE,
02550                                 DBUS_TYPE_STRING,
02551                                 &v);
02552   return v;
02553 }
02554 
02562 dbus_bool_t
02563 dbus_message_has_interface (DBusMessage   *message,
02564                             const char    *interface)
02565 {
02566   const char *msg_interface;
02567   msg_interface = dbus_message_get_interface (message);
02568    
02569   if (msg_interface == NULL)
02570     {
02571       if (interface == NULL)
02572         return TRUE;
02573       else
02574         return FALSE;
02575     }
02576 
02577   if (interface == NULL)
02578     return FALSE;
02579      
02580   if (strcmp (msg_interface, interface) == 0)
02581     return TRUE;
02582 
02583   return FALSE;
02584 
02585 }
02586 
02597 dbus_bool_t
02598 dbus_message_set_member (DBusMessage  *message,
02599                          const char   *member)
02600 {
02601   _dbus_return_val_if_fail (message != NULL, FALSE);
02602   _dbus_return_val_if_fail (!message->locked, FALSE);
02603   _dbus_return_val_if_fail (member == NULL ||
02604                             _dbus_check_is_valid_member (member),
02605                             FALSE);
02606 
02607   return set_or_delete_string_field (message,
02608                                      DBUS_HEADER_FIELD_MEMBER,
02609                                      DBUS_TYPE_STRING,
02610                                      member);
02611 }
02612 
02621 const char*
02622 dbus_message_get_member (DBusMessage *message)
02623 {
02624   const char *v;
02625 
02626   _dbus_return_val_if_fail (message != NULL, NULL);
02627 
02628   v = NULL; /* in case field doesn't exist */
02629   _dbus_header_get_field_basic (&message->header,
02630                                 DBUS_HEADER_FIELD_MEMBER,
02631                                 DBUS_TYPE_STRING,
02632                                 &v);
02633   return v;
02634 }
02635 
02643 dbus_bool_t
02644 dbus_message_has_member (DBusMessage   *message,
02645                          const char    *member)
02646 {
02647   const char *msg_member;
02648   msg_member = dbus_message_get_member (message);
02649  
02650   if (msg_member == NULL)
02651     {
02652       if (member == NULL)
02653         return TRUE;
02654       else
02655         return FALSE;
02656     }
02657 
02658   if (member == NULL)
02659     return FALSE;
02660     
02661   if (strcmp (msg_member, member) == 0)
02662     return TRUE;
02663 
02664   return FALSE;
02665 
02666 }
02667 
02676 dbus_bool_t
02677 dbus_message_set_error_name (DBusMessage  *message,
02678                              const char   *error_name)
02679 {
02680   _dbus_return_val_if_fail (message != NULL, FALSE);
02681   _dbus_return_val_if_fail (!message->locked, FALSE);
02682   _dbus_return_val_if_fail (error_name == NULL ||
02683                             _dbus_check_is_valid_error_name (error_name),
02684                             FALSE);
02685 
02686   return set_or_delete_string_field (message,
02687                                      DBUS_HEADER_FIELD_ERROR_NAME,
02688                                      DBUS_TYPE_STRING,
02689                                      error_name);
02690 }
02691 
02699 const char*
02700 dbus_message_get_error_name (DBusMessage *message)
02701 {
02702   const char *v;
02703 
02704   _dbus_return_val_if_fail (message != NULL, NULL);
02705 
02706   v = NULL; /* in case field doesn't exist */
02707   _dbus_header_get_field_basic (&message->header,
02708                                 DBUS_HEADER_FIELD_ERROR_NAME,
02709                                 DBUS_TYPE_STRING,
02710                                 &v);
02711   return v;
02712 }
02713 
02724 dbus_bool_t
02725 dbus_message_set_destination (DBusMessage  *message,
02726                               const char   *destination)
02727 {
02728   _dbus_return_val_if_fail (message != NULL, FALSE);
02729   _dbus_return_val_if_fail (!message->locked, FALSE);
02730   _dbus_return_val_if_fail (destination == NULL ||
02731                             _dbus_check_is_valid_bus_name (destination),
02732                             FALSE);
02733 
02734   return set_or_delete_string_field (message,
02735                                      DBUS_HEADER_FIELD_DESTINATION,
02736                                      DBUS_TYPE_STRING,
02737                                      destination);
02738 }
02739 
02746 const char*
02747 dbus_message_get_destination (DBusMessage *message)
02748 {
02749   const char *v;
02750 
02751   _dbus_return_val_if_fail (message != NULL, NULL);
02752 
02753   v = NULL; /* in case field doesn't exist */
02754   _dbus_header_get_field_basic (&message->header,
02755                                 DBUS_HEADER_FIELD_DESTINATION,
02756                                 DBUS_TYPE_STRING,
02757                                 &v);
02758   return v;
02759 }
02760 
02768 dbus_bool_t
02769 dbus_message_set_sender (DBusMessage  *message,
02770                          const char   *sender)
02771 {
02772   _dbus_return_val_if_fail (message != NULL, FALSE);
02773   _dbus_return_val_if_fail (!message->locked, FALSE);
02774   _dbus_return_val_if_fail (sender == NULL ||
02775                             _dbus_check_is_valid_bus_name (sender),
02776                             FALSE);
02777 
02778   return set_or_delete_string_field (message,
02779                                      DBUS_HEADER_FIELD_SENDER,
02780                                      DBUS_TYPE_STRING,
02781                                      sender);
02782 }
02783 
02792 const char*
02793 dbus_message_get_sender (DBusMessage *message)
02794 {
02795   const char *v;
02796 
02797   _dbus_return_val_if_fail (message != NULL, NULL);
02798 
02799   v = NULL; /* in case field doesn't exist */
02800   _dbus_header_get_field_basic (&message->header,
02801                                 DBUS_HEADER_FIELD_SENDER,
02802                                 DBUS_TYPE_STRING,
02803                                 &v);
02804   return v;
02805 }
02806 
02822 const char*
02823 dbus_message_get_signature (DBusMessage *message)
02824 {
02825   const DBusString *type_str;
02826   int type_pos;
02827 
02828   _dbus_return_val_if_fail (message != NULL, NULL);
02829 
02830   get_const_signature (&message->header, &type_str, &type_pos);
02831 
02832   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
02833 }
02834 
02835 static dbus_bool_t
02836 _dbus_message_has_type_interface_member (DBusMessage *message,
02837                                          int          type,
02838                                          const char  *interface,
02839                                          const char  *member)
02840 {
02841   const char *n;
02842 
02843   _dbus_assert (message != NULL);
02844   _dbus_assert (interface != NULL);
02845   _dbus_assert (member != NULL);
02846 
02847   if (dbus_message_get_type (message) != type)
02848     return FALSE;
02849 
02850   /* Optimize by checking the short member name first
02851    * instead of the longer interface name
02852    */
02853 
02854   n = dbus_message_get_member (message);
02855 
02856   if (n && strcmp (n, member) == 0)
02857     {
02858       n = dbus_message_get_interface (message);
02859 
02860       if (n == NULL || strcmp (n, interface) == 0)
02861         return TRUE;
02862     }
02863 
02864   return FALSE;
02865 }
02866 
02881 dbus_bool_t
02882 dbus_message_is_method_call (DBusMessage *message,
02883                              const char  *interface,
02884                              const char  *method)
02885 {
02886   _dbus_return_val_if_fail (message != NULL, FALSE);
02887   _dbus_return_val_if_fail (interface != NULL, FALSE);
02888   _dbus_return_val_if_fail (method != NULL, FALSE);
02889   /* don't check that interface/method are valid since it would be
02890    * expensive, and not catch many common errors
02891    */
02892 
02893   return _dbus_message_has_type_interface_member (message,
02894                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
02895                                                   interface, method);
02896 }
02897 
02911 dbus_bool_t
02912 dbus_message_is_signal (DBusMessage *message,
02913                         const char  *interface,
02914                         const char  *signal_name)
02915 {
02916   _dbus_return_val_if_fail (message != NULL, FALSE);
02917   _dbus_return_val_if_fail (interface != NULL, FALSE);
02918   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
02919   /* don't check that interface/name are valid since it would be
02920    * expensive, and not catch many common errors
02921    */
02922 
02923   return _dbus_message_has_type_interface_member (message,
02924                                                   DBUS_MESSAGE_TYPE_SIGNAL,
02925                                                   interface, signal_name);
02926 }
02927 
02938 dbus_bool_t
02939 dbus_message_is_error (DBusMessage *message,
02940                        const char  *error_name)
02941 {
02942   const char *n;
02943 
02944   _dbus_return_val_if_fail (message != NULL, FALSE);
02945   _dbus_return_val_if_fail (error_name != NULL, FALSE);
02946   /* don't check that error_name is valid since it would be expensive,
02947    * and not catch many common errors
02948    */
02949 
02950   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
02951     return FALSE;
02952 
02953   n = dbus_message_get_error_name (message);
02954 
02955   if (n && strcmp (n, error_name) == 0)
02956     return TRUE;
02957   else
02958     return FALSE;
02959 }
02960 
02971 dbus_bool_t
02972 dbus_message_has_destination (DBusMessage  *message,
02973                               const char   *name)
02974 {
02975   const char *s;
02976 
02977   _dbus_return_val_if_fail (message != NULL, FALSE);
02978   _dbus_return_val_if_fail (name != NULL, FALSE);
02979   /* don't check that name is valid since it would be expensive, and
02980    * not catch many common errors
02981    */
02982 
02983   s = dbus_message_get_destination (message);
02984 
02985   if (s && strcmp (s, name) == 0)
02986     return TRUE;
02987   else
02988     return FALSE;
02989 }
02990 
03006 dbus_bool_t
03007 dbus_message_has_sender (DBusMessage  *message,
03008                          const char   *name)
03009 {
03010   const char *s;
03011 
03012   _dbus_return_val_if_fail (message != NULL, FALSE);
03013   _dbus_return_val_if_fail (name != NULL, FALSE);
03014   /* don't check that name is valid since it would be expensive, and
03015    * not catch many common errors
03016    */
03017 
03018   s = dbus_message_get_sender (message);
03019 
03020   if (s && strcmp (s, name) == 0)
03021     return TRUE;
03022   else
03023     return FALSE;
03024 }
03025 
03035 dbus_bool_t
03036 dbus_message_has_signature (DBusMessage   *message,
03037                             const char    *signature)
03038 {
03039   const char *s;
03040 
03041   _dbus_return_val_if_fail (message != NULL, FALSE);
03042   _dbus_return_val_if_fail (signature != NULL, FALSE);
03043   /* don't check that signature is valid since it would be expensive,
03044    * and not catch many common errors
03045    */
03046 
03047   s = dbus_message_get_signature (message);
03048 
03049   if (s && strcmp (s, signature) == 0)
03050     return TRUE;
03051   else
03052     return FALSE;
03053 }
03054 
03077 dbus_bool_t
03078 dbus_set_error_from_message (DBusError   *error,
03079                              DBusMessage *message)
03080 {
03081   const char *str;
03082 
03083   _dbus_return_val_if_fail (message != NULL, FALSE);
03084   _dbus_return_val_if_error_is_set (error, FALSE);
03085 
03086   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03087     return FALSE;
03088 
03089   str = NULL;
03090   dbus_message_get_args (message, NULL,
03091                          DBUS_TYPE_STRING, &str,
03092                          DBUS_TYPE_INVALID);
03093 
03094   dbus_set_error (error, dbus_message_get_error_name (message),
03095                   str ? "%s" : NULL, str);
03096 
03097   return TRUE;
03098 }
03099 
03118 #define INITIAL_LOADER_DATA_LEN 32
03119 
03126 DBusMessageLoader*
03127 _dbus_message_loader_new (void)
03128 {
03129   DBusMessageLoader *loader;
03130 
03131   loader = dbus_new0 (DBusMessageLoader, 1);
03132   if (loader == NULL)
03133     return NULL;
03134   
03135   loader->refcount = 1;
03136 
03137   loader->corrupted = FALSE;
03138   loader->corruption_reason = DBUS_VALID;
03139 
03140   /* this can be configured by the app, but defaults to the protocol max */
03141   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03142 
03143   if (!_dbus_string_init (&loader->data))
03144     {
03145       dbus_free (loader);
03146       return NULL;
03147     }
03148 
03149   /* preallocate the buffer for speed, ignore failure */
03150   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03151   _dbus_string_set_length (&loader->data, 0);
03152 
03153   return loader;
03154 }
03155 
03162 DBusMessageLoader *
03163 _dbus_message_loader_ref (DBusMessageLoader *loader)
03164 {
03165   loader->refcount += 1;
03166 
03167   return loader;
03168 }
03169 
03176 void
03177 _dbus_message_loader_unref (DBusMessageLoader *loader)
03178 {
03179   loader->refcount -= 1;
03180   if (loader->refcount == 0)
03181     {
03182       _dbus_list_foreach (&loader->messages,
03183                           (DBusForeachFunction) dbus_message_unref,
03184                           NULL);
03185       _dbus_list_clear (&loader->messages);
03186       _dbus_string_free (&loader->data);
03187       dbus_free (loader);
03188     }
03189 }
03190 
03209 void
03210 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03211                                  DBusString        **buffer)
03212 {
03213   _dbus_assert (!loader->buffer_outstanding);
03214 
03215   *buffer = &loader->data;
03216 
03217   loader->buffer_outstanding = TRUE;
03218 }
03219 
03230 void
03231 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03232                                     DBusString         *buffer,
03233                                     int                 bytes_read)
03234 {
03235   _dbus_assert (loader->buffer_outstanding);
03236   _dbus_assert (buffer == &loader->data);
03237 
03238   loader->buffer_outstanding = FALSE;
03239 }
03240 
03241 /*
03242  * FIXME when we move the header out of the buffer, that memmoves all
03243  * buffered messages. Kind of crappy.
03244  *
03245  * Also we copy the header and body, which is kind of crappy.  To
03246  * avoid this, we have to allow header and body to be in a single
03247  * memory block, which is good for messages we read and bad for
03248  * messages we are creating. But we could move_len() the buffer into
03249  * this single memory block, and move_len() will just swap the buffers
03250  * if you're moving the entire buffer replacing the dest string.
03251  *
03252  * We could also have the message loader tell the transport how many
03253  * bytes to read; so it would first ask for some arbitrary number like
03254  * 256, then if the message was incomplete it would use the
03255  * header/body len to ask for exactly the size of the message (or
03256  * blocks the size of a typical kernel buffer for the socket). That
03257  * way we don't get trailing bytes in the buffer that have to be
03258  * memmoved. Though I suppose we also don't have a chance of reading a
03259  * bunch of small messages at once, so the optimization may be stupid.
03260  *
03261  * Another approach would be to keep a "start" index into
03262  * loader->data and only delete it occasionally, instead of after
03263  * each message is loaded.
03264  *
03265  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03266  */
03267 static dbus_bool_t
03268 load_message (DBusMessageLoader *loader,
03269               DBusMessage       *message,
03270               int                byte_order,
03271               int                fields_array_len,
03272               int                header_len,
03273               int                body_len)
03274 {
03275   dbus_bool_t oom;
03276   DBusValidity validity;
03277   const DBusString *type_str;
03278   int type_pos;
03279   DBusValidationMode mode;
03280 
03281   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03282   
03283   oom = FALSE;
03284 
03285 #if 0
03286   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03287 #endif
03288 
03289   /* 1. VALIDATE AND COPY OVER HEADER */
03290   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03291   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03292 
03293   if (!_dbus_header_load (&message->header,
03294                           mode,
03295                           &validity,
03296                           byte_order,
03297                           fields_array_len,
03298                           header_len,
03299                           body_len,
03300                           &loader->data, 0,
03301                           _dbus_string_get_length (&loader->data)))
03302     {
03303       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03304 
03305       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03306          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03307       _dbus_assert (validity != DBUS_VALID);
03308 
03309       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03310         oom = TRUE;
03311       else
03312         {
03313           loader->corrupted = TRUE;
03314           loader->corruption_reason = validity;
03315         }
03316       goto failed;
03317     }
03318 
03319   _dbus_assert (validity == DBUS_VALID);
03320 
03321   message->byte_order = byte_order;
03322 
03323   /* 2. VALIDATE BODY */
03324   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
03325     {
03326       get_const_signature (&message->header, &type_str, &type_pos);
03327       
03328       /* Because the bytes_remaining arg is NULL, this validates that the
03329        * body is the right length
03330        */
03331       validity = _dbus_validate_body_with_reason (type_str,
03332                                                   type_pos,
03333                                                   byte_order,
03334                                                   NULL,
03335                                                   &loader->data,
03336                                                   header_len,
03337                                                   body_len);
03338       if (validity != DBUS_VALID)
03339         {
03340           _dbus_verbose ("Failed to validate message body code %d\n", validity);
03341 
03342           loader->corrupted = TRUE;
03343           loader->corruption_reason = validity;
03344           
03345           goto failed;
03346         }
03347     }
03348 
03349   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
03350 
03351   if (!_dbus_list_append (&loader->messages, message))
03352     {
03353       _dbus_verbose ("Failed to append new message to loader queue\n");
03354       oom = TRUE;
03355       goto failed;
03356     }
03357 
03358   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
03359   _dbus_assert (_dbus_string_get_length (&loader->data) >=
03360                 (header_len + body_len));
03361 
03362   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
03363     {
03364       _dbus_verbose ("Failed to move body into new message\n");
03365       oom = TRUE;
03366       goto failed;
03367     }
03368 
03369   _dbus_string_delete (&loader->data, 0, header_len + body_len);
03370 
03371   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
03372   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
03373 
03374   _dbus_verbose ("Loaded message %p\n", message);
03375 
03376   _dbus_assert (!oom);
03377   _dbus_assert (!loader->corrupted);
03378   _dbus_assert (loader->messages != NULL);
03379   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03380 
03381   return TRUE;
03382 
03383  failed:
03384 
03385   /* Clean up */
03386 
03387   /* does nothing if the message isn't in the list */
03388   _dbus_list_remove_last (&loader->messages, message);
03389   
03390   if (oom)
03391     _dbus_assert (!loader->corrupted);
03392   else
03393     _dbus_assert (loader->corrupted);
03394 
03395   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
03396 
03397   return FALSE;
03398 }
03399 
03414 dbus_bool_t
03415 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
03416 {
03417   while (!loader->corrupted &&
03418          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
03419     {
03420       DBusValidity validity;
03421       int byte_order, fields_array_len, header_len, body_len;
03422 
03423       if (_dbus_header_have_message_untrusted (loader->max_message_size,
03424                                                &validity,
03425                                                &byte_order,
03426                                                &fields_array_len,
03427                                                &header_len,
03428                                                &body_len,
03429                                                &loader->data, 0,
03430                                                _dbus_string_get_length (&loader->data)))
03431         {
03432           DBusMessage *message;
03433 
03434           _dbus_assert (validity == DBUS_VALID);
03435 
03436           message = dbus_message_new_empty_header ();
03437           if (message == NULL)
03438             return FALSE;
03439 
03440           if (!load_message (loader, message,
03441                              byte_order, fields_array_len,
03442                              header_len, body_len))
03443             {
03444               dbus_message_unref (message);
03445               /* load_message() returns false if corrupted or OOM; if
03446                * corrupted then return TRUE for not OOM
03447                */
03448               return loader->corrupted;
03449             }
03450 
03451           _dbus_assert (loader->messages != NULL);
03452           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03453         }
03454       else
03455         {
03456           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
03457                          validity);
03458           if (validity != DBUS_VALID)
03459             {
03460               loader->corrupted = TRUE;
03461               loader->corruption_reason = validity;
03462             }
03463           return TRUE;
03464         }
03465     }
03466 
03467   return TRUE;
03468 }
03469 
03477 DBusMessage*
03478 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
03479 {
03480   if (loader->messages)
03481     return loader->messages->data;
03482   else
03483     return NULL;
03484 }
03485 
03494 DBusMessage*
03495 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
03496 {
03497   return _dbus_list_pop_first (&loader->messages);
03498 }
03499 
03508 DBusList*
03509 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
03510 {
03511   return _dbus_list_pop_first_link (&loader->messages);
03512 }
03513 
03520 void
03521 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
03522                                            DBusList           *link)
03523 {
03524   _dbus_list_prepend_link (&loader->messages, link);
03525 }
03526 
03536 dbus_bool_t
03537 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
03538 {
03539   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
03540                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
03541   return loader->corrupted;
03542 }
03543 
03550 void
03551 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
03552                                            long                size)
03553 {
03554   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
03555     {
03556       _dbus_verbose ("clamping requested max message size %ld to %d\n",
03557                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
03558       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03559     }
03560   loader->max_message_size = size;
03561 }
03562 
03569 long
03570 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
03571 {
03572   return loader->max_message_size;
03573 }
03574 
03575 static DBusDataSlotAllocator slot_allocator;
03576 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
03577 
03592 dbus_bool_t
03593 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
03594 {
03595   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03596                                           _DBUS_LOCK_NAME (message_slots),
03597                                           slot_p);
03598 }
03599 
03611 void
03612 dbus_message_free_data_slot (dbus_int32_t *slot_p)
03613 {
03614   _dbus_return_if_fail (*slot_p >= 0);
03615 
03616   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03617 }
03618 
03632 dbus_bool_t
03633 dbus_message_set_data (DBusMessage     *message,
03634                        dbus_int32_t     slot,
03635                        void            *data,
03636                        DBusFreeFunction free_data_func)
03637 {
03638   DBusFreeFunction old_free_func;
03639   void *old_data;
03640   dbus_bool_t retval;
03641 
03642   _dbus_return_val_if_fail (message != NULL, FALSE);
03643   _dbus_return_val_if_fail (slot >= 0, FALSE);
03644 
03645   retval = _dbus_data_slot_list_set (&slot_allocator,
03646                                      &message->slot_list,
03647                                      slot, data, free_data_func,
03648                                      &old_free_func, &old_data);
03649 
03650   if (retval)
03651     {
03652       /* Do the actual free outside the message lock */
03653       if (old_free_func)
03654         (* old_free_func) (old_data);
03655     }
03656 
03657   return retval;
03658 }
03659 
03668 void*
03669 dbus_message_get_data (DBusMessage   *message,
03670                        dbus_int32_t   slot)
03671 {
03672   void *res;
03673 
03674   _dbus_return_val_if_fail (message != NULL, NULL);
03675 
03676   res = _dbus_data_slot_list_get (&slot_allocator,
03677                                   &message->slot_list,
03678                                   slot);
03679 
03680   return res;
03681 }
03682 
03696 int
03697 dbus_message_type_from_string (const char *type_str)
03698 {
03699   if (strcmp (type_str, "method_call") == 0)
03700     return DBUS_MESSAGE_TYPE_METHOD_CALL;
03701   if (strcmp (type_str, "method_return") == 0)
03702     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
03703   else if (strcmp (type_str, "signal") == 0)
03704     return DBUS_MESSAGE_TYPE_SIGNAL;
03705   else if (strcmp (type_str, "error") == 0)
03706     return DBUS_MESSAGE_TYPE_ERROR;
03707   else
03708     return DBUS_MESSAGE_TYPE_INVALID;
03709 }
03710 
03724 const char *
03725 dbus_message_type_to_string (int type)
03726 {
03727   switch (type)
03728     {
03729     case DBUS_MESSAGE_TYPE_METHOD_CALL:
03730       return "method_call";
03731     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
03732       return "method_return";
03733     case DBUS_MESSAGE_TYPE_SIGNAL:
03734       return "signal";
03735     case DBUS_MESSAGE_TYPE_ERROR:
03736       return "error";
03737     default:
03738       return "invalid";
03739     }
03740 }
03741 
03744 /* tests in dbus-message-util.c */

Generated on Wed Jan 3 04:49:04 2007 for D-BUS by  doxygen 1.4.4