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   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
01739 
01740   _dbus_return_if_fail (_dbus_message_iter_check (real));
01741   _dbus_return_if_fail (value != NULL);
01742   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
01743                          dbus_type_is_fixed (subtype));
01744 
01745   _dbus_type_reader_read_fixed_multi (&real->u.reader,
01746                                       value, n_elements);
01747 }
01748 
01762 dbus_bool_t
01763 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
01764                                     DBusError       *error,
01765                                     int              first_arg_type,
01766                                     va_list          var_args)
01767 {
01768   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01769   int spec_type, msg_type, i;
01770   dbus_bool_t retval;
01771 
01772   _dbus_assert (_dbus_message_iter_check (real));
01773 
01774   retval = FALSE;
01775 
01776   spec_type = first_arg_type;
01777   i = 0;
01778 
01779   while (spec_type != DBUS_TYPE_INVALID)
01780     {
01781       msg_type = dbus_message_iter_get_arg_type (iter);
01782 
01783       if (msg_type != spec_type)
01784         {
01785           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01786                           "Argument %d is specified to be of type \"%s\", but "
01787                           "is actually of type \"%s\"\n", i,
01788                           _dbus_type_to_string (spec_type),
01789                           _dbus_type_to_string (msg_type));
01790 
01791           goto out;
01792         }
01793 
01794       if (dbus_type_is_basic (spec_type))
01795         {
01796           DBusBasicValue *ptr;
01797 
01798           ptr = va_arg (var_args, DBusBasicValue*);
01799 
01800           _dbus_assert (ptr != NULL);
01801 
01802           _dbus_type_reader_read_basic (&real->u.reader,
01803                                         ptr);
01804         }
01805       else if (spec_type == DBUS_TYPE_ARRAY)
01806         {
01807           int element_type;
01808           int spec_element_type;
01809           const DBusBasicValue **ptr;
01810           int *n_elements_p;
01811           DBusTypeReader array;
01812 
01813           spec_element_type = va_arg (var_args, int);
01814           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
01815 
01816           if (spec_element_type != element_type)
01817             {
01818               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01819                               "Argument %d is specified to be an array of \"%s\", but "
01820                               "is actually an array of \"%s\"\n",
01821                               i,
01822                               _dbus_type_to_string (spec_element_type),
01823                               _dbus_type_to_string (element_type));
01824 
01825               goto out;
01826             }
01827 
01828           if (dbus_type_is_fixed (spec_element_type))
01829             {
01830               ptr = va_arg (var_args, const DBusBasicValue**);
01831               n_elements_p = va_arg (var_args, int*);
01832 
01833               _dbus_assert (ptr != NULL);
01834               _dbus_assert (n_elements_p != NULL);
01835 
01836               _dbus_type_reader_recurse (&real->u.reader, &array);
01837 
01838               _dbus_type_reader_read_fixed_multi (&array,
01839                                                   ptr, n_elements_p);
01840             }
01841           else if (spec_element_type == DBUS_TYPE_STRING ||
01842                    spec_element_type == DBUS_TYPE_SIGNATURE ||
01843                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
01844             {
01845               char ***str_array_p;
01846               int n_elements;
01847               char **str_array;
01848 
01849               str_array_p = va_arg (var_args, char***);
01850               n_elements_p = va_arg (var_args, int*);
01851 
01852               _dbus_assert (str_array_p != NULL);
01853               _dbus_assert (n_elements_p != NULL);
01854 
01855               /* Count elements in the array */
01856               _dbus_type_reader_recurse (&real->u.reader, &array);
01857 
01858               n_elements = 0;
01859               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
01860                 {
01861                   ++n_elements;
01862                   _dbus_type_reader_next (&array);
01863                 }
01864 
01865               str_array = dbus_new0 (char*, n_elements + 1);
01866               if (str_array == NULL)
01867                 {
01868                   _DBUS_SET_OOM (error);
01869                   goto out;
01870                 }
01871 
01872               /* Now go through and dup each string */
01873               _dbus_type_reader_recurse (&real->u.reader, &array);
01874 
01875               i = 0;
01876               while (i < n_elements)
01877                 {
01878                   const char *s;
01879                   _dbus_type_reader_read_basic (&array,
01880                                                 &s);
01881                   
01882                   str_array[i] = _dbus_strdup (s);
01883                   if (str_array[i] == NULL)
01884                     {
01885                       dbus_free_string_array (str_array);
01886                       _DBUS_SET_OOM (error);
01887                       goto out;
01888                     }
01889                   
01890                   ++i;
01891                   
01892                   if (!_dbus_type_reader_next (&array))
01893                     _dbus_assert (i == n_elements);
01894                 }
01895 
01896               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
01897               _dbus_assert (i == n_elements);
01898               _dbus_assert (str_array[i] == NULL);
01899 
01900               *str_array_p = str_array;
01901               *n_elements_p = n_elements;
01902             }
01903 #ifndef DBUS_DISABLE_CHECKS
01904           else
01905             {
01906               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
01907                           _DBUS_FUNCTION_NAME);
01908               goto out;
01909             }
01910 #endif
01911         }
01912 #ifndef DBUS_DISABLE_CHECKS
01913       else
01914         {
01915           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
01916                       _DBUS_FUNCTION_NAME);
01917           goto out;
01918         }
01919 #endif
01920 
01921       spec_type = va_arg (var_args, int);
01922       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
01923         {
01924           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01925                           "Message has only %d arguments, but more were expected", i);
01926           goto out;
01927         }
01928 
01929       i++;
01930     }
01931 
01932   retval = TRUE;
01933 
01934  out:
01935 
01936   return retval;
01937 }
01938 
01950 void
01951 dbus_message_iter_init_append (DBusMessage     *message,
01952                                DBusMessageIter *iter)
01953 {
01954   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01955 
01956   _dbus_return_if_fail (message != NULL);
01957   _dbus_return_if_fail (iter != NULL);
01958 
01959   _dbus_message_iter_init_common (message, real,
01960                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
01961 
01962   /* We create the signature string and point iterators at it "on demand"
01963    * when a value is actually appended. That means that init() never fails
01964    * due to OOM.
01965    */
01966   _dbus_type_writer_init_types_delayed (&real->u.writer,
01967                                         message->byte_order,
01968                                         &message->body,
01969                                         _dbus_string_get_length (&message->body));
01970 }
01971 
01980 static dbus_bool_t
01981 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
01982 {
01983   DBusString *str;
01984   const DBusString *current_sig;
01985   int current_sig_pos;
01986 
01987   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
01988 
01989   if (real->u.writer.type_str != NULL)
01990     {
01991       _dbus_assert (real->sig_refcount > 0);
01992       real->sig_refcount += 1;
01993       return TRUE;
01994     }
01995 
01996   str = dbus_new (DBusString, 1);
01997   if (str == NULL)
01998     return FALSE;
01999 
02000   if (!_dbus_header_get_field_raw (&real->message->header,
02001                                    DBUS_HEADER_FIELD_SIGNATURE,
02002                                    &current_sig, &current_sig_pos))
02003     current_sig = NULL;
02004 
02005   if (current_sig)
02006     {
02007       int current_len;
02008 
02009       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02010       current_sig_pos += 1; /* move on to sig data */
02011 
02012       if (!_dbus_string_init_preallocated (str, current_len + 4))
02013         {
02014           dbus_free (str);
02015           return FALSE;
02016         }
02017 
02018       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02019                                   str, 0))
02020         {
02021           _dbus_string_free (str);
02022           dbus_free (str);
02023           return FALSE;
02024         }
02025     }
02026   else
02027     {
02028       if (!_dbus_string_init_preallocated (str, 4))
02029         {
02030           dbus_free (str);
02031           return FALSE;
02032         }
02033     }
02034 
02035   real->sig_refcount = 1;
02036 
02037   _dbus_type_writer_add_types (&real->u.writer,
02038                                str, _dbus_string_get_length (str));
02039   return TRUE;
02040 }
02041 
02051 static dbus_bool_t
02052 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02053 {
02054   DBusString *str;
02055   const char *v_STRING;
02056   dbus_bool_t retval;
02057 
02058   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02059   _dbus_assert (real->u.writer.type_str != NULL);
02060   _dbus_assert (real->sig_refcount > 0);
02061 
02062   real->sig_refcount -= 1;
02063 
02064   if (real->sig_refcount > 0)
02065     return TRUE;
02066   _dbus_assert (real->sig_refcount == 0);
02067 
02068   retval = TRUE;
02069 
02070   str = real->u.writer.type_str;
02071 
02072   v_STRING = _dbus_string_get_const_data (str);
02073   if (!_dbus_header_set_field_basic (&real->message->header,
02074                                      DBUS_HEADER_FIELD_SIGNATURE,
02075                                      DBUS_TYPE_SIGNATURE,
02076                                      &v_STRING))
02077     retval = FALSE;
02078 
02079   _dbus_type_writer_remove_types (&real->u.writer);
02080   _dbus_string_free (str);
02081   dbus_free (str);
02082 
02083   return retval;
02084 }
02085 
02086 #ifndef DBUS_DISABLE_CHECKS
02087 static dbus_bool_t
02088 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02089 {
02090   if (!_dbus_message_iter_check (iter))
02091     return FALSE;
02092 
02093   if (iter->message->locked)
02094     {
02095       _dbus_warn ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02096       return FALSE;
02097     }
02098 
02099   return TRUE;
02100 }
02101 #endif /* DBUS_DISABLE_CHECKS */
02102 
02118 dbus_bool_t
02119 dbus_message_iter_append_basic (DBusMessageIter *iter,
02120                                 int              type,
02121                                 const void      *value)
02122 {
02123   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02124   dbus_bool_t ret;
02125 
02126   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02127   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02128   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02129   _dbus_return_val_if_fail (value != NULL, FALSE);
02130 
02131   if (!_dbus_message_iter_open_signature (real))
02132     return FALSE;
02133 
02134   ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02135 
02136   if (!_dbus_message_iter_close_signature (real))
02137     ret = FALSE;
02138 
02139   return ret;
02140 }
02141 
02177 dbus_bool_t
02178 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02179                                       int              element_type,
02180                                       const void      *value,
02181                                       int              n_elements)
02182 {
02183   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02184   dbus_bool_t ret;
02185 
02186   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02187   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02188   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type), FALSE);
02189   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02190   _dbus_return_val_if_fail (value != NULL, FALSE);
02191   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02192   _dbus_return_val_if_fail (n_elements <=
02193                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02194                             FALSE);
02195 
02196   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02197 
02198   return ret;
02199 }
02200 
02222 dbus_bool_t
02223 dbus_message_iter_open_container (DBusMessageIter *iter,
02224                                   int              type,
02225                                   const char      *contained_signature,
02226                                   DBusMessageIter *sub)
02227 {
02228   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02229   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02230   DBusString contained_str;
02231 
02232   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02233   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02234   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02235   _dbus_return_val_if_fail (sub != NULL, FALSE);
02236   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02237                              contained_signature == NULL) ||
02238                             (type == DBUS_TYPE_DICT_ENTRY &&
02239                              contained_signature == NULL) ||
02240                             contained_signature != NULL, FALSE);
02241   
02242 #if 0
02243   /* FIXME this would fail if the contained_signature is a dict entry,
02244    * since dict entries are invalid signatures standalone (they must be in
02245    * an array)
02246    */
02247   _dbus_return_val_if_fail (contained_signature == NULL ||
02248                             _dbus_check_is_valid_signature (contained_signature));
02249 #endif
02250 
02251   if (!_dbus_message_iter_open_signature (real))
02252     return FALSE;
02253 
02254   *real_sub = *real;
02255 
02256   if (contained_signature != NULL)
02257     {
02258       _dbus_string_init_const (&contained_str, contained_signature);
02259 
02260       return _dbus_type_writer_recurse (&real->u.writer,
02261                                         type,
02262                                         &contained_str, 0,
02263                                         &real_sub->u.writer);
02264     }
02265   else
02266     {
02267       return _dbus_type_writer_recurse (&real->u.writer,
02268                                         type,
02269                                         NULL, 0,
02270                                         &real_sub->u.writer);
02271     } 
02272 }
02273 
02274 
02288 dbus_bool_t
02289 dbus_message_iter_close_container (DBusMessageIter *iter,
02290                                    DBusMessageIter *sub)
02291 {
02292   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02293   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02294   dbus_bool_t ret;
02295 
02296   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02297   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02298   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02299   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02300 
02301   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02302                                      &real_sub->u.writer);
02303 
02304   if (!_dbus_message_iter_close_signature (real))
02305     ret = FALSE;
02306 
02307   return ret;
02308 }
02309 
02321 void
02322 dbus_message_set_no_reply (DBusMessage *message,
02323                            dbus_bool_t  no_reply)
02324 {
02325   _dbus_return_if_fail (message != NULL);
02326   _dbus_return_if_fail (!message->locked);
02327 
02328   _dbus_header_toggle_flag (&message->header,
02329                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02330                             no_reply);
02331 }
02332 
02340 dbus_bool_t
02341 dbus_message_get_no_reply (DBusMessage *message)
02342 {
02343   _dbus_return_val_if_fail (message != NULL, FALSE);
02344 
02345   return _dbus_header_get_flag (&message->header,
02346                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02347 }
02348 
02359 void
02360 dbus_message_set_auto_start (DBusMessage *message,
02361                              dbus_bool_t  auto_start)
02362 {
02363   _dbus_return_if_fail (message != NULL);
02364   _dbus_return_if_fail (!message->locked);
02365 
02366   _dbus_header_toggle_flag (&message->header,
02367                             DBUS_HEADER_FLAG_NO_AUTO_START,
02368                             !auto_start);
02369 }
02370 
02378 dbus_bool_t
02379 dbus_message_get_auto_start (DBusMessage *message)
02380 {
02381   _dbus_return_val_if_fail (message != NULL, FALSE);
02382 
02383   return !_dbus_header_get_flag (&message->header,
02384                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02385 }
02386 
02387 
02397 dbus_bool_t
02398 dbus_message_set_path (DBusMessage   *message,
02399                        const char    *object_path)
02400 {
02401   _dbus_return_val_if_fail (message != NULL, FALSE);
02402   _dbus_return_val_if_fail (!message->locked, FALSE);
02403   _dbus_return_val_if_fail (object_path == NULL ||
02404                             _dbus_check_is_valid_path (object_path),
02405                             FALSE);
02406 
02407   return set_or_delete_string_field (message,
02408                                      DBUS_HEADER_FIELD_PATH,
02409                                      DBUS_TYPE_OBJECT_PATH,
02410                                      object_path);
02411 }
02412 
02421 const char*
02422 dbus_message_get_path (DBusMessage   *message)
02423 {
02424   const char *v;
02425 
02426   _dbus_return_val_if_fail (message != NULL, NULL);
02427 
02428   v = NULL; /* in case field doesn't exist */
02429   _dbus_header_get_field_basic (&message->header,
02430                                 DBUS_HEADER_FIELD_PATH,
02431                                 DBUS_TYPE_OBJECT_PATH,
02432                                 &v);
02433   return v;
02434 }
02435 
02443 dbus_bool_t
02444 dbus_message_has_path (DBusMessage   *message,
02445                        const char    *path)
02446 {
02447   const char *msg_path;
02448   msg_path = dbus_message_get_path (message);
02449   
02450   if (msg_path == NULL)
02451     {
02452       if (path == NULL)
02453         return TRUE;
02454       else
02455         return FALSE;
02456     }
02457 
02458   if (path == NULL)
02459     return FALSE;
02460    
02461   if (strcmp (msg_path, path) == 0)
02462     return TRUE;
02463 
02464   return FALSE;
02465 }
02466 
02485 dbus_bool_t
02486 dbus_message_get_path_decomposed (DBusMessage   *message,
02487                                   char        ***path)
02488 {
02489   const char *v;
02490 
02491   _dbus_return_val_if_fail (message != NULL, FALSE);
02492   _dbus_return_val_if_fail (path != NULL, FALSE);
02493 
02494   *path = NULL;
02495 
02496   v = dbus_message_get_path (message);
02497   if (v != NULL)
02498     {
02499       if (!_dbus_decompose_path (v, strlen (v),
02500                                  path, NULL))
02501         return FALSE;
02502     }
02503   return TRUE;
02504 }
02505 
02516 dbus_bool_t
02517 dbus_message_set_interface (DBusMessage  *message,
02518                             const char   *interface)
02519 {
02520   _dbus_return_val_if_fail (message != NULL, FALSE);
02521   _dbus_return_val_if_fail (!message->locked, FALSE);
02522   _dbus_return_val_if_fail (interface == NULL ||
02523                             _dbus_check_is_valid_interface (interface),
02524                             FALSE);
02525 
02526   return set_or_delete_string_field (message,
02527                                      DBUS_HEADER_FIELD_INTERFACE,
02528                                      DBUS_TYPE_STRING,
02529                                      interface);
02530 }
02531 
02542 const char*
02543 dbus_message_get_interface (DBusMessage *message)
02544 {
02545   const char *v;
02546 
02547   _dbus_return_val_if_fail (message != NULL, NULL);
02548 
02549   v = NULL; /* in case field doesn't exist */
02550   _dbus_header_get_field_basic (&message->header,
02551                                 DBUS_HEADER_FIELD_INTERFACE,
02552                                 DBUS_TYPE_STRING,
02553                                 &v);
02554   return v;
02555 }
02556 
02564 dbus_bool_t
02565 dbus_message_has_interface (DBusMessage   *message,
02566                             const char    *interface)
02567 {
02568   const char *msg_interface;
02569   msg_interface = dbus_message_get_interface (message);
02570    
02571   if (msg_interface == NULL)
02572     {
02573       if (interface == NULL)
02574         return TRUE;
02575       else
02576         return FALSE;
02577     }
02578 
02579   if (interface == NULL)
02580     return FALSE;
02581      
02582   if (strcmp (msg_interface, interface) == 0)
02583     return TRUE;
02584 
02585   return FALSE;
02586 
02587 }
02588 
02599 dbus_bool_t
02600 dbus_message_set_member (DBusMessage  *message,
02601                          const char   *member)
02602 {
02603   _dbus_return_val_if_fail (message != NULL, FALSE);
02604   _dbus_return_val_if_fail (!message->locked, FALSE);
02605   _dbus_return_val_if_fail (member == NULL ||
02606                             _dbus_check_is_valid_member (member),
02607                             FALSE);
02608 
02609   return set_or_delete_string_field (message,
02610                                      DBUS_HEADER_FIELD_MEMBER,
02611                                      DBUS_TYPE_STRING,
02612                                      member);
02613 }
02614 
02623 const char*
02624 dbus_message_get_member (DBusMessage *message)
02625 {
02626   const char *v;
02627 
02628   _dbus_return_val_if_fail (message != NULL, NULL);
02629 
02630   v = NULL; /* in case field doesn't exist */
02631   _dbus_header_get_field_basic (&message->header,
02632                                 DBUS_HEADER_FIELD_MEMBER,
02633                                 DBUS_TYPE_STRING,
02634                                 &v);
02635   return v;
02636 }
02637 
02645 dbus_bool_t
02646 dbus_message_has_member (DBusMessage   *message,
02647                          const char    *member)
02648 {
02649   const char *msg_member;
02650   msg_member = dbus_message_get_member (message);
02651  
02652   if (msg_member == NULL)
02653     {
02654       if (member == NULL)
02655         return TRUE;
02656       else
02657         return FALSE;
02658     }
02659 
02660   if (member == NULL)
02661     return FALSE;
02662     
02663   if (strcmp (msg_member, member) == 0)
02664     return TRUE;
02665 
02666   return FALSE;
02667 
02668 }
02669 
02678 dbus_bool_t
02679 dbus_message_set_error_name (DBusMessage  *message,
02680                              const char   *error_name)
02681 {
02682   _dbus_return_val_if_fail (message != NULL, FALSE);
02683   _dbus_return_val_if_fail (!message->locked, FALSE);
02684   _dbus_return_val_if_fail (error_name == NULL ||
02685                             _dbus_check_is_valid_error_name (error_name),
02686                             FALSE);
02687 
02688   return set_or_delete_string_field (message,
02689                                      DBUS_HEADER_FIELD_ERROR_NAME,
02690                                      DBUS_TYPE_STRING,
02691                                      error_name);
02692 }
02693 
02701 const char*
02702 dbus_message_get_error_name (DBusMessage *message)
02703 {
02704   const char *v;
02705 
02706   _dbus_return_val_if_fail (message != NULL, NULL);
02707 
02708   v = NULL; /* in case field doesn't exist */
02709   _dbus_header_get_field_basic (&message->header,
02710                                 DBUS_HEADER_FIELD_ERROR_NAME,
02711                                 DBUS_TYPE_STRING,
02712                                 &v);
02713   return v;
02714 }
02715 
02726 dbus_bool_t
02727 dbus_message_set_destination (DBusMessage  *message,
02728                               const char   *destination)
02729 {
02730   _dbus_return_val_if_fail (message != NULL, FALSE);
02731   _dbus_return_val_if_fail (!message->locked, FALSE);
02732   _dbus_return_val_if_fail (destination == NULL ||
02733                             _dbus_check_is_valid_bus_name (destination),
02734                             FALSE);
02735 
02736   return set_or_delete_string_field (message,
02737                                      DBUS_HEADER_FIELD_DESTINATION,
02738                                      DBUS_TYPE_STRING,
02739                                      destination);
02740 }
02741 
02748 const char*
02749 dbus_message_get_destination (DBusMessage *message)
02750 {
02751   const char *v;
02752 
02753   _dbus_return_val_if_fail (message != NULL, NULL);
02754 
02755   v = NULL; /* in case field doesn't exist */
02756   _dbus_header_get_field_basic (&message->header,
02757                                 DBUS_HEADER_FIELD_DESTINATION,
02758                                 DBUS_TYPE_STRING,
02759                                 &v);
02760   return v;
02761 }
02762 
02770 dbus_bool_t
02771 dbus_message_set_sender (DBusMessage  *message,
02772                          const char   *sender)
02773 {
02774   _dbus_return_val_if_fail (message != NULL, FALSE);
02775   _dbus_return_val_if_fail (!message->locked, FALSE);
02776   _dbus_return_val_if_fail (sender == NULL ||
02777                             _dbus_check_is_valid_bus_name (sender),
02778                             FALSE);
02779 
02780   return set_or_delete_string_field (message,
02781                                      DBUS_HEADER_FIELD_SENDER,
02782                                      DBUS_TYPE_STRING,
02783                                      sender);
02784 }
02785 
02794 const char*
02795 dbus_message_get_sender (DBusMessage *message)
02796 {
02797   const char *v;
02798 
02799   _dbus_return_val_if_fail (message != NULL, NULL);
02800 
02801   v = NULL; /* in case field doesn't exist */
02802   _dbus_header_get_field_basic (&message->header,
02803                                 DBUS_HEADER_FIELD_SENDER,
02804                                 DBUS_TYPE_STRING,
02805                                 &v);
02806   return v;
02807 }
02808 
02824 const char*
02825 dbus_message_get_signature (DBusMessage *message)
02826 {
02827   const DBusString *type_str;
02828   int type_pos;
02829 
02830   _dbus_return_val_if_fail (message != NULL, NULL);
02831 
02832   get_const_signature (&message->header, &type_str, &type_pos);
02833 
02834   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
02835 }
02836 
02837 static dbus_bool_t
02838 _dbus_message_has_type_interface_member (DBusMessage *message,
02839                                          int          type,
02840                                          const char  *interface,
02841                                          const char  *member)
02842 {
02843   const char *n;
02844 
02845   _dbus_assert (message != NULL);
02846   _dbus_assert (interface != NULL);
02847   _dbus_assert (member != NULL);
02848 
02849   if (dbus_message_get_type (message) != type)
02850     return FALSE;
02851 
02852   /* Optimize by checking the short member name first
02853    * instead of the longer interface name
02854    */
02855 
02856   n = dbus_message_get_member (message);
02857 
02858   if (n && strcmp (n, member) == 0)
02859     {
02860       n = dbus_message_get_interface (message);
02861 
02862       if (n == NULL || strcmp (n, interface) == 0)
02863         return TRUE;
02864     }
02865 
02866   return FALSE;
02867 }
02868 
02883 dbus_bool_t
02884 dbus_message_is_method_call (DBusMessage *message,
02885                              const char  *interface,
02886                              const char  *method)
02887 {
02888   _dbus_return_val_if_fail (message != NULL, FALSE);
02889   _dbus_return_val_if_fail (interface != NULL, FALSE);
02890   _dbus_return_val_if_fail (method != NULL, FALSE);
02891   /* don't check that interface/method are valid since it would be
02892    * expensive, and not catch many common errors
02893    */
02894 
02895   return _dbus_message_has_type_interface_member (message,
02896                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
02897                                                   interface, method);
02898 }
02899 
02913 dbus_bool_t
02914 dbus_message_is_signal (DBusMessage *message,
02915                         const char  *interface,
02916                         const char  *signal_name)
02917 {
02918   _dbus_return_val_if_fail (message != NULL, FALSE);
02919   _dbus_return_val_if_fail (interface != NULL, FALSE);
02920   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
02921   /* don't check that interface/name are valid since it would be
02922    * expensive, and not catch many common errors
02923    */
02924 
02925   return _dbus_message_has_type_interface_member (message,
02926                                                   DBUS_MESSAGE_TYPE_SIGNAL,
02927                                                   interface, signal_name);
02928 }
02929 
02940 dbus_bool_t
02941 dbus_message_is_error (DBusMessage *message,
02942                        const char  *error_name)
02943 {
02944   const char *n;
02945 
02946   _dbus_return_val_if_fail (message != NULL, FALSE);
02947   _dbus_return_val_if_fail (error_name != NULL, FALSE);
02948   /* don't check that error_name is valid since it would be expensive,
02949    * and not catch many common errors
02950    */
02951 
02952   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
02953     return FALSE;
02954 
02955   n = dbus_message_get_error_name (message);
02956 
02957   if (n && strcmp (n, error_name) == 0)
02958     return TRUE;
02959   else
02960     return FALSE;
02961 }
02962 
02973 dbus_bool_t
02974 dbus_message_has_destination (DBusMessage  *message,
02975                               const char   *name)
02976 {
02977   const char *s;
02978 
02979   _dbus_return_val_if_fail (message != NULL, FALSE);
02980   _dbus_return_val_if_fail (name != NULL, FALSE);
02981   /* don't check that name is valid since it would be expensive, and
02982    * not catch many common errors
02983    */
02984 
02985   s = dbus_message_get_destination (message);
02986 
02987   if (s && strcmp (s, name) == 0)
02988     return TRUE;
02989   else
02990     return FALSE;
02991 }
02992 
03008 dbus_bool_t
03009 dbus_message_has_sender (DBusMessage  *message,
03010                          const char   *name)
03011 {
03012   const char *s;
03013 
03014   _dbus_return_val_if_fail (message != NULL, FALSE);
03015   _dbus_return_val_if_fail (name != NULL, FALSE);
03016   /* don't check that name is valid since it would be expensive, and
03017    * not catch many common errors
03018    */
03019 
03020   s = dbus_message_get_sender (message);
03021 
03022   if (s && strcmp (s, name) == 0)
03023     return TRUE;
03024   else
03025     return FALSE;
03026 }
03027 
03037 dbus_bool_t
03038 dbus_message_has_signature (DBusMessage   *message,
03039                             const char    *signature)
03040 {
03041   const char *s;
03042 
03043   _dbus_return_val_if_fail (message != NULL, FALSE);
03044   _dbus_return_val_if_fail (signature != NULL, FALSE);
03045   /* don't check that signature is valid since it would be expensive,
03046    * and not catch many common errors
03047    */
03048 
03049   s = dbus_message_get_signature (message);
03050 
03051   if (s && strcmp (s, signature) == 0)
03052     return TRUE;
03053   else
03054     return FALSE;
03055 }
03056 
03079 dbus_bool_t
03080 dbus_set_error_from_message (DBusError   *error,
03081                              DBusMessage *message)
03082 {
03083   const char *str;
03084 
03085   _dbus_return_val_if_fail (message != NULL, FALSE);
03086   _dbus_return_val_if_error_is_set (error, FALSE);
03087 
03088   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03089     return FALSE;
03090 
03091   str = NULL;
03092   dbus_message_get_args (message, NULL,
03093                          DBUS_TYPE_STRING, &str,
03094                          DBUS_TYPE_INVALID);
03095 
03096   dbus_set_error (error, dbus_message_get_error_name (message),
03097                   str ? "%s" : NULL, str);
03098 
03099   return TRUE;
03100 }
03101 
03120 #define INITIAL_LOADER_DATA_LEN 32
03121 
03128 DBusMessageLoader*
03129 _dbus_message_loader_new (void)
03130 {
03131   DBusMessageLoader *loader;
03132 
03133   loader = dbus_new0 (DBusMessageLoader, 1);
03134   if (loader == NULL)
03135     return NULL;
03136   
03137   loader->refcount = 1;
03138 
03139   loader->corrupted = FALSE;
03140   loader->corruption_reason = DBUS_VALID;
03141 
03142   /* this can be configured by the app, but defaults to the protocol max */
03143   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03144 
03145   if (!_dbus_string_init (&loader->data))
03146     {
03147       dbus_free (loader);
03148       return NULL;
03149     }
03150 
03151   /* preallocate the buffer for speed, ignore failure */
03152   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03153   _dbus_string_set_length (&loader->data, 0);
03154 
03155   return loader;
03156 }
03157 
03164 DBusMessageLoader *
03165 _dbus_message_loader_ref (DBusMessageLoader *loader)
03166 {
03167   loader->refcount += 1;
03168 
03169   return loader;
03170 }
03171 
03178 void
03179 _dbus_message_loader_unref (DBusMessageLoader *loader)
03180 {
03181   loader->refcount -= 1;
03182   if (loader->refcount == 0)
03183     {
03184       _dbus_list_foreach (&loader->messages,
03185                           (DBusForeachFunction) dbus_message_unref,
03186                           NULL);
03187       _dbus_list_clear (&loader->messages);
03188       _dbus_string_free (&loader->data);
03189       dbus_free (loader);
03190     }
03191 }
03192 
03211 void
03212 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03213                                  DBusString        **buffer)
03214 {
03215   _dbus_assert (!loader->buffer_outstanding);
03216 
03217   *buffer = &loader->data;
03218 
03219   loader->buffer_outstanding = TRUE;
03220 }
03221 
03232 void
03233 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03234                                     DBusString         *buffer,
03235                                     int                 bytes_read)
03236 {
03237   _dbus_assert (loader->buffer_outstanding);
03238   _dbus_assert (buffer == &loader->data);
03239 
03240   loader->buffer_outstanding = FALSE;
03241 }
03242 
03243 /*
03244  * FIXME when we move the header out of the buffer, that memmoves all
03245  * buffered messages. Kind of crappy.
03246  *
03247  * Also we copy the header and body, which is kind of crappy.  To
03248  * avoid this, we have to allow header and body to be in a single
03249  * memory block, which is good for messages we read and bad for
03250  * messages we are creating. But we could move_len() the buffer into
03251  * this single memory block, and move_len() will just swap the buffers
03252  * if you're moving the entire buffer replacing the dest string.
03253  *
03254  * We could also have the message loader tell the transport how many
03255  * bytes to read; so it would first ask for some arbitrary number like
03256  * 256, then if the message was incomplete it would use the
03257  * header/body len to ask for exactly the size of the message (or
03258  * blocks the size of a typical kernel buffer for the socket). That
03259  * way we don't get trailing bytes in the buffer that have to be
03260  * memmoved. Though I suppose we also don't have a chance of reading a
03261  * bunch of small messages at once, so the optimization may be stupid.
03262  *
03263  * Another approach would be to keep a "start" index into
03264  * loader->data and only delete it occasionally, instead of after
03265  * each message is loaded.
03266  *
03267  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03268  */
03269 static dbus_bool_t
03270 load_message (DBusMessageLoader *loader,
03271               DBusMessage       *message,
03272               int                byte_order,
03273               int                fields_array_len,
03274               int                header_len,
03275               int                body_len)
03276 {
03277   dbus_bool_t oom;
03278   DBusValidity validity;
03279   const DBusString *type_str;
03280   int type_pos;
03281   DBusValidationMode mode;
03282 
03283   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03284   
03285   oom = FALSE;
03286 
03287 #if 0
03288   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03289 #endif
03290 
03291   /* 1. VALIDATE AND COPY OVER HEADER */
03292   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03293   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03294 
03295   if (!_dbus_header_load (&message->header,
03296                           mode,
03297                           &validity,
03298                           byte_order,
03299                           fields_array_len,
03300                           header_len,
03301                           body_len,
03302                           &loader->data, 0,
03303                           _dbus_string_get_length (&loader->data)))
03304     {
03305       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03306 
03307       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03308          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03309       _dbus_assert (validity != DBUS_VALID);
03310 
03311       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03312         oom = TRUE;
03313       else
03314         {
03315           loader->corrupted = TRUE;
03316           loader->corruption_reason = validity;
03317         }
03318       goto failed;
03319     }
03320 
03321   _dbus_assert (validity == DBUS_VALID);
03322 
03323   message->byte_order = byte_order;
03324 
03325   /* 2. VALIDATE BODY */
03326   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
03327     {
03328       get_const_signature (&message->header, &type_str, &type_pos);
03329       
03330       /* Because the bytes_remaining arg is NULL, this validates that the
03331        * body is the right length
03332        */
03333       validity = _dbus_validate_body_with_reason (type_str,
03334                                                   type_pos,
03335                                                   byte_order,
03336                                                   NULL,
03337                                                   &loader->data,
03338                                                   header_len,
03339                                                   body_len);
03340       if (validity != DBUS_VALID)
03341         {
03342           _dbus_verbose ("Failed to validate message body code %d\n", validity);
03343 
03344           loader->corrupted = TRUE;
03345           loader->corruption_reason = validity;
03346           
03347           goto failed;
03348         }
03349     }
03350 
03351   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
03352 
03353   if (!_dbus_list_append (&loader->messages, message))
03354     {
03355       _dbus_verbose ("Failed to append new message to loader queue\n");
03356       oom = TRUE;
03357       goto failed;
03358     }
03359 
03360   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
03361   _dbus_assert (_dbus_string_get_length (&loader->data) >=
03362                 (header_len + body_len));
03363 
03364   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
03365     {
03366       _dbus_verbose ("Failed to move body into new message\n");
03367       oom = TRUE;
03368       goto failed;
03369     }
03370 
03371   _dbus_string_delete (&loader->data, 0, header_len + body_len);
03372 
03373   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
03374   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
03375 
03376   _dbus_verbose ("Loaded message %p\n", message);
03377 
03378   _dbus_assert (!oom);
03379   _dbus_assert (!loader->corrupted);
03380   _dbus_assert (loader->messages != NULL);
03381   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03382 
03383   return TRUE;
03384 
03385  failed:
03386 
03387   /* Clean up */
03388 
03389   /* does nothing if the message isn't in the list */
03390   _dbus_list_remove_last (&loader->messages, message);
03391   
03392   if (oom)
03393     _dbus_assert (!loader->corrupted);
03394   else
03395     _dbus_assert (loader->corrupted);
03396 
03397   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
03398 
03399   return FALSE;
03400 }
03401 
03416 dbus_bool_t
03417 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
03418 {
03419   while (!loader->corrupted &&
03420          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
03421     {
03422       DBusValidity validity;
03423       int byte_order, fields_array_len, header_len, body_len;
03424 
03425       if (_dbus_header_have_message_untrusted (loader->max_message_size,
03426                                                &validity,
03427                                                &byte_order,
03428                                                &fields_array_len,
03429                                                &header_len,
03430                                                &body_len,
03431                                                &loader->data, 0,
03432                                                _dbus_string_get_length (&loader->data)))
03433         {
03434           DBusMessage *message;
03435 
03436           _dbus_assert (validity == DBUS_VALID);
03437 
03438           message = dbus_message_new_empty_header ();
03439           if (message == NULL)
03440             return FALSE;
03441 
03442           if (!load_message (loader, message,
03443                              byte_order, fields_array_len,
03444                              header_len, body_len))
03445             {
03446               dbus_message_unref (message);
03447               /* load_message() returns false if corrupted or OOM; if
03448                * corrupted then return TRUE for not OOM
03449                */
03450               return loader->corrupted;
03451             }
03452 
03453           _dbus_assert (loader->messages != NULL);
03454           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03455         }
03456       else
03457         {
03458           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
03459                          validity);
03460           if (validity != DBUS_VALID)
03461             {
03462               loader->corrupted = TRUE;
03463               loader->corruption_reason = validity;
03464             }
03465           return TRUE;
03466         }
03467     }
03468 
03469   return TRUE;
03470 }
03471 
03479 DBusMessage*
03480 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
03481 {
03482   if (loader->messages)
03483     return loader->messages->data;
03484   else
03485     return NULL;
03486 }
03487 
03496 DBusMessage*
03497 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
03498 {
03499   return _dbus_list_pop_first (&loader->messages);
03500 }
03501 
03510 DBusList*
03511 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
03512 {
03513   return _dbus_list_pop_first_link (&loader->messages);
03514 }
03515 
03522 void
03523 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
03524                                            DBusList           *link)
03525 {
03526   _dbus_list_prepend_link (&loader->messages, link);
03527 }
03528 
03538 dbus_bool_t
03539 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
03540 {
03541   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
03542                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
03543   return loader->corrupted;
03544 }
03545 
03552 void
03553 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
03554                                            long                size)
03555 {
03556   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
03557     {
03558       _dbus_verbose ("clamping requested max message size %ld to %d\n",
03559                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
03560       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03561     }
03562   loader->max_message_size = size;
03563 }
03564 
03571 long
03572 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
03573 {
03574   return loader->max_message_size;
03575 }
03576 
03577 static DBusDataSlotAllocator slot_allocator;
03578 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
03579 
03594 dbus_bool_t
03595 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
03596 {
03597   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03598                                           &_DBUS_LOCK_NAME (message_slots),
03599                                           slot_p);
03600 }
03601 
03613 void
03614 dbus_message_free_data_slot (dbus_int32_t *slot_p)
03615 {
03616   _dbus_return_if_fail (*slot_p >= 0);
03617 
03618   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03619 }
03620 
03634 dbus_bool_t
03635 dbus_message_set_data (DBusMessage     *message,
03636                        dbus_int32_t     slot,
03637                        void            *data,
03638                        DBusFreeFunction free_data_func)
03639 {
03640   DBusFreeFunction old_free_func;
03641   void *old_data;
03642   dbus_bool_t retval;
03643 
03644   _dbus_return_val_if_fail (message != NULL, FALSE);
03645   _dbus_return_val_if_fail (slot >= 0, FALSE);
03646 
03647   retval = _dbus_data_slot_list_set (&slot_allocator,
03648                                      &message->slot_list,
03649                                      slot, data, free_data_func,
03650                                      &old_free_func, &old_data);
03651 
03652   if (retval)
03653     {
03654       /* Do the actual free outside the message lock */
03655       if (old_free_func)
03656         (* old_free_func) (old_data);
03657     }
03658 
03659   return retval;
03660 }
03661 
03670 void*
03671 dbus_message_get_data (DBusMessage   *message,
03672                        dbus_int32_t   slot)
03673 {
03674   void *res;
03675 
03676   _dbus_return_val_if_fail (message != NULL, NULL);
03677 
03678   res = _dbus_data_slot_list_get (&slot_allocator,
03679                                   &message->slot_list,
03680                                   slot);
03681 
03682   return res;
03683 }
03684 
03698 int
03699 dbus_message_type_from_string (const char *type_str)
03700 {
03701   if (strcmp (type_str, "method_call") == 0)
03702     return DBUS_MESSAGE_TYPE_METHOD_CALL;
03703   if (strcmp (type_str, "method_return") == 0)
03704     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
03705   else if (strcmp (type_str, "signal") == 0)
03706     return DBUS_MESSAGE_TYPE_SIGNAL;
03707   else if (strcmp (type_str, "error") == 0)
03708     return DBUS_MESSAGE_TYPE_ERROR;
03709   else
03710     return DBUS_MESSAGE_TYPE_INVALID;
03711 }
03712 
03726 const char *
03727 dbus_message_type_to_string (int type)
03728 {
03729   switch (type)
03730     {
03731     case DBUS_MESSAGE_TYPE_METHOD_CALL:
03732       return "method_call";
03733     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
03734       return "method_return";
03735     case DBUS_MESSAGE_TYPE_SIGNAL:
03736       return "signal";
03737     case DBUS_MESSAGE_TYPE_ERROR:
03738       return "error";
03739     default:
03740       return "invalid";
03741     }
03742 }
03743 
03746 /* tests in dbus-message-util.c */

Generated on Wed Jan 3 04:58:28 2007 for D-Bus by  doxygen 1.4.7