Main Page | Modules | Namespace List | Class Hierarchy | Data Structures | Directories | File List | Namespace Members | 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 
00406   return _dbus_header_set_field_basic (&message->header,
00407                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
00408                                        DBUS_TYPE_UINT32,
00409                                        &reply_serial);
00410 }
00411 
00418 dbus_uint32_t
00419 dbus_message_get_reply_serial  (DBusMessage *message)
00420 {
00421   dbus_uint32_t v_UINT32;
00422 
00423   _dbus_return_val_if_fail (message != NULL, 0);
00424 
00425   if (_dbus_header_get_field_basic (&message->header,
00426                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
00427                                     DBUS_TYPE_UINT32,
00428                                     &v_UINT32))
00429     return v_UINT32;
00430   else
00431     return 0;
00432 }
00433 
00434 static void
00435 free_size_counter (void *element,
00436                    void *data)
00437 {
00438   DBusCounter *counter = element;
00439   DBusMessage *message = data;
00440 
00441   _dbus_counter_adjust (counter, - message->size_counter_delta);
00442 
00443   _dbus_counter_unref (counter);
00444 }
00445 
00446 static void
00447 dbus_message_finalize (DBusMessage *message)
00448 {
00449   _dbus_assert (message->refcount.value == 0);
00450 
00451   /* This calls application callbacks! */
00452   _dbus_data_slot_list_free (&message->slot_list);
00453 
00454   _dbus_list_foreach (&message->size_counters,
00455                       free_size_counter, message);
00456   _dbus_list_clear (&message->size_counters);
00457 
00458   _dbus_header_free (&message->header);
00459   _dbus_string_free (&message->body);
00460 
00461   _dbus_assert (message->refcount.value == 0);
00462   
00463   dbus_free (message);
00464 }
00465 
00466 /* Message Cache
00467  *
00468  * We cache some DBusMessage to reduce the overhead of allocating
00469  * them.  In my profiling this consistently made about an 8%
00470  * difference.  It avoids the malloc for the message, the malloc for
00471  * the slot list, the malloc for the header string and body string,
00472  * and the associated free() calls. It does introduce another global
00473  * lock which could be a performance issue in certain cases.
00474  *
00475  * For the echo client/server the round trip time goes from around
00476  * .000077 to .000069 with the message cache on my laptop. The sysprof
00477  * change is as follows (numbers are cumulative percentage):
00478  *
00479  *  with message cache implemented as array as it is now (0.000069 per):
00480  *    new_empty_header           1.46
00481  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00482  *      mutex_unlock             0.25
00483  *      self                     0.41
00484  *    unref                      2.24
00485  *      self                     0.68
00486  *      list_clear               0.43
00487  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00488  *      mutex_unlock             0.25
00489  *
00490  *  with message cache implemented as list (0.000070 per roundtrip):
00491  *    new_empty_header           2.72
00492  *      list_pop_first           1.88
00493  *    unref                      3.3
00494  *      list_prepend             1.63
00495  *
00496  * without cache (0.000077 per roundtrip):
00497  *    new_empty_header           6.7
00498  *      string_init_preallocated 3.43
00499  *        dbus_malloc            2.43
00500  *      dbus_malloc0             2.59
00501  *
00502  *    unref                      4.02
00503  *      string_free              1.82
00504  *        dbus_free              1.63
00505  *      dbus_free                0.71
00506  *
00507  * If you implement the message_cache with a list, the primary reason
00508  * it's slower is that you add another thread lock (on the DBusList
00509  * mempool).
00510  */
00511 
00513 #define MAX_MESSAGE_SIZE_TO_CACHE _DBUS_ONE_MEGABYTE
00514 
00516 #define MAX_MESSAGE_CACHE_SIZE    5
00517 
00518 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00519 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00520 static int message_cache_count = 0;
00521 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00522 
00523 static void
00524 dbus_message_cache_shutdown (void *data)
00525 {
00526   int i;
00527 
00528   _DBUS_LOCK (message_cache);
00529 
00530   i = 0;
00531   while (i < MAX_MESSAGE_CACHE_SIZE)
00532     {
00533       if (message_cache[i])
00534         dbus_message_finalize (message_cache[i]);
00535 
00536       ++i;
00537     }
00538 
00539   message_cache_count = 0;
00540   message_cache_shutdown_registered = FALSE;
00541 
00542   _DBUS_UNLOCK (message_cache);
00543 }
00544 
00552 static DBusMessage*
00553 dbus_message_get_cached (void)
00554 {
00555   DBusMessage *message;
00556   int i;
00557 
00558   message = NULL;
00559 
00560   _DBUS_LOCK (message_cache);
00561 
00562   _dbus_assert (message_cache_count >= 0);
00563 
00564   if (message_cache_count == 0)
00565     {
00566       _DBUS_UNLOCK (message_cache);
00567       return NULL;
00568     }
00569 
00570   /* This is not necessarily true unless count > 0, and
00571    * message_cache is uninitialized until the shutdown is
00572    * registered
00573    */
00574   _dbus_assert (message_cache_shutdown_registered);
00575 
00576   i = 0;
00577   while (i < MAX_MESSAGE_CACHE_SIZE)
00578     {
00579       if (message_cache[i])
00580         {
00581           message = message_cache[i];
00582           message_cache[i] = NULL;
00583           message_cache_count -= 1;
00584           break;
00585         }
00586       ++i;
00587     }
00588   _dbus_assert (message_cache_count >= 0);
00589   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00590   _dbus_assert (message != NULL);
00591 
00592   _DBUS_UNLOCK (message_cache);
00593 
00594   _dbus_assert (message->refcount.value == 0);
00595   _dbus_assert (message->size_counters == NULL);
00596 
00597   return message;
00598 }
00599 
00605 static void
00606 dbus_message_cache_or_finalize (DBusMessage *message)
00607 {
00608   dbus_bool_t was_cached;
00609   int i;
00610   
00611   _dbus_assert (message->refcount.value == 0);
00612 
00613   /* This calls application code and has to be done first thing
00614    * without holding the lock
00615    */
00616   _dbus_data_slot_list_clear (&message->slot_list);
00617 
00618   _dbus_list_foreach (&message->size_counters,
00619                       free_size_counter, message);
00620   _dbus_list_clear (&message->size_counters);
00621 
00622   was_cached = FALSE;
00623 
00624   _DBUS_LOCK (message_cache);
00625 
00626   if (!message_cache_shutdown_registered)
00627     {
00628       _dbus_assert (message_cache_count == 0);
00629 
00630       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00631         goto out;
00632 
00633       i = 0;
00634       while (i < MAX_MESSAGE_CACHE_SIZE)
00635         {
00636           message_cache[i] = NULL;
00637           ++i;
00638         }
00639 
00640       message_cache_shutdown_registered = TRUE;
00641     }
00642 
00643   _dbus_assert (message_cache_count >= 0);
00644 
00645   if ((_dbus_string_get_length (&message->header.data) +
00646        _dbus_string_get_length (&message->body)) >
00647       MAX_MESSAGE_SIZE_TO_CACHE)
00648     goto out;
00649 
00650   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00651     goto out;
00652 
00653   /* Find empty slot */
00654   i = 0;
00655   while (message_cache[i] != NULL)
00656     ++i;
00657 
00658   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00659 
00660   _dbus_assert (message_cache[i] == NULL);
00661   message_cache[i] = message;
00662   message_cache_count += 1;
00663   was_cached = TRUE;
00664 #ifndef DBUS_DISABLE_CHECKS
00665   message->in_cache = TRUE;
00666 #endif
00667 
00668  out:
00669   _DBUS_UNLOCK (message_cache);
00670 
00671   _dbus_assert (message->refcount.value == 0);
00672   
00673   if (!was_cached)
00674     dbus_message_finalize (message);
00675 }
00676 
00677 static DBusMessage*
00678 dbus_message_new_empty_header (void)
00679 {
00680   DBusMessage *message;
00681   dbus_bool_t from_cache;
00682 
00683   message = dbus_message_get_cached ();
00684 
00685   if (message != NULL)
00686     {
00687       from_cache = TRUE;
00688     }
00689   else
00690     {
00691       from_cache = FALSE;
00692       message = dbus_new (DBusMessage, 1);
00693       if (message == NULL)
00694         return NULL;
00695 #ifndef DBUS_DISABLE_CHECKS
00696       message->generation = _dbus_current_generation;
00697 #endif
00698     }
00699   
00700   message->refcount.value = 1;
00701   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
00702   message->locked = FALSE;
00703 #ifndef DBUS_DISABLE_CHECKS
00704   message->in_cache = FALSE;
00705 #endif
00706   message->size_counters = NULL;
00707   message->size_counter_delta = 0;
00708   message->changed_stamp = 0;
00709 
00710   if (!from_cache)
00711     _dbus_data_slot_list_init (&message->slot_list);
00712 
00713   if (from_cache)
00714     {
00715       _dbus_header_reinit (&message->header, message->byte_order);
00716       _dbus_string_set_length (&message->body, 0);
00717     }
00718   else
00719     {
00720       if (!_dbus_header_init (&message->header, message->byte_order))
00721         {
00722           dbus_free (message);
00723           return NULL;
00724         }
00725 
00726       if (!_dbus_string_init_preallocated (&message->body, 32))
00727         {
00728           _dbus_header_free (&message->header);
00729           dbus_free (message);
00730           return NULL;
00731         }
00732     }
00733 
00734   return message;
00735 }
00736 
00745 DBusMessage*
00746 dbus_message_new (int message_type)
00747 {
00748   DBusMessage *message;
00749 
00750   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
00751 
00752   message = dbus_message_new_empty_header ();
00753   if (message == NULL)
00754     return NULL;
00755 
00756   if (!_dbus_header_create (&message->header,
00757                             message_type,
00758                             NULL, NULL, NULL, NULL, NULL))
00759     {
00760       dbus_message_unref (message);
00761       return NULL;
00762     }
00763 
00764   return message;
00765 }
00766 
00784 DBusMessage*
00785 dbus_message_new_method_call (const char *destination,
00786                               const char *path,
00787                               const char *interface,
00788                               const char *method)
00789 {
00790   DBusMessage *message;
00791 
00792   _dbus_return_val_if_fail (path != NULL, NULL);
00793   _dbus_return_val_if_fail (method != NULL, NULL);
00794   _dbus_return_val_if_fail (destination == NULL ||
00795                             _dbus_check_is_valid_bus_name (destination), NULL);
00796   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
00797   _dbus_return_val_if_fail (interface == NULL ||
00798                             _dbus_check_is_valid_interface (interface), NULL);
00799   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
00800 
00801   message = dbus_message_new_empty_header ();
00802   if (message == NULL)
00803     return NULL;
00804 
00805   if (!_dbus_header_create (&message->header,
00806                             DBUS_MESSAGE_TYPE_METHOD_CALL,
00807                             destination, path, interface, method, NULL))
00808     {
00809       dbus_message_unref (message);
00810       return NULL;
00811     }
00812 
00813   return message;
00814 }
00815 
00825 DBusMessage*
00826 dbus_message_new_method_return (DBusMessage *method_call)
00827 {
00828   DBusMessage *message;
00829   const char *sender;
00830 
00831   _dbus_return_val_if_fail (method_call != NULL, NULL);
00832 
00833   sender = dbus_message_get_sender (method_call);
00834 
00835   /* sender is allowed to be null here in peer-to-peer case */
00836 
00837   message = dbus_message_new_empty_header ();
00838   if (message == NULL)
00839     return NULL;
00840 
00841   if (!_dbus_header_create (&message->header,
00842                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
00843                             sender, NULL, NULL, NULL, NULL))
00844     {
00845       dbus_message_unref (message);
00846       return NULL;
00847     }
00848 
00849   dbus_message_set_no_reply (message, TRUE);
00850 
00851   if (!dbus_message_set_reply_serial (message,
00852                                       dbus_message_get_serial (method_call)))
00853     {
00854       dbus_message_unref (message);
00855       return NULL;
00856     }
00857 
00858   return message;
00859 }
00860 
00873 DBusMessage*
00874 dbus_message_new_signal (const char *path,
00875                          const char *interface,
00876                          const char *name)
00877 {
00878   DBusMessage *message;
00879 
00880   _dbus_return_val_if_fail (path != NULL, NULL);
00881   _dbus_return_val_if_fail (interface != NULL, NULL);
00882   _dbus_return_val_if_fail (name != NULL, NULL);
00883   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
00884   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
00885   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
00886 
00887   message = dbus_message_new_empty_header ();
00888   if (message == NULL)
00889     return NULL;
00890 
00891   if (!_dbus_header_create (&message->header,
00892                             DBUS_MESSAGE_TYPE_SIGNAL,
00893                             NULL, path, interface, name, NULL))
00894     {
00895       dbus_message_unref (message);
00896       return NULL;
00897     }
00898 
00899   dbus_message_set_no_reply (message, TRUE);
00900 
00901   return message;
00902 }
00903 
00913 DBusMessage*
00914 dbus_message_new_error (DBusMessage *reply_to,
00915                         const char  *error_name,
00916                         const char  *error_message)
00917 {
00918   DBusMessage *message;
00919   const char *sender;
00920   DBusMessageIter iter;
00921 
00922   _dbus_return_val_if_fail (reply_to != NULL, NULL);
00923   _dbus_return_val_if_fail (error_name != NULL, NULL);
00924   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
00925 
00926   sender = dbus_message_get_sender (reply_to);
00927 
00928   /* sender may be NULL for non-message-bus case or
00929    * when the message bus is dealing with an unregistered
00930    * connection.
00931    */
00932   message = dbus_message_new_empty_header ();
00933   if (message == NULL)
00934     return NULL;
00935 
00936   if (!_dbus_header_create (&message->header,
00937                             DBUS_MESSAGE_TYPE_ERROR,
00938                             sender, NULL, NULL, NULL, error_name))
00939     {
00940       dbus_message_unref (message);
00941       return NULL;
00942     }
00943 
00944   dbus_message_set_no_reply (message, TRUE);
00945 
00946   if (!dbus_message_set_reply_serial (message,
00947                                       dbus_message_get_serial (reply_to)))
00948     {
00949       dbus_message_unref (message);
00950       return NULL;
00951     }
00952 
00953   if (error_message != NULL)
00954     {
00955       dbus_message_iter_init_append (message, &iter);
00956       if (!dbus_message_iter_append_basic (&iter,
00957                                            DBUS_TYPE_STRING,
00958                                            &error_message))
00959         {
00960           dbus_message_unref (message);
00961           return NULL;
00962         }
00963     }
00964 
00965   return message;
00966 }
00967 
00978 DBusMessage*
00979 dbus_message_new_error_printf (DBusMessage *reply_to,
00980                                const char  *error_name,
00981                                const char  *error_format,
00982                                ...)
00983 {
00984   va_list args;
00985   DBusString str;
00986   DBusMessage *message;
00987 
00988   _dbus_return_val_if_fail (reply_to != NULL, NULL);
00989   _dbus_return_val_if_fail (error_name != NULL, NULL);
00990   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
00991 
00992   if (!_dbus_string_init (&str))
00993     return NULL;
00994 
00995   va_start (args, error_format);
00996 
00997   if (_dbus_string_append_printf_valist (&str, error_format, args))
00998     message = dbus_message_new_error (reply_to, error_name,
00999                                       _dbus_string_get_const_data (&str));
01000   else
01001     message = NULL;
01002 
01003   _dbus_string_free (&str);
01004 
01005   va_end (args);
01006 
01007   return message;
01008 }
01009 
01010 
01021 DBusMessage *
01022 dbus_message_copy (const DBusMessage *message)
01023 {
01024   DBusMessage *retval;
01025 
01026   _dbus_return_val_if_fail (message != NULL, NULL);
01027 
01028   retval = dbus_new0 (DBusMessage, 1);
01029   if (retval == NULL)
01030     return NULL;
01031 
01032   retval->refcount.value = 1;
01033   retval->byte_order = message->byte_order;
01034   retval->locked = FALSE;
01035 #ifndef DBUS_DISABLE_CHECKS
01036   retval->generation = message->generation;
01037 #endif
01038 
01039   if (!_dbus_header_copy (&message->header, &retval->header))
01040     {
01041       dbus_free (retval);
01042       return NULL;
01043     }
01044 
01045   if (!_dbus_string_init_preallocated (&retval->body,
01046                                        _dbus_string_get_length (&message->body)))
01047     {
01048       _dbus_header_free (&retval->header);
01049       dbus_free (retval);
01050       return NULL;
01051     }
01052 
01053   if (!_dbus_string_copy (&message->body, 0,
01054                           &retval->body, 0))
01055     goto failed_copy;
01056 
01057   return retval;
01058 
01059  failed_copy:
01060   _dbus_header_free (&retval->header);
01061   _dbus_string_free (&retval->body);
01062   dbus_free (retval);
01063 
01064   return NULL;
01065 }
01066 
01067 
01075 DBusMessage *
01076 dbus_message_ref (DBusMessage *message)
01077 {
01078   dbus_int32_t old_refcount;
01079 
01080   _dbus_return_val_if_fail (message != NULL, NULL);
01081   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01082   _dbus_return_val_if_fail (!message->in_cache, NULL);
01083   
01084   old_refcount = _dbus_atomic_inc (&message->refcount);
01085   _dbus_assert (old_refcount >= 1);
01086 
01087   return message;
01088 }
01089 
01096 void
01097 dbus_message_unref (DBusMessage *message)
01098 {
01099  dbus_int32_t old_refcount;
01100 
01101   _dbus_return_if_fail (message != NULL);
01102   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01103   _dbus_return_if_fail (!message->in_cache);
01104 
01105   old_refcount = _dbus_atomic_dec (&message->refcount);
01106 
01107   _dbus_assert (old_refcount >= 0);
01108 
01109   if (old_refcount == 1)
01110     {
01111       /* Calls application callbacks! */
01112       dbus_message_cache_or_finalize (message);
01113     }
01114 }
01115 
01128 int
01129 dbus_message_get_type (DBusMessage *message)
01130 {
01131   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01132 
01133   return _dbus_header_get_message_type (&message->header);
01134 }
01135 
01188 dbus_bool_t
01189 dbus_message_append_args (DBusMessage *message,
01190                           int          first_arg_type,
01191                           ...)
01192 {
01193   dbus_bool_t retval;
01194   va_list var_args;
01195 
01196   _dbus_return_val_if_fail (message != NULL, FALSE);
01197 
01198   va_start (var_args, first_arg_type);
01199   retval = dbus_message_append_args_valist (message,
01200                                             first_arg_type,
01201                                             var_args);
01202   va_end (var_args);
01203 
01204   return retval;
01205 }
01206 
01221 dbus_bool_t
01222 dbus_message_append_args_valist (DBusMessage *message,
01223                                  int          first_arg_type,
01224                                  va_list      var_args)
01225 {
01226   int type;
01227   DBusMessageIter iter;
01228 
01229   _dbus_return_val_if_fail (message != NULL, FALSE);
01230 
01231   type = first_arg_type;
01232 
01233   dbus_message_iter_init_append (message, &iter);
01234 
01235   while (type != DBUS_TYPE_INVALID)
01236     {
01237       if (dbus_type_is_basic (type))
01238         {
01239           const DBusBasicValue *value;
01240           value = va_arg (var_args, const DBusBasicValue*);
01241 
01242           if (!dbus_message_iter_append_basic (&iter,
01243                                                type,
01244                                                value))
01245             goto failed;
01246         }
01247       else if (type == DBUS_TYPE_ARRAY)
01248         {
01249           int element_type;
01250           DBusMessageIter array;
01251           char buf[2];
01252 
01253           element_type = va_arg (var_args, int);
01254               
01255           buf[0] = element_type;
01256           buf[1] = '\0';
01257           if (!dbus_message_iter_open_container (&iter,
01258                                                  DBUS_TYPE_ARRAY,
01259                                                  buf,
01260                                                  &array))
01261             goto failed;
01262           
01263           if (dbus_type_is_fixed (element_type))
01264             {
01265               const DBusBasicValue **value;
01266               int n_elements;
01267 
01268               value = va_arg (var_args, const DBusBasicValue**);
01269               n_elements = va_arg (var_args, int);
01270               
01271               if (!dbus_message_iter_append_fixed_array (&array,
01272                                                          element_type,
01273                                                          value,
01274                                                          n_elements))
01275                 goto failed;
01276             }
01277           else if (element_type == DBUS_TYPE_STRING ||
01278                    element_type == DBUS_TYPE_SIGNATURE ||
01279                    element_type == DBUS_TYPE_OBJECT_PATH)
01280             {
01281               const char ***value_p;
01282               const char **value;
01283               int n_elements;
01284               int i;
01285               
01286               value_p = va_arg (var_args, const char***);
01287               n_elements = va_arg (var_args, int);
01288 
01289               value = *value_p;
01290               
01291               i = 0;
01292               while (i < n_elements)
01293                 {
01294                   if (!dbus_message_iter_append_basic (&array,
01295                                                        element_type,
01296                                                        &value[i]))
01297                     goto failed;
01298                   ++i;
01299                 }
01300             }
01301           else
01302             {
01303               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01304                           _dbus_type_to_string (element_type),
01305                           _DBUS_FUNCTION_NAME);
01306               goto failed;
01307             }
01308 
01309           if (!dbus_message_iter_close_container (&iter, &array))
01310             goto failed;
01311         }
01312 #ifndef DBUS_DISABLE_CHECKS
01313       else
01314         {
01315           _dbus_warn ("type %s isn't supported yet in %s\n",
01316                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01317           goto failed;
01318         }
01319 #endif
01320 
01321       type = va_arg (var_args, int);
01322     }
01323 
01324   return TRUE;
01325 
01326  failed:
01327   return FALSE;
01328 }
01329 
01362 dbus_bool_t
01363 dbus_message_get_args (DBusMessage     *message,
01364                        DBusError       *error,
01365                        int              first_arg_type,
01366                        ...)
01367 {
01368   dbus_bool_t retval;
01369   va_list var_args;
01370 
01371   _dbus_return_val_if_fail (message != NULL, FALSE);
01372   _dbus_return_val_if_error_is_set (error, FALSE);
01373 
01374   va_start (var_args, first_arg_type);
01375   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01376   va_end (var_args);
01377 
01378   return retval;
01379 }
01380 
01392 dbus_bool_t
01393 dbus_message_get_args_valist (DBusMessage     *message,
01394                               DBusError       *error,
01395                               int              first_arg_type,
01396                               va_list          var_args)
01397 {
01398   DBusMessageIter iter;
01399 
01400   _dbus_return_val_if_fail (message != NULL, FALSE);
01401   _dbus_return_val_if_error_is_set (error, FALSE);
01402 
01403   dbus_message_iter_init (message, &iter);
01404   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01405 }
01406 
01407 static void
01408 _dbus_message_iter_init_common (DBusMessage         *message,
01409                                 DBusMessageRealIter *real,
01410                                 int                  iter_type)
01411 {
01412   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01413 
01414   /* Since the iterator will read or write who-knows-what from the
01415    * message, we need to get in the right byte order
01416    */
01417   ensure_byte_order (message);
01418   
01419   real->message = message;
01420   real->changed_stamp = message->changed_stamp;
01421   real->iter_type = iter_type;
01422   real->sig_refcount = 0;
01423 }
01424 
01433 dbus_bool_t
01434 dbus_message_iter_init (DBusMessage     *message,
01435                         DBusMessageIter *iter)
01436 {
01437   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01438   const DBusString *type_str;
01439   int type_pos;
01440 
01441   _dbus_return_val_if_fail (message != NULL, FALSE);
01442   _dbus_return_val_if_fail (iter != NULL, FALSE);
01443 
01444   get_const_signature (&message->header, &type_str, &type_pos);
01445 
01446   _dbus_message_iter_init_common (message, real,
01447                                   DBUS_MESSAGE_ITER_TYPE_READER);
01448 
01449   _dbus_type_reader_init (&real->u.reader,
01450                           message->byte_order,
01451                           type_str, type_pos,
01452                           &message->body,
01453                           0);
01454 
01455   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
01456 }
01457 
01458 #ifndef DBUS_DISABLE_CHECKS
01459 static dbus_bool_t
01460 _dbus_message_iter_check (DBusMessageRealIter *iter)
01461 {
01462   if (iter == NULL)
01463     {
01464       _dbus_warn ("dbus message iterator is NULL\n");
01465       return FALSE;
01466     }
01467 
01468   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
01469     {
01470       if (iter->u.reader.byte_order != iter->message->byte_order)
01471         {
01472           _dbus_warn ("dbus message changed byte order since iterator was created\n");
01473           return FALSE;
01474         }
01475       /* because we swap the message into compiler order when you init an iter */
01476       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
01477     }
01478   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
01479     {
01480       if (iter->u.writer.byte_order != iter->message->byte_order)
01481         {
01482           _dbus_warn ("dbus message changed byte order since append iterator was created\n");
01483           return FALSE;
01484         }
01485       /* because we swap the message into compiler order when you init an iter */
01486       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
01487     }
01488   else
01489     {
01490       _dbus_warn ("dbus message iterator looks uninitialized or corrupted\n");
01491       return FALSE;
01492     }
01493 
01494   if (iter->changed_stamp != iter->message->changed_stamp)
01495     {
01496       _dbus_warn ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
01497       return FALSE;
01498     }
01499 
01500   return TRUE;
01501 }
01502 #endif /* DBUS_DISABLE_CHECKS */
01503 
01511 dbus_bool_t
01512 dbus_message_iter_has_next (DBusMessageIter *iter)
01513 {
01514   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01515 
01516   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01517   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01518 
01519   return _dbus_type_reader_has_next (&real->u.reader);
01520 }
01521 
01530 dbus_bool_t
01531 dbus_message_iter_next (DBusMessageIter *iter)
01532 {
01533   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01534 
01535   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
01536   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01537 
01538   return _dbus_type_reader_next (&real->u.reader);
01539 }
01540 
01555 int
01556 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
01557 {
01558   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01559 
01560   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01561   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
01562 
01563   return _dbus_type_reader_get_current_type (&real->u.reader);
01564 }
01565 
01574 int
01575 dbus_message_iter_get_element_type (DBusMessageIter *iter)
01576 {
01577   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01578 
01579   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
01580   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
01581   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
01582 
01583   return _dbus_type_reader_get_element_type (&real->u.reader);
01584 }
01585 
01601 void
01602 dbus_message_iter_recurse (DBusMessageIter  *iter,
01603                            DBusMessageIter  *sub)
01604 {
01605   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01606   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
01607 
01608   _dbus_return_if_fail (_dbus_message_iter_check (real));
01609   _dbus_return_if_fail (sub != NULL);
01610 
01611   *real_sub = *real;
01612   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
01613 }
01614 
01624 char *
01625 dbus_message_iter_get_signature (DBusMessageIter *iter)
01626 {
01627   const DBusString *sig;
01628   DBusString retstr;
01629   char *ret;
01630   int start, len;
01631   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01632 
01633   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
01634 
01635   if (!_dbus_string_init (&retstr))
01636     return NULL;
01637 
01638   _dbus_type_reader_get_signature (&real->u.reader, &sig,
01639                                    &start, &len);
01640   if (!_dbus_string_append_len (&retstr,
01641                                 _dbus_string_get_const_data (sig) + start,
01642                                 len))
01643     return NULL;
01644   if (!_dbus_string_steal_data (&retstr, &ret))
01645     return NULL;
01646   _dbus_string_free (&retstr);
01647   return ret;
01648 }
01649 
01685 void
01686 dbus_message_iter_get_basic (DBusMessageIter  *iter,
01687                              void             *value)
01688 {
01689   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01690 
01691   _dbus_return_if_fail (_dbus_message_iter_check (real));
01692   _dbus_return_if_fail (value != NULL);
01693 
01694   _dbus_type_reader_read_basic (&real->u.reader,
01695                                 value);
01696 }
01697 
01704 int
01705 dbus_message_iter_get_array_len (DBusMessageIter *iter)
01706 {
01707   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01708 
01709   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
01710 
01711   return _dbus_type_reader_get_array_length (&real->u.reader);
01712 }
01713 
01731 void
01732 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
01733                                    void             *value,
01734                                    int              *n_elements)
01735 {
01736   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01737 
01738   _dbus_return_if_fail (_dbus_message_iter_check (real));
01739   _dbus_return_if_fail (value != NULL);
01740   _dbus_return_if_fail (dbus_type_is_fixed (_dbus_type_reader_get_current_type (&real->u.reader)));
01741 
01742   _dbus_type_reader_read_fixed_multi (&real->u.reader,
01743                                       value, n_elements);
01744 }
01745 
01759 dbus_bool_t
01760 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
01761                                     DBusError       *error,
01762                                     int              first_arg_type,
01763                                     va_list          var_args)
01764 {
01765   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01766   int spec_type, msg_type, i;
01767   dbus_bool_t retval;
01768 
01769   _dbus_assert (_dbus_message_iter_check (real));
01770 
01771   retval = FALSE;
01772 
01773   spec_type = first_arg_type;
01774   i = 0;
01775 
01776   while (spec_type != DBUS_TYPE_INVALID)
01777     {
01778       msg_type = dbus_message_iter_get_arg_type (iter);
01779 
01780       if (msg_type != spec_type)
01781         {
01782           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01783                           "Argument %d is specified to be of type \"%s\", but "
01784                           "is actually of type \"%s\"\n", i,
01785                           _dbus_type_to_string (spec_type),
01786                           _dbus_type_to_string (msg_type));
01787 
01788           goto out;
01789         }
01790 
01791       if (dbus_type_is_basic (spec_type))
01792         {
01793           DBusBasicValue *ptr;
01794 
01795           ptr = va_arg (var_args, DBusBasicValue*);
01796 
01797           _dbus_assert (ptr != NULL);
01798 
01799           _dbus_type_reader_read_basic (&real->u.reader,
01800                                         ptr);
01801         }
01802       else if (spec_type == DBUS_TYPE_ARRAY)
01803         {
01804           int element_type;
01805           int spec_element_type;
01806           const DBusBasicValue **ptr;
01807           int *n_elements_p;
01808           DBusTypeReader array;
01809 
01810           spec_element_type = va_arg (var_args, int);
01811           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
01812 
01813           if (spec_element_type != element_type)
01814             {
01815               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01816                               "Argument %d is specified to be an array of \"%s\", but "
01817                               "is actually an array of \"%s\"\n",
01818                               i,
01819                               _dbus_type_to_string (spec_element_type),
01820                               _dbus_type_to_string (element_type));
01821 
01822               goto out;
01823             }
01824 
01825           if (dbus_type_is_fixed (spec_element_type))
01826             {
01827               ptr = va_arg (var_args, const DBusBasicValue**);
01828               n_elements_p = va_arg (var_args, int*);
01829 
01830               _dbus_assert (ptr != NULL);
01831               _dbus_assert (n_elements_p != NULL);
01832 
01833               _dbus_type_reader_recurse (&real->u.reader, &array);
01834 
01835               _dbus_type_reader_read_fixed_multi (&array,
01836                                                   ptr, n_elements_p);
01837             }
01838           else if (spec_element_type == DBUS_TYPE_STRING ||
01839                    spec_element_type == DBUS_TYPE_SIGNATURE ||
01840                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
01841             {
01842               char ***str_array_p;
01843               int n_elements;
01844               char **str_array;
01845 
01846               str_array_p = va_arg (var_args, char***);
01847               n_elements_p = va_arg (var_args, int*);
01848 
01849               _dbus_assert (str_array_p != NULL);
01850               _dbus_assert (n_elements_p != NULL);
01851 
01852               /* Count elements in the array */
01853               _dbus_type_reader_recurse (&real->u.reader, &array);
01854 
01855               n_elements = 0;
01856               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
01857                 {
01858                   ++n_elements;
01859                   _dbus_type_reader_next (&array);
01860                 }
01861 
01862               str_array = dbus_new0 (char*, n_elements + 1);
01863               if (str_array == NULL)
01864                 {
01865                   _DBUS_SET_OOM (error);
01866                   goto out;
01867                 }
01868 
01869               /* Now go through and dup each string */
01870               _dbus_type_reader_recurse (&real->u.reader, &array);
01871 
01872               i = 0;
01873               while (i < n_elements)
01874                 {
01875                   const char *s;
01876                   _dbus_type_reader_read_basic (&array,
01877                                                 &s);
01878                   
01879                   str_array[i] = _dbus_strdup (s);
01880                   if (str_array[i] == NULL)
01881                     {
01882                       dbus_free_string_array (str_array);
01883                       _DBUS_SET_OOM (error);
01884                       goto out;
01885                     }
01886                   
01887                   ++i;
01888                   
01889                   if (!_dbus_type_reader_next (&array))
01890                     _dbus_assert (i == n_elements);
01891                 }
01892 
01893               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
01894               _dbus_assert (i == n_elements);
01895               _dbus_assert (str_array[i] == NULL);
01896 
01897               *str_array_p = str_array;
01898               *n_elements_p = n_elements;
01899             }
01900 #ifndef DBUS_DISABLE_CHECKS
01901           else
01902             {
01903               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
01904                           _DBUS_FUNCTION_NAME);
01905               goto out;
01906             }
01907 #endif
01908         }
01909 #ifndef DBUS_DISABLE_CHECKS
01910       else
01911         {
01912           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
01913                       _DBUS_FUNCTION_NAME);
01914           goto out;
01915         }
01916 #endif
01917 
01918       spec_type = va_arg (var_args, int);
01919       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
01920         {
01921           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
01922                           "Message has only %d arguments, but more were expected", i);
01923           goto out;
01924         }
01925 
01926       i++;
01927     }
01928 
01929   retval = TRUE;
01930 
01931  out:
01932 
01933   return retval;
01934 }
01935 
01947 void
01948 dbus_message_iter_init_append (DBusMessage     *message,
01949                                DBusMessageIter *iter)
01950 {
01951   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01952 
01953   _dbus_return_if_fail (message != NULL);
01954   _dbus_return_if_fail (iter != NULL);
01955 
01956   _dbus_message_iter_init_common (message, real,
01957                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
01958 
01959   /* We create the signature string and point iterators at it "on demand"
01960    * when a value is actually appended. That means that init() never fails
01961    * due to OOM.
01962    */
01963   _dbus_type_writer_init_types_delayed (&real->u.writer,
01964                                         message->byte_order,
01965                                         &message->body,
01966                                         _dbus_string_get_length (&message->body));
01967 }
01968 
01977 static dbus_bool_t
01978 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
01979 {
01980   DBusString *str;
01981   const DBusString *current_sig;
01982   int current_sig_pos;
01983 
01984   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
01985 
01986   if (real->u.writer.type_str != NULL)
01987     {
01988       _dbus_assert (real->sig_refcount > 0);
01989       real->sig_refcount += 1;
01990       return TRUE;
01991     }
01992 
01993   str = dbus_new (DBusString, 1);
01994   if (str == NULL)
01995     return FALSE;
01996 
01997   if (!_dbus_header_get_field_raw (&real->message->header,
01998                                    DBUS_HEADER_FIELD_SIGNATURE,
01999                                    &current_sig, &current_sig_pos))
02000     current_sig = NULL;
02001 
02002   if (current_sig)
02003     {
02004       int current_len;
02005 
02006       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02007       current_sig_pos += 1; /* move on to sig data */
02008 
02009       if (!_dbus_string_init_preallocated (str, current_len + 4))
02010         {
02011           dbus_free (str);
02012           return FALSE;
02013         }
02014 
02015       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02016                                   str, 0))
02017         {
02018           _dbus_string_free (str);
02019           dbus_free (str);
02020           return FALSE;
02021         }
02022     }
02023   else
02024     {
02025       if (!_dbus_string_init_preallocated (str, 4))
02026         {
02027           dbus_free (str);
02028           return FALSE;
02029         }
02030     }
02031 
02032   real->sig_refcount = 1;
02033 
02034   _dbus_type_writer_add_types (&real->u.writer,
02035                                str, _dbus_string_get_length (str));
02036   return TRUE;
02037 }
02038 
02048 static dbus_bool_t
02049 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02050 {
02051   DBusString *str;
02052   const char *v_STRING;
02053   dbus_bool_t retval;
02054 
02055   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02056   _dbus_assert (real->u.writer.type_str != NULL);
02057   _dbus_assert (real->sig_refcount > 0);
02058 
02059   real->sig_refcount -= 1;
02060 
02061   if (real->sig_refcount > 0)
02062     return TRUE;
02063   _dbus_assert (real->sig_refcount == 0);
02064 
02065   retval = TRUE;
02066 
02067   str = real->u.writer.type_str;
02068 
02069   v_STRING = _dbus_string_get_const_data (str);
02070   if (!_dbus_header_set_field_basic (&real->message->header,
02071                                      DBUS_HEADER_FIELD_SIGNATURE,
02072                                      DBUS_TYPE_SIGNATURE,
02073                                      &v_STRING))
02074     retval = FALSE;
02075 
02076   _dbus_type_writer_remove_types (&real->u.writer);
02077   _dbus_string_free (str);
02078   dbus_free (str);
02079 
02080   return retval;
02081 }
02082 
02083 #ifndef DBUS_DISABLE_CHECKS
02084 static dbus_bool_t
02085 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02086 {
02087   if (!_dbus_message_iter_check (iter))
02088     return FALSE;
02089 
02090   if (iter->message->locked)
02091     {
02092       _dbus_warn ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02093       return FALSE;
02094     }
02095 
02096   return TRUE;
02097 }
02098 #endif /* DBUS_DISABLE_CHECKS */
02099 
02115 dbus_bool_t
02116 dbus_message_iter_append_basic (DBusMessageIter *iter,
02117                                 int              type,
02118                                 const void      *value)
02119 {
02120   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02121   dbus_bool_t ret;
02122 
02123   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02124   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02125   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02126   _dbus_return_val_if_fail (value != NULL, FALSE);
02127 
02128   if (!_dbus_message_iter_open_signature (real))
02129     return FALSE;
02130 
02131   ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02132 
02133   if (!_dbus_message_iter_close_signature (real))
02134     ret = FALSE;
02135 
02136   return ret;
02137 }
02138 
02174 dbus_bool_t
02175 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02176                                       int              element_type,
02177                                       const void      *value,
02178                                       int              n_elements)
02179 {
02180   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02181   dbus_bool_t ret;
02182 
02183   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02184   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02185   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type), FALSE);
02186   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02187   _dbus_return_val_if_fail (value != NULL, FALSE);
02188   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02189   _dbus_return_val_if_fail (n_elements <=
02190                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02191                             FALSE);
02192 
02193   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02194 
02195   return ret;
02196 }
02197 
02219 dbus_bool_t
02220 dbus_message_iter_open_container (DBusMessageIter *iter,
02221                                   int              type,
02222                                   const char      *contained_signature,
02223                                   DBusMessageIter *sub)
02224 {
02225   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02226   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02227   DBusString contained_str;
02228 
02229   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02230   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02231   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02232   _dbus_return_val_if_fail (sub != NULL, FALSE);
02233   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02234                              contained_signature == NULL) ||
02235                             (type == DBUS_TYPE_DICT_ENTRY &&
02236                              contained_signature == NULL) ||
02237                             contained_signature != NULL, FALSE);
02238   
02239 #if 0
02240   /* FIXME this would fail if the contained_signature is a dict entry,
02241    * since dict entries are invalid signatures standalone (they must be in
02242    * an array)
02243    */
02244   _dbus_return_val_if_fail (contained_signature == NULL ||
02245                             _dbus_check_is_valid_signature (contained_signature));
02246 #endif
02247 
02248   if (!_dbus_message_iter_open_signature (real))
02249     return FALSE;
02250 
02251   *real_sub = *real;
02252 
02253   if (contained_signature != NULL)
02254     {
02255       _dbus_string_init_const (&contained_str, contained_signature);
02256 
02257       return _dbus_type_writer_recurse (&real->u.writer,
02258                                         type,
02259                                         &contained_str, 0,
02260                                         &real_sub->u.writer);
02261     }
02262   else
02263     {
02264       return _dbus_type_writer_recurse (&real->u.writer,
02265                                         type,
02266                                         NULL, 0,
02267                                         &real_sub->u.writer);
02268     } 
02269 }
02270 
02271 
02285 dbus_bool_t
02286 dbus_message_iter_close_container (DBusMessageIter *iter,
02287                                    DBusMessageIter *sub)
02288 {
02289   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02290   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02291   dbus_bool_t ret;
02292 
02293   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02294   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02295   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02296   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02297 
02298   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02299                                      &real_sub->u.writer);
02300 
02301   if (!_dbus_message_iter_close_signature (real))
02302     ret = FALSE;
02303 
02304   return ret;
02305 }
02306 
02318 void
02319 dbus_message_set_no_reply (DBusMessage *message,
02320                            dbus_bool_t  no_reply)
02321 {
02322   _dbus_return_if_fail (message != NULL);
02323   _dbus_return_if_fail (!message->locked);
02324 
02325   _dbus_header_toggle_flag (&message->header,
02326                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02327                             no_reply);
02328 }
02329 
02337 dbus_bool_t
02338 dbus_message_get_no_reply (DBusMessage *message)
02339 {
02340   _dbus_return_val_if_fail (message != NULL, FALSE);
02341 
02342   return _dbus_header_get_flag (&message->header,
02343                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02344 }
02345 
02356 void
02357 dbus_message_set_auto_start (DBusMessage *message,
02358                              dbus_bool_t  auto_start)
02359 {
02360   _dbus_return_if_fail (message != NULL);
02361   _dbus_return_if_fail (!message->locked);
02362 
02363   _dbus_header_toggle_flag (&message->header,
02364                             DBUS_HEADER_FLAG_NO_AUTO_START,
02365                             !auto_start);
02366 }
02367 
02375 dbus_bool_t
02376 dbus_message_get_auto_start (DBusMessage *message)
02377 {
02378   _dbus_return_val_if_fail (message != NULL, FALSE);
02379 
02380   return !_dbus_header_get_flag (&message->header,
02381                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02382 }
02383 
02384 
02394 dbus_bool_t
02395 dbus_message_set_path (DBusMessage   *message,
02396                        const char    *object_path)
02397 {
02398   _dbus_return_val_if_fail (message != NULL, FALSE);
02399   _dbus_return_val_if_fail (!message->locked, FALSE);
02400   _dbus_return_val_if_fail (object_path == NULL ||
02401                             _dbus_check_is_valid_path (object_path),
02402                             FALSE);
02403 
02404   return set_or_delete_string_field (message,
02405                                      DBUS_HEADER_FIELD_PATH,
02406                                      DBUS_TYPE_OBJECT_PATH,
02407                                      object_path);
02408 }
02409 
02418 const char*
02419 dbus_message_get_path (DBusMessage   *message)
02420 {
02421   const char *v;
02422 
02423   _dbus_return_val_if_fail (message != NULL, NULL);
02424 
02425   v = NULL; /* in case field doesn't exist */
02426   _dbus_header_get_field_basic (&message->header,
02427                                 DBUS_HEADER_FIELD_PATH,
02428                                 DBUS_TYPE_OBJECT_PATH,
02429                                 &v);
02430   return v;
02431 }
02432 
02439 dbus_bool_t
02440 dbus_message_has_path (DBusMessage   *message,
02441                        const char    *path)
02442 {
02443   const char *msg_path;
02444   msg_path = dbus_message_get_path (message);
02445   
02446   if (msg_path == NULL)
02447     {
02448       if (path == NULL)
02449         return TRUE;
02450       else
02451         return FALSE;
02452     }
02453 
02454   if (path == NULL)
02455     return FALSE;
02456    
02457   if (strcmp (msg_path, path) == 0)
02458     return TRUE;
02459 
02460   return FALSE;
02461 }
02462 
02481 dbus_bool_t
02482 dbus_message_get_path_decomposed (DBusMessage   *message,
02483                                   char        ***path)
02484 {
02485   const char *v;
02486 
02487   _dbus_return_val_if_fail (message != NULL, FALSE);
02488   _dbus_return_val_if_fail (path != NULL, FALSE);
02489 
02490   *path = NULL;
02491 
02492   v = dbus_message_get_path (message);
02493   if (v != NULL)
02494     {
02495       if (!_dbus_decompose_path (v, strlen (v),
02496                                  path, NULL))
02497         return FALSE;
02498     }
02499   return TRUE;
02500 }
02501 
02512 dbus_bool_t
02513 dbus_message_set_interface (DBusMessage  *message,
02514                             const char   *interface)
02515 {
02516   _dbus_return_val_if_fail (message != NULL, FALSE);
02517   _dbus_return_val_if_fail (!message->locked, FALSE);
02518   _dbus_return_val_if_fail (interface == NULL ||
02519                             _dbus_check_is_valid_interface (interface),
02520                             FALSE);
02521 
02522   return set_or_delete_string_field (message,
02523                                      DBUS_HEADER_FIELD_INTERFACE,
02524                                      DBUS_TYPE_STRING,
02525                                      interface);
02526 }
02527 
02538 const char*
02539 dbus_message_get_interface (DBusMessage *message)
02540 {
02541   const char *v;
02542 
02543   _dbus_return_val_if_fail (message != NULL, NULL);
02544 
02545   v = NULL; /* in case field doesn't exist */
02546   _dbus_header_get_field_basic (&message->header,
02547                                 DBUS_HEADER_FIELD_INTERFACE,
02548                                 DBUS_TYPE_STRING,
02549                                 &v);
02550   return v;
02551 }
02552 
02559 dbus_bool_t
02560 dbus_message_has_interface (DBusMessage   *message,
02561                             const char    *interface)
02562 {
02563   const char *msg_interface;
02564   msg_interface = dbus_message_get_interface (message);
02565    
02566   if (msg_interface == NULL)
02567     {
02568       if (interface == NULL)
02569         return TRUE;
02570       else
02571         return FALSE;
02572     }
02573 
02574   if (interface == NULL)
02575     return FALSE;
02576      
02577   if (strcmp (msg_interface, interface) == 0)
02578     return TRUE;
02579 
02580   return FALSE;
02581 
02582 }
02583 
02594 dbus_bool_t
02595 dbus_message_set_member (DBusMessage  *message,
02596                          const char   *member)
02597 {
02598   _dbus_return_val_if_fail (message != NULL, FALSE);
02599   _dbus_return_val_if_fail (!message->locked, FALSE);
02600   _dbus_return_val_if_fail (member == NULL ||
02601                             _dbus_check_is_valid_member (member),
02602                             FALSE);
02603 
02604   return set_or_delete_string_field (message,
02605                                      DBUS_HEADER_FIELD_MEMBER,
02606                                      DBUS_TYPE_STRING,
02607                                      member);
02608 }
02609 
02618 const char*
02619 dbus_message_get_member (DBusMessage *message)
02620 {
02621   const char *v;
02622 
02623   _dbus_return_val_if_fail (message != NULL, NULL);
02624 
02625   v = NULL; /* in case field doesn't exist */
02626   _dbus_header_get_field_basic (&message->header,
02627                                 DBUS_HEADER_FIELD_MEMBER,
02628                                 DBUS_TYPE_STRING,
02629                                 &v);
02630   return v;
02631 }
02632 
02639 dbus_bool_t
02640 dbus_message_has_member (DBusMessage   *message,
02641                          const char    *member)
02642 {
02643   const char *msg_member;
02644   msg_member = dbus_message_get_member (message);
02645  
02646   if (msg_member == NULL)
02647     {
02648       if (member == NULL)
02649         return TRUE;
02650       else
02651         return FALSE;
02652     }
02653 
02654   if (member == NULL)
02655     return FALSE;
02656     
02657   if (strcmp (msg_member, member) == 0)
02658     return TRUE;
02659 
02660   return FALSE;
02661 
02662 }
02663 
02672 dbus_bool_t
02673 dbus_message_set_error_name (DBusMessage  *message,
02674                              const char   *error_name)
02675 {
02676   _dbus_return_val_if_fail (message != NULL, FALSE);
02677   _dbus_return_val_if_fail (!message->locked, FALSE);
02678   _dbus_return_val_if_fail (error_name == NULL ||
02679                             _dbus_check_is_valid_error_name (error_name),
02680                             FALSE);
02681 
02682   return set_or_delete_string_field (message,
02683                                      DBUS_HEADER_FIELD_ERROR_NAME,
02684                                      DBUS_TYPE_STRING,
02685                                      error_name);
02686 }
02687 
02695 const char*
02696 dbus_message_get_error_name (DBusMessage *message)
02697 {
02698   const char *v;
02699 
02700   _dbus_return_val_if_fail (message != NULL, NULL);
02701 
02702   v = NULL; /* in case field doesn't exist */
02703   _dbus_header_get_field_basic (&message->header,
02704                                 DBUS_HEADER_FIELD_ERROR_NAME,
02705                                 DBUS_TYPE_STRING,
02706                                 &v);
02707   return v;
02708 }
02709 
02720 dbus_bool_t
02721 dbus_message_set_destination (DBusMessage  *message,
02722                               const char   *destination)
02723 {
02724   _dbus_return_val_if_fail (message != NULL, FALSE);
02725   _dbus_return_val_if_fail (!message->locked, FALSE);
02726   _dbus_return_val_if_fail (destination == NULL ||
02727                             _dbus_check_is_valid_bus_name (destination),
02728                             FALSE);
02729 
02730   return set_or_delete_string_field (message,
02731                                      DBUS_HEADER_FIELD_DESTINATION,
02732                                      DBUS_TYPE_STRING,
02733                                      destination);
02734 }
02735 
02742 const char*
02743 dbus_message_get_destination (DBusMessage *message)
02744 {
02745   const char *v;
02746 
02747   _dbus_return_val_if_fail (message != NULL, NULL);
02748 
02749   v = NULL; /* in case field doesn't exist */
02750   _dbus_header_get_field_basic (&message->header,
02751                                 DBUS_HEADER_FIELD_DESTINATION,
02752                                 DBUS_TYPE_STRING,
02753                                 &v);
02754   return v;
02755 }
02756 
02764 dbus_bool_t
02765 dbus_message_set_sender (DBusMessage  *message,
02766                          const char   *sender)
02767 {
02768   _dbus_return_val_if_fail (message != NULL, FALSE);
02769   _dbus_return_val_if_fail (!message->locked, FALSE);
02770   _dbus_return_val_if_fail (sender == NULL ||
02771                             _dbus_check_is_valid_bus_name (sender),
02772                             FALSE);
02773 
02774   return set_or_delete_string_field (message,
02775                                      DBUS_HEADER_FIELD_SENDER,
02776                                      DBUS_TYPE_STRING,
02777                                      sender);
02778 }
02779 
02788 const char*
02789 dbus_message_get_sender (DBusMessage *message)
02790 {
02791   const char *v;
02792 
02793   _dbus_return_val_if_fail (message != NULL, NULL);
02794 
02795   v = NULL; /* in case field doesn't exist */
02796   _dbus_header_get_field_basic (&message->header,
02797                                 DBUS_HEADER_FIELD_SENDER,
02798                                 DBUS_TYPE_STRING,
02799                                 &v);
02800   return v;
02801 }
02802 
02818 const char*
02819 dbus_message_get_signature (DBusMessage *message)
02820 {
02821   const DBusString *type_str;
02822   int type_pos;
02823 
02824   _dbus_return_val_if_fail (message != NULL, NULL);
02825 
02826   get_const_signature (&message->header, &type_str, &type_pos);
02827 
02828   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
02829 }
02830 
02831 static dbus_bool_t
02832 _dbus_message_has_type_interface_member (DBusMessage *message,
02833                                          int          type,
02834                                          const char  *interface,
02835                                          const char  *member)
02836 {
02837   const char *n;
02838 
02839   _dbus_assert (message != NULL);
02840   _dbus_assert (interface != NULL);
02841   _dbus_assert (member != NULL);
02842 
02843   if (dbus_message_get_type (message) != type)
02844     return FALSE;
02845 
02846   /* Optimize by checking the short member name first
02847    * instead of the longer interface name
02848    */
02849 
02850   n = dbus_message_get_member (message);
02851 
02852   if (n && strcmp (n, member) == 0)
02853     {
02854       n = dbus_message_get_interface (message);
02855 
02856       if (n == NULL || strcmp (n, interface) == 0)
02857         return TRUE;
02858     }
02859 
02860   return FALSE;
02861 }
02862 
02877 dbus_bool_t
02878 dbus_message_is_method_call (DBusMessage *message,
02879                              const char  *interface,
02880                              const char  *method)
02881 {
02882   _dbus_return_val_if_fail (message != NULL, FALSE);
02883   _dbus_return_val_if_fail (interface != NULL, FALSE);
02884   _dbus_return_val_if_fail (method != NULL, FALSE);
02885   /* don't check that interface/method are valid since it would be
02886    * expensive, and not catch many common errors
02887    */
02888 
02889   return _dbus_message_has_type_interface_member (message,
02890                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
02891                                                   interface, method);
02892 }
02893 
02907 dbus_bool_t
02908 dbus_message_is_signal (DBusMessage *message,
02909                         const char  *interface,
02910                         const char  *signal_name)
02911 {
02912   _dbus_return_val_if_fail (message != NULL, FALSE);
02913   _dbus_return_val_if_fail (interface != NULL, FALSE);
02914   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
02915   /* don't check that interface/name are valid since it would be
02916    * expensive, and not catch many common errors
02917    */
02918 
02919   return _dbus_message_has_type_interface_member (message,
02920                                                   DBUS_MESSAGE_TYPE_SIGNAL,
02921                                                   interface, signal_name);
02922 }
02923 
02934 dbus_bool_t
02935 dbus_message_is_error (DBusMessage *message,
02936                        const char  *error_name)
02937 {
02938   const char *n;
02939 
02940   _dbus_return_val_if_fail (message != NULL, FALSE);
02941   _dbus_return_val_if_fail (error_name != NULL, FALSE);
02942   /* don't check that error_name is valid since it would be expensive,
02943    * and not catch many common errors
02944    */
02945 
02946   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
02947     return FALSE;
02948 
02949   n = dbus_message_get_error_name (message);
02950 
02951   if (n && strcmp (n, error_name) == 0)
02952     return TRUE;
02953   else
02954     return FALSE;
02955 }
02956 
02967 dbus_bool_t
02968 dbus_message_has_destination (DBusMessage  *message,
02969                               const char   *name)
02970 {
02971   const char *s;
02972 
02973   _dbus_return_val_if_fail (message != NULL, FALSE);
02974   _dbus_return_val_if_fail (name != NULL, FALSE);
02975   /* don't check that name is valid since it would be expensive, and
02976    * not catch many common errors
02977    */
02978 
02979   s = dbus_message_get_destination (message);
02980 
02981   if (s && strcmp (s, name) == 0)
02982     return TRUE;
02983   else
02984     return FALSE;
02985 }
02986 
03002 dbus_bool_t
03003 dbus_message_has_sender (DBusMessage  *message,
03004                          const char   *name)
03005 {
03006   const char *s;
03007 
03008   _dbus_return_val_if_fail (message != NULL, FALSE);
03009   _dbus_return_val_if_fail (name != NULL, FALSE);
03010   /* don't check that name is valid since it would be expensive, and
03011    * not catch many common errors
03012    */
03013 
03014   s = dbus_message_get_sender (message);
03015 
03016   if (s && strcmp (s, name) == 0)
03017     return TRUE;
03018   else
03019     return FALSE;
03020 }
03021 
03031 dbus_bool_t
03032 dbus_message_has_signature (DBusMessage   *message,
03033                             const char    *signature)
03034 {
03035   const char *s;
03036 
03037   _dbus_return_val_if_fail (message != NULL, FALSE);
03038   _dbus_return_val_if_fail (signature != NULL, FALSE);
03039   /* don't check that signature is valid since it would be expensive,
03040    * and not catch many common errors
03041    */
03042 
03043   s = dbus_message_get_signature (message);
03044 
03045   if (s && strcmp (s, signature) == 0)
03046     return TRUE;
03047   else
03048     return FALSE;
03049 }
03050 
03073 dbus_bool_t
03074 dbus_set_error_from_message (DBusError   *error,
03075                              DBusMessage *message)
03076 {
03077   const char *str;
03078 
03079   _dbus_return_val_if_fail (message != NULL, FALSE);
03080   _dbus_return_val_if_error_is_set (error, FALSE);
03081 
03082   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03083     return FALSE;
03084 
03085   str = NULL;
03086   dbus_message_get_args (message, NULL,
03087                          DBUS_TYPE_STRING, &str,
03088                          DBUS_TYPE_INVALID);
03089 
03090   dbus_set_error (error, dbus_message_get_error_name (message),
03091                   str ? "%s" : NULL, str);
03092 
03093   return TRUE;
03094 }
03095 
03114 #define INITIAL_LOADER_DATA_LEN 32
03115 
03122 DBusMessageLoader*
03123 _dbus_message_loader_new (void)
03124 {
03125   DBusMessageLoader *loader;
03126 
03127   loader = dbus_new0 (DBusMessageLoader, 1);
03128   if (loader == NULL)
03129     return NULL;
03130   
03131   loader->refcount = 1;
03132 
03133   loader->corrupted = FALSE;
03134   loader->corruption_reason = DBUS_VALID;
03135 
03136   /* this can be configured by the app, but defaults to the protocol max */
03137   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03138 
03139   if (!_dbus_string_init (&loader->data))
03140     {
03141       dbus_free (loader);
03142       return NULL;
03143     }
03144 
03145   /* preallocate the buffer for speed, ignore failure */
03146   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03147   _dbus_string_set_length (&loader->data, 0);
03148 
03149   return loader;
03150 }
03151 
03158 DBusMessageLoader *
03159 _dbus_message_loader_ref (DBusMessageLoader *loader)
03160 {
03161   loader->refcount += 1;
03162 
03163   return loader;
03164 }
03165 
03172 void
03173 _dbus_message_loader_unref (DBusMessageLoader *loader)
03174 {
03175   loader->refcount -= 1;
03176   if (loader->refcount == 0)
03177     {
03178       _dbus_list_foreach (&loader->messages,
03179                           (DBusForeachFunction) dbus_message_unref,
03180                           NULL);
03181       _dbus_list_clear (&loader->messages);
03182       _dbus_string_free (&loader->data);
03183       dbus_free (loader);
03184     }
03185 }
03186 
03205 void
03206 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03207                                  DBusString        **buffer)
03208 {
03209   _dbus_assert (!loader->buffer_outstanding);
03210 
03211   *buffer = &loader->data;
03212 
03213   loader->buffer_outstanding = TRUE;
03214 }
03215 
03226 void
03227 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03228                                     DBusString         *buffer,
03229                                     int                 bytes_read)
03230 {
03231   _dbus_assert (loader->buffer_outstanding);
03232   _dbus_assert (buffer == &loader->data);
03233 
03234   loader->buffer_outstanding = FALSE;
03235 }
03236 
03237 /*
03238  * FIXME when we move the header out of the buffer, that memmoves all
03239  * buffered messages. Kind of crappy.
03240  *
03241  * Also we copy the header and body, which is kind of crappy.  To
03242  * avoid this, we have to allow header and body to be in a single
03243  * memory block, which is good for messages we read and bad for
03244  * messages we are creating. But we could move_len() the buffer into
03245  * this single memory block, and move_len() will just swap the buffers
03246  * if you're moving the entire buffer replacing the dest string.
03247  *
03248  * We could also have the message loader tell the transport how many
03249  * bytes to read; so it would first ask for some arbitrary number like
03250  * 256, then if the message was incomplete it would use the
03251  * header/body len to ask for exactly the size of the message (or
03252  * blocks the size of a typical kernel buffer for the socket). That
03253  * way we don't get trailing bytes in the buffer that have to be
03254  * memmoved. Though I suppose we also don't have a chance of reading a
03255  * bunch of small messages at once, so the optimization may be stupid.
03256  *
03257  * Another approach would be to keep a "start" index into
03258  * loader->data and only delete it occasionally, instead of after
03259  * each message is loaded.
03260  *
03261  * load_message() returns FALSE if not enough memory OR the loader was corrupted
03262  */
03263 static dbus_bool_t
03264 load_message (DBusMessageLoader *loader,
03265               DBusMessage       *message,
03266               int                byte_order,
03267               int                fields_array_len,
03268               int                header_len,
03269               int                body_len)
03270 {
03271   dbus_bool_t oom;
03272   DBusValidity validity;
03273   const DBusString *type_str;
03274   int type_pos;
03275   DBusValidationMode mode;
03276 
03277   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
03278   
03279   oom = FALSE;
03280 
03281 #if 0
03282   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
03283 #endif
03284 
03285   /* 1. VALIDATE AND COPY OVER HEADER */
03286   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
03287   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
03288 
03289   if (!_dbus_header_load (&message->header,
03290                           mode,
03291                           &validity,
03292                           byte_order,
03293                           fields_array_len,
03294                           header_len,
03295                           body_len,
03296                           &loader->data, 0,
03297                           _dbus_string_get_length (&loader->data)))
03298     {
03299       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
03300 
03301       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
03302          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
03303       _dbus_assert (validity != DBUS_VALID);
03304 
03305       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
03306         oom = TRUE;
03307       else
03308         {
03309           loader->corrupted = TRUE;
03310           loader->corruption_reason = validity;
03311         }
03312       goto failed;
03313     }
03314 
03315   _dbus_assert (validity == DBUS_VALID);
03316 
03317   message->byte_order = byte_order;
03318 
03319   /* 2. VALIDATE BODY */
03320   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
03321     {
03322       get_const_signature (&message->header, &type_str, &type_pos);
03323       
03324       /* Because the bytes_remaining arg is NULL, this validates that the
03325        * body is the right length
03326        */
03327       validity = _dbus_validate_body_with_reason (type_str,
03328                                                   type_pos,
03329                                                   byte_order,
03330                                                   NULL,
03331                                                   &loader->data,
03332                                                   header_len,
03333                                                   body_len);
03334       if (validity != DBUS_VALID)
03335         {
03336           _dbus_verbose ("Failed to validate message body code %d\n", validity);
03337 
03338           loader->corrupted = TRUE;
03339           loader->corruption_reason = validity;
03340           
03341           goto failed;
03342         }
03343     }
03344 
03345   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
03346 
03347   if (!_dbus_list_append (&loader->messages, message))
03348     {
03349       _dbus_verbose ("Failed to append new message to loader queue\n");
03350       oom = TRUE;
03351       goto failed;
03352     }
03353 
03354   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
03355   _dbus_assert (_dbus_string_get_length (&loader->data) >=
03356                 (header_len + body_len));
03357 
03358   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
03359     {
03360       _dbus_verbose ("Failed to move body into new message\n");
03361       oom = TRUE;
03362       goto failed;
03363     }
03364 
03365   _dbus_string_delete (&loader->data, 0, header_len + body_len);
03366 
03367   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
03368   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
03369 
03370   _dbus_verbose ("Loaded message %p\n", message);
03371 
03372   _dbus_assert (!oom);
03373   _dbus_assert (!loader->corrupted);
03374   _dbus_assert (loader->messages != NULL);
03375   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03376 
03377   return TRUE;
03378 
03379  failed:
03380 
03381   /* Clean up */
03382 
03383   /* does nothing if the message isn't in the list */
03384   _dbus_list_remove_last (&loader->messages, message);
03385   
03386   if (oom)
03387     _dbus_assert (!loader->corrupted);
03388   else
03389     _dbus_assert (loader->corrupted);
03390 
03391   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
03392 
03393   return FALSE;
03394 }
03395 
03410 dbus_bool_t
03411 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
03412 {
03413   while (!loader->corrupted &&
03414          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
03415     {
03416       DBusValidity validity;
03417       int byte_order, fields_array_len, header_len, body_len;
03418 
03419       if (_dbus_header_have_message_untrusted (loader->max_message_size,
03420                                                &validity,
03421                                                &byte_order,
03422                                                &fields_array_len,
03423                                                &header_len,
03424                                                &body_len,
03425                                                &loader->data, 0,
03426                                                _dbus_string_get_length (&loader->data)))
03427         {
03428           DBusMessage *message;
03429 
03430           _dbus_assert (validity == DBUS_VALID);
03431 
03432           message = dbus_message_new_empty_header ();
03433           if (message == NULL)
03434             return FALSE;
03435 
03436           if (!load_message (loader, message,
03437                              byte_order, fields_array_len,
03438                              header_len, body_len))
03439             {
03440               dbus_message_unref (message);
03441               /* load_message() returns false if corrupted or OOM; if
03442                * corrupted then return TRUE for not OOM
03443                */
03444               return loader->corrupted;
03445             }
03446 
03447           _dbus_assert (loader->messages != NULL);
03448           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
03449         }
03450       else
03451         {
03452           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
03453                          validity);
03454           if (validity != DBUS_VALID)
03455             {
03456               loader->corrupted = TRUE;
03457               loader->corruption_reason = validity;
03458             }
03459           return TRUE;
03460         }
03461     }
03462 
03463   return TRUE;
03464 }
03465 
03473 DBusMessage*
03474 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
03475 {
03476   if (loader->messages)
03477     return loader->messages->data;
03478   else
03479     return NULL;
03480 }
03481 
03490 DBusMessage*
03491 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
03492 {
03493   return _dbus_list_pop_first (&loader->messages);
03494 }
03495 
03504 DBusList*
03505 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
03506 {
03507   return _dbus_list_pop_first_link (&loader->messages);
03508 }
03509 
03516 void
03517 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
03518                                            DBusList           *link)
03519 {
03520   _dbus_list_prepend_link (&loader->messages, link);
03521 }
03522 
03532 dbus_bool_t
03533 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
03534 {
03535   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
03536                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
03537   return loader->corrupted;
03538 }
03539 
03546 void
03547 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
03548                                            long                size)
03549 {
03550   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
03551     {
03552       _dbus_verbose ("clamping requested max message size %ld to %d\n",
03553                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
03554       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03555     }
03556   loader->max_message_size = size;
03557 }
03558 
03565 long
03566 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
03567 {
03568   return loader->max_message_size;
03569 }
03570 
03571 static DBusDataSlotAllocator slot_allocator;
03572 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
03573 
03588 dbus_bool_t
03589 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
03590 {
03591   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03592                                           _DBUS_LOCK_NAME (message_slots),
03593                                           slot_p);
03594 }
03595 
03607 void
03608 dbus_message_free_data_slot (dbus_int32_t *slot_p)
03609 {
03610   _dbus_return_if_fail (*slot_p >= 0);
03611 
03612   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03613 }
03614 
03628 dbus_bool_t
03629 dbus_message_set_data (DBusMessage     *message,
03630                        dbus_int32_t     slot,
03631                        void            *data,
03632                        DBusFreeFunction free_data_func)
03633 {
03634   DBusFreeFunction old_free_func;
03635   void *old_data;
03636   dbus_bool_t retval;
03637 
03638   _dbus_return_val_if_fail (message != NULL, FALSE);
03639   _dbus_return_val_if_fail (slot >= 0, FALSE);
03640 
03641   retval = _dbus_data_slot_list_set (&slot_allocator,
03642                                      &message->slot_list,
03643                                      slot, data, free_data_func,
03644                                      &old_free_func, &old_data);
03645 
03646   if (retval)
03647     {
03648       /* Do the actual free outside the message lock */
03649       if (old_free_func)
03650         (* old_free_func) (old_data);
03651     }
03652 
03653   return retval;
03654 }
03655 
03664 void*
03665 dbus_message_get_data (DBusMessage   *message,
03666                        dbus_int32_t   slot)
03667 {
03668   void *res;
03669 
03670   _dbus_return_val_if_fail (message != NULL, NULL);
03671 
03672   res = _dbus_data_slot_list_get (&slot_allocator,
03673                                   &message->slot_list,
03674                                   slot);
03675 
03676   return res;
03677 }
03678 
03692 int
03693 dbus_message_type_from_string (const char *type_str)
03694 {
03695   if (strcmp (type_str, "method_call") == 0)
03696     return DBUS_MESSAGE_TYPE_METHOD_CALL;
03697   if (strcmp (type_str, "method_return") == 0)
03698     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
03699   else if (strcmp (type_str, "signal") == 0)
03700     return DBUS_MESSAGE_TYPE_SIGNAL;
03701   else if (strcmp (type_str, "error") == 0)
03702     return DBUS_MESSAGE_TYPE_ERROR;
03703   else
03704     return DBUS_MESSAGE_TYPE_INVALID;
03705 }
03706 
03720 const char *
03721 dbus_message_type_to_string (int type)
03722 {
03723   switch (type)
03724     {
03725     case DBUS_MESSAGE_TYPE_METHOD_CALL:
03726       return "method_call";
03727     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
03728       return "method_return";
03729     case DBUS_MESSAGE_TYPE_SIGNAL:
03730       return "signal";
03731     case DBUS_MESSAGE_TYPE_ERROR:
03732       return "error";
03733     default:
03734       return "invalid";
03735     }
03736 }
03737 
03740 /* tests in dbus-message-util.c */

Generated on Tue Sep 13 01:28:07 2005 for D-BUS by  doxygen 1.4.4