D-Bus 1.6.12

dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus-internals.h"
00027 #include "dbus-marshal-recursive.h"
00028 #include "dbus-marshal-validate.h"
00029 #include "dbus-marshal-byteswap.h"
00030 #include "dbus-marshal-header.h"
00031 #include "dbus-signature.h"
00032 #include "dbus-message-private.h"
00033 #include "dbus-object-tree.h"
00034 #include "dbus-memory.h"
00035 #include "dbus-list.h"
00036 #include "dbus-threads-internal.h"
00037 #ifdef HAVE_UNIX_FD_PASSING
00038 #include "dbus-sysdeps-unix.h"
00039 #endif
00040 
00041 #include <string.h>
00042 
00043 #define _DBUS_TYPE_IS_STRINGLIKE(type) \
00044   (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
00045    type == DBUS_TYPE_OBJECT_PATH)
00046 
00047 static void dbus_message_finalize (DBusMessage *message);
00048 
00059 #ifdef DBUS_BUILD_TESTS
00060 static dbus_bool_t
00061 _dbus_enable_message_cache (void)
00062 {
00063   static int enabled = -1;
00064 
00065   if (enabled < 0)
00066     {
00067       const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
00068 
00069       enabled = TRUE;
00070 
00071       if (s && *s)
00072         {
00073           if (*s == '0')
00074             enabled = FALSE;
00075           else if (*s == '1')
00076             enabled = TRUE;
00077           else
00078             _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
00079                 s);
00080         }
00081     }
00082 
00083   return enabled;
00084 }
00085 #else
00086     /* constant expression, should be optimized away */
00087 #   define _dbus_enable_message_cache() (TRUE)
00088 #endif
00089 
00090 #ifndef _dbus_message_trace_ref
00091 void
00092 _dbus_message_trace_ref (DBusMessage *message,
00093                          int          old_refcount,
00094                          int          new_refcount,
00095                          const char  *why)
00096 {
00097   static int enabled = -1;
00098 
00099   _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
00100       "DBUS_MESSAGE_TRACE", &enabled);
00101 }
00102 #endif
00103 
00104 /* Not thread locked, but strictly const/read-only so should be OK
00105  */
00107 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
00108 
00109 /* these have wacky values to help trap uninitialized iterators;
00110  * but has to fit in 3 bits
00111  */
00112 enum {
00113   DBUS_MESSAGE_ITER_TYPE_READER = 3,
00114   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
00115 };
00116 
00118 typedef struct DBusMessageRealIter DBusMessageRealIter;
00119 
00125 struct DBusMessageRealIter
00126 {
00127   DBusMessage *message; 
00128   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 
00129   dbus_uint32_t iter_type : 3;      
00130   dbus_uint32_t sig_refcount : 8;   
00131   union
00132   {
00133     DBusTypeWriter writer; 
00134     DBusTypeReader reader; 
00135   } u; 
00136 };
00137 
00138 static void
00139 get_const_signature (DBusHeader        *header,
00140                      const DBusString **type_str_p,
00141                      int               *type_pos_p)
00142 {
00143   if (_dbus_header_get_field_raw (header,
00144                                   DBUS_HEADER_FIELD_SIGNATURE,
00145                                   type_str_p,
00146                                   type_pos_p))
00147     {
00148       *type_pos_p += 1; /* skip the signature length which is 1 byte */
00149     }
00150   else
00151     {
00152       *type_str_p = &_dbus_empty_signature_str;
00153       *type_pos_p = 0;
00154     }
00155 }
00156 
00162 static void
00163 _dbus_message_byteswap (DBusMessage *message)
00164 {
00165   const DBusString *type_str;
00166   int type_pos;
00167   char byte_order;
00168 
00169   byte_order = _dbus_header_get_byte_order (&message->header);
00170 
00171   if (byte_order == DBUS_COMPILER_BYTE_ORDER)
00172     return;
00173 
00174   _dbus_verbose ("Swapping message into compiler byte order\n");
00175   
00176   get_const_signature (&message->header, &type_str, &type_pos);
00177   
00178   _dbus_marshal_byteswap (type_str, type_pos,
00179                           byte_order,
00180                           DBUS_COMPILER_BYTE_ORDER,
00181                           &message->body, 0);
00182 
00183   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
00184   _dbus_assert (_dbus_header_get_byte_order (&message->header) ==
00185                 DBUS_COMPILER_BYTE_ORDER);
00186 }
00187 
00194 #define ensure_byte_order(message) _dbus_message_byteswap (message)
00195 
00206 void
00207 _dbus_message_get_network_data (DBusMessage          *message,
00208                                 const DBusString    **header,
00209                                 const DBusString    **body)
00210 {
00211   _dbus_assert (message->locked);
00212 
00213   *header = &message->header.data;
00214   *body = &message->body;
00215 }
00216 
00226 void _dbus_message_get_unix_fds(DBusMessage *message,
00227                                 const int  **fds,
00228                                 unsigned    *n_fds)
00229 {
00230   _dbus_assert (message->locked);
00231 
00232 #ifdef HAVE_UNIX_FD_PASSING
00233   *fds = message->unix_fds;
00234   *n_fds = message->n_unix_fds;
00235 #else
00236   *fds = NULL;
00237   *n_fds = 0;
00238 #endif
00239 }
00240 
00252 void 
00253 dbus_message_set_serial (DBusMessage   *message,
00254                          dbus_uint32_t  serial)
00255 {
00256   _dbus_return_if_fail (message != NULL);
00257   _dbus_return_if_fail (!message->locked);
00258 
00259   _dbus_header_set_serial (&message->header, serial);
00260 }
00261 
00278 void
00279 _dbus_message_add_counter_link (DBusMessage  *message,
00280                                 DBusList     *link)
00281 {
00282   /* right now we don't recompute the delta when message
00283    * size changes, and that's OK for current purposes
00284    * I think, but could be important to change later.
00285    * Do recompute it whenever there are no outstanding counters,
00286    * since it's basically free.
00287    */
00288   if (message->counters == NULL)
00289     {
00290       message->size_counter_delta =
00291         _dbus_string_get_length (&message->header.data) +
00292         _dbus_string_get_length (&message->body);
00293 
00294 #ifdef HAVE_UNIX_FD_PASSING
00295       message->unix_fd_counter_delta = message->n_unix_fds;
00296 #endif
00297 
00298 #if 0
00299       _dbus_verbose ("message has size %ld\n",
00300                      message->size_counter_delta);
00301 #endif
00302     }
00303 
00304   _dbus_list_append_link (&message->counters, link);
00305 
00306   _dbus_counter_adjust_size (link->data, message->size_counter_delta);
00307 
00308 #ifdef HAVE_UNIX_FD_PASSING
00309   _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
00310 #endif
00311 }
00312 
00327 dbus_bool_t
00328 _dbus_message_add_counter (DBusMessage *message,
00329                            DBusCounter *counter)
00330 {
00331   DBusList *link;
00332 
00333   link = _dbus_list_alloc_link (counter);
00334   if (link == NULL)
00335     return FALSE;
00336 
00337   _dbus_counter_ref (counter);
00338   _dbus_message_add_counter_link (message, link);
00339 
00340   return TRUE;
00341 }
00342 
00350 void
00351 _dbus_message_remove_counter (DBusMessage  *message,
00352                               DBusCounter  *counter)
00353 {
00354   DBusList *link;
00355 
00356   link = _dbus_list_find_last (&message->counters,
00357                                counter);
00358   _dbus_assert (link != NULL);
00359 
00360   _dbus_list_remove_link (&message->counters, link);
00361 
00362   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00363 
00364 #ifdef HAVE_UNIX_FD_PASSING
00365   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00366 #endif
00367 
00368   _dbus_counter_notify (counter);
00369   _dbus_counter_unref (counter);
00370 }
00371 
00382 void
00383 dbus_message_lock (DBusMessage  *message)
00384 {
00385   if (!message->locked)
00386     {
00387       _dbus_header_update_lengths (&message->header,
00388                                    _dbus_string_get_length (&message->body));
00389 
00390       /* must have a signature if you have a body */
00391       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
00392                     dbus_message_get_signature (message) != NULL);
00393 
00394       message->locked = TRUE;
00395     }
00396 }
00397 
00398 static dbus_bool_t
00399 set_or_delete_string_field (DBusMessage *message,
00400                             int          field,
00401                             int          typecode,
00402                             const char  *value)
00403 {
00404   if (value == NULL)
00405     return _dbus_header_delete_field (&message->header, field);
00406   else
00407     return _dbus_header_set_field_basic (&message->header,
00408                                          field,
00409                                          typecode,
00410                                          &value);
00411 }
00412 
00413 #if 0
00414 /* Probably we don't need to use this */
00438 static dbus_bool_t
00439 _dbus_message_set_signature (DBusMessage *message,
00440                              const char  *signature)
00441 {
00442   _dbus_return_val_if_fail (message != NULL, FALSE);
00443   _dbus_return_val_if_fail (!message->locked, FALSE);
00444   _dbus_return_val_if_fail (signature == NULL ||
00445                             _dbus_check_is_valid_signature (signature));
00446   /* can't delete the signature if you have a message body */
00447   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
00448                             signature != NULL);
00449 
00450   return set_or_delete_string_field (message,
00451                                      DBUS_HEADER_FIELD_SIGNATURE,
00452                                      DBUS_TYPE_SIGNATURE,
00453                                      signature);
00454 }
00455 #endif
00456 
00457 /* Message Cache
00458  *
00459  * We cache some DBusMessage to reduce the overhead of allocating
00460  * them.  In my profiling this consistently made about an 8%
00461  * difference.  It avoids the malloc for the message, the malloc for
00462  * the slot list, the malloc for the header string and body string,
00463  * and the associated free() calls. It does introduce another global
00464  * lock which could be a performance issue in certain cases.
00465  *
00466  * For the echo client/server the round trip time goes from around
00467  * .000077 to .000069 with the message cache on my laptop. The sysprof
00468  * change is as follows (numbers are cumulative percentage):
00469  *
00470  *  with message cache implemented as array as it is now (0.000069 per):
00471  *    new_empty_header           1.46
00472  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
00473  *      mutex_unlock             0.25
00474  *      self                     0.41
00475  *    unref                      2.24
00476  *      self                     0.68
00477  *      list_clear               0.43
00478  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
00479  *      mutex_unlock             0.25
00480  *
00481  *  with message cache implemented as list (0.000070 per roundtrip):
00482  *    new_empty_header           2.72
00483  *      list_pop_first           1.88
00484  *    unref                      3.3
00485  *      list_prepend             1.63
00486  *
00487  * without cache (0.000077 per roundtrip):
00488  *    new_empty_header           6.7
00489  *      string_init_preallocated 3.43
00490  *        dbus_malloc            2.43
00491  *      dbus_malloc0             2.59
00492  *
00493  *    unref                      4.02
00494  *      string_free              1.82
00495  *        dbus_free              1.63
00496  *      dbus_free                0.71
00497  *
00498  * If you implement the message_cache with a list, the primary reason
00499  * it's slower is that you add another thread lock (on the DBusList
00500  * mempool).
00501  */
00502 
00504 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
00505 
00507 #define MAX_MESSAGE_CACHE_SIZE    5
00508 
00509 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
00510 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
00511 static int message_cache_count = 0;
00512 static dbus_bool_t message_cache_shutdown_registered = FALSE;
00513 
00514 static void
00515 dbus_message_cache_shutdown (void *data)
00516 {
00517   int i;
00518 
00519   _DBUS_LOCK (message_cache);
00520 
00521   i = 0;
00522   while (i < MAX_MESSAGE_CACHE_SIZE)
00523     {
00524       if (message_cache[i])
00525         dbus_message_finalize (message_cache[i]);
00526 
00527       ++i;
00528     }
00529 
00530   message_cache_count = 0;
00531   message_cache_shutdown_registered = FALSE;
00532 
00533   _DBUS_UNLOCK (message_cache);
00534 }
00535 
00543 static DBusMessage*
00544 dbus_message_get_cached (void)
00545 {
00546   DBusMessage *message;
00547   int i;
00548 
00549   message = NULL;
00550 
00551   _DBUS_LOCK (message_cache);
00552 
00553   _dbus_assert (message_cache_count >= 0);
00554 
00555   if (message_cache_count == 0)
00556     {
00557       _DBUS_UNLOCK (message_cache);
00558       return NULL;
00559     }
00560 
00561   /* This is not necessarily true unless count > 0, and
00562    * message_cache is uninitialized until the shutdown is
00563    * registered
00564    */
00565   _dbus_assert (message_cache_shutdown_registered);
00566 
00567   i = 0;
00568   while (i < MAX_MESSAGE_CACHE_SIZE)
00569     {
00570       if (message_cache[i])
00571         {
00572           message = message_cache[i];
00573           message_cache[i] = NULL;
00574           message_cache_count -= 1;
00575           break;
00576         }
00577       ++i;
00578     }
00579   _dbus_assert (message_cache_count >= 0);
00580   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00581   _dbus_assert (message != NULL);
00582 
00583   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00584 
00585   _dbus_assert (message->counters == NULL);
00586   
00587   _DBUS_UNLOCK (message_cache);
00588 
00589   return message;
00590 }
00591 
00592 #ifdef HAVE_UNIX_FD_PASSING
00593 static void
00594 close_unix_fds(int *fds, unsigned *n_fds)
00595 {
00596   DBusError e;
00597   int i;
00598 
00599   if (*n_fds <= 0)
00600     return;
00601 
00602   dbus_error_init(&e);
00603 
00604   for (i = 0; i < *n_fds; i++)
00605     {
00606       if (!_dbus_close(fds[i], &e))
00607         {
00608           _dbus_warn("Failed to close file descriptor: %s\n", e.message);
00609           dbus_error_free(&e);
00610         }
00611     }
00612 
00613   *n_fds = 0;
00614 
00615   /* We don't free the array here, in case we can recycle it later */
00616 }
00617 #endif
00618 
00619 static void
00620 free_counter (void *element,
00621               void *data)
00622 {
00623   DBusCounter *counter = element;
00624   DBusMessage *message = data;
00625 
00626   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
00627 #ifdef HAVE_UNIX_FD_PASSING
00628   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
00629 #endif
00630 
00631   _dbus_counter_notify (counter);
00632   _dbus_counter_unref (counter);
00633 }
00634 
00640 static void
00641 dbus_message_cache_or_finalize (DBusMessage *message)
00642 {
00643   dbus_bool_t was_cached;
00644   int i;
00645 
00646   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00647 
00648   /* This calls application code and has to be done first thing
00649    * without holding the lock
00650    */
00651   _dbus_data_slot_list_clear (&message->slot_list);
00652 
00653   _dbus_list_foreach (&message->counters,
00654                       free_counter, message);
00655   _dbus_list_clear (&message->counters);
00656 
00657 #ifdef HAVE_UNIX_FD_PASSING
00658   close_unix_fds(message->unix_fds, &message->n_unix_fds);
00659 #endif
00660 
00661   was_cached = FALSE;
00662 
00663   _DBUS_LOCK (message_cache);
00664 
00665   if (!message_cache_shutdown_registered)
00666     {
00667       _dbus_assert (message_cache_count == 0);
00668 
00669       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
00670         goto out;
00671 
00672       i = 0;
00673       while (i < MAX_MESSAGE_CACHE_SIZE)
00674         {
00675           message_cache[i] = NULL;
00676           ++i;
00677         }
00678 
00679       message_cache_shutdown_registered = TRUE;
00680     }
00681 
00682   _dbus_assert (message_cache_count >= 0);
00683 
00684   if (!_dbus_enable_message_cache ())
00685     goto out;
00686 
00687   if ((_dbus_string_get_length (&message->header.data) +
00688        _dbus_string_get_length (&message->body)) >
00689       MAX_MESSAGE_SIZE_TO_CACHE)
00690     goto out;
00691 
00692   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
00693     goto out;
00694 
00695   /* Find empty slot */
00696   i = 0;
00697   while (message_cache[i] != NULL)
00698     ++i;
00699 
00700   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
00701 
00702   _dbus_assert (message_cache[i] == NULL);
00703   message_cache[i] = message;
00704   message_cache_count += 1;
00705   was_cached = TRUE;
00706 #ifndef DBUS_DISABLE_CHECKS
00707   message->in_cache = TRUE;
00708 #endif
00709 
00710  out:
00711   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
00712 
00713   _DBUS_UNLOCK (message_cache);
00714   
00715   if (!was_cached)
00716     dbus_message_finalize (message);
00717 }
00718 
00719 #ifndef DBUS_DISABLE_CHECKS
00720 static dbus_bool_t
00721 _dbus_message_iter_check (DBusMessageRealIter *iter)
00722 {
00723   char byte_order;
00724 
00725   if (iter == NULL)
00726     {
00727       _dbus_warn_check_failed ("dbus message iterator is NULL\n");
00728       return FALSE;
00729     }
00730 
00731   byte_order = _dbus_header_get_byte_order (&iter->message->header);
00732 
00733   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
00734     {
00735       if (iter->u.reader.byte_order != byte_order)
00736         {
00737           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
00738           return FALSE;
00739         }
00740       /* because we swap the message into compiler order when you init an iter */
00741       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
00742     }
00743   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
00744     {
00745       if (iter->u.writer.byte_order != byte_order)
00746         {
00747           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
00748           return FALSE;
00749         }
00750       /* because we swap the message into compiler order when you init an iter */
00751       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
00752     }
00753   else
00754     {
00755       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
00756       return FALSE;
00757     }
00758 
00759   if (iter->changed_stamp != iter->message->changed_stamp)
00760     {
00761       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
00762       return FALSE;
00763     }
00764 
00765   return TRUE;
00766 }
00767 #endif /* DBUS_DISABLE_CHECKS */
00768 
00783 dbus_bool_t
00784 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
00785                                     DBusError       *error,
00786                                     int              first_arg_type,
00787                                     va_list          var_args)
00788 {
00789   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
00790   int spec_type, msg_type, i;
00791   dbus_bool_t retval;
00792 
00793   _dbus_assert (_dbus_message_iter_check (real));
00794 
00795   retval = FALSE;
00796 
00797   spec_type = first_arg_type;
00798   i = 0;
00799 
00800   while (spec_type != DBUS_TYPE_INVALID)
00801     {
00802       msg_type = dbus_message_iter_get_arg_type (iter);
00803 
00804       if (msg_type != spec_type)
00805         {
00806           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00807                           "Argument %d is specified to be of type \"%s\", but "
00808                           "is actually of type \"%s\"\n", i,
00809                           _dbus_type_to_string (spec_type),
00810                           _dbus_type_to_string (msg_type));
00811 
00812           goto out;
00813         }
00814 
00815       if (spec_type == DBUS_TYPE_UNIX_FD)
00816         {
00817 #ifdef HAVE_UNIX_FD_PASSING
00818           DBusBasicValue idx;
00819           int *pfd, nfd;
00820 
00821           pfd = va_arg (var_args, int*);
00822           _dbus_assert(pfd);
00823 
00824           _dbus_type_reader_read_basic(&real->u.reader, &idx);
00825 
00826           if (idx.u32 >= real->message->n_unix_fds)
00827             {
00828               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
00829                               "Message refers to file descriptor at index %i,"
00830                               "but has only %i descriptors attached.\n",
00831                               idx.u32,
00832                               real->message->n_unix_fds);
00833               goto out;
00834             }
00835 
00836           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
00837             goto out;
00838 
00839           *pfd = nfd;
00840 #else
00841           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
00842                           "Platform does not support file desciptor passing.\n");
00843           goto out;
00844 #endif
00845         }
00846       else if (dbus_type_is_basic (spec_type))
00847         {
00848           DBusBasicValue *ptr;
00849 
00850           ptr = va_arg (var_args, DBusBasicValue*);
00851 
00852           _dbus_assert (ptr != NULL);
00853 
00854           _dbus_type_reader_read_basic (&real->u.reader,
00855                                         ptr);
00856         }
00857       else if (spec_type == DBUS_TYPE_ARRAY)
00858         {
00859           int element_type;
00860           int spec_element_type;
00861           const DBusBasicValue **ptr;
00862           int *n_elements_p;
00863           DBusTypeReader array;
00864 
00865           spec_element_type = va_arg (var_args, int);
00866           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
00867 
00868           if (spec_element_type != element_type)
00869             {
00870               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00871                               "Argument %d is specified to be an array of \"%s\", but "
00872                               "is actually an array of \"%s\"\n",
00873                               i,
00874                               _dbus_type_to_string (spec_element_type),
00875                               _dbus_type_to_string (element_type));
00876 
00877               goto out;
00878             }
00879 
00880           if (dbus_type_is_fixed (spec_element_type) &&
00881               element_type != DBUS_TYPE_UNIX_FD)
00882             {
00883               ptr = va_arg (var_args, const DBusBasicValue**);
00884               n_elements_p = va_arg (var_args, int*);
00885 
00886               _dbus_assert (ptr != NULL);
00887               _dbus_assert (n_elements_p != NULL);
00888 
00889               _dbus_type_reader_recurse (&real->u.reader, &array);
00890 
00891               _dbus_type_reader_read_fixed_multi (&array,
00892                                                   (void *) ptr, n_elements_p);
00893             }
00894           else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
00895             {
00896               char ***str_array_p;
00897               int n_elements;
00898               char **str_array;
00899 
00900               str_array_p = va_arg (var_args, char***);
00901               n_elements_p = va_arg (var_args, int*);
00902 
00903               _dbus_assert (str_array_p != NULL);
00904               _dbus_assert (n_elements_p != NULL);
00905 
00906               /* Count elements in the array */
00907               _dbus_type_reader_recurse (&real->u.reader, &array);
00908 
00909               n_elements = 0;
00910               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
00911                 {
00912                   ++n_elements;
00913                   _dbus_type_reader_next (&array);
00914                 }
00915 
00916               str_array = dbus_new0 (char*, n_elements + 1);
00917               if (str_array == NULL)
00918                 {
00919                   _DBUS_SET_OOM (error);
00920                   goto out;
00921                 }
00922 
00923               /* Now go through and dup each string */
00924               _dbus_type_reader_recurse (&real->u.reader, &array);
00925 
00926               i = 0;
00927               while (i < n_elements)
00928                 {
00929                   const char *s;
00930                   _dbus_type_reader_read_basic (&array,
00931                                                 (void *) &s);
00932                   
00933                   str_array[i] = _dbus_strdup (s);
00934                   if (str_array[i] == NULL)
00935                     {
00936                       dbus_free_string_array (str_array);
00937                       _DBUS_SET_OOM (error);
00938                       goto out;
00939                     }
00940                   
00941                   ++i;
00942                   
00943                   if (!_dbus_type_reader_next (&array))
00944                     _dbus_assert (i == n_elements);
00945                 }
00946 
00947               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
00948               _dbus_assert (i == n_elements);
00949               _dbus_assert (str_array[i] == NULL);
00950 
00951               *str_array_p = str_array;
00952               *n_elements_p = n_elements;
00953             }
00954 #ifndef DBUS_DISABLE_CHECKS
00955           else
00956             {
00957               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
00958                           _DBUS_FUNCTION_NAME);
00959               goto out;
00960             }
00961 #endif
00962         }
00963 #ifndef DBUS_DISABLE_CHECKS
00964       else
00965         {
00966           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
00967                       _DBUS_FUNCTION_NAME);
00968           goto out;
00969         }
00970 #endif
00971 
00972       spec_type = va_arg (var_args, int);
00973       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
00974         {
00975           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
00976                           "Message has only %d arguments, but more were expected", i);
00977           goto out;
00978         }
00979 
00980       i++;
00981     }
00982 
00983   retval = TRUE;
00984 
00985  out:
00986 
00987   return retval;
00988 }
00989 
01048 dbus_uint32_t
01049 dbus_message_get_serial (DBusMessage *message)
01050 {
01051   _dbus_return_val_if_fail (message != NULL, 0);
01052 
01053   return _dbus_header_get_serial (&message->header);
01054 }
01055 
01064 dbus_bool_t
01065 dbus_message_set_reply_serial (DBusMessage   *message,
01066                                dbus_uint32_t  reply_serial)
01067 {
01068   _dbus_return_val_if_fail (message != NULL, FALSE);
01069   _dbus_return_val_if_fail (!message->locked, FALSE);
01070   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
01071 
01072   return _dbus_header_set_field_basic (&message->header,
01073                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
01074                                        DBUS_TYPE_UINT32,
01075                                        &reply_serial);
01076 }
01077 
01084 dbus_uint32_t
01085 dbus_message_get_reply_serial  (DBusMessage *message)
01086 {
01087   dbus_uint32_t v_UINT32;
01088 
01089   _dbus_return_val_if_fail (message != NULL, 0);
01090 
01091   if (_dbus_header_get_field_basic (&message->header,
01092                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
01093                                     DBUS_TYPE_UINT32,
01094                                     &v_UINT32))
01095     return v_UINT32;
01096   else
01097     return 0;
01098 }
01099 
01100 static void
01101 dbus_message_finalize (DBusMessage *message)
01102 {
01103   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01104 
01105   /* This calls application callbacks! */
01106   _dbus_data_slot_list_free (&message->slot_list);
01107 
01108   _dbus_list_foreach (&message->counters,
01109                       free_counter, message);
01110   _dbus_list_clear (&message->counters);
01111 
01112   _dbus_header_free (&message->header);
01113   _dbus_string_free (&message->body);
01114 
01115 #ifdef HAVE_UNIX_FD_PASSING
01116   close_unix_fds(message->unix_fds, &message->n_unix_fds);
01117   dbus_free(message->unix_fds);
01118 #endif
01119 
01120   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
01121 
01122   dbus_free (message);
01123 }
01124 
01125 static DBusMessage*
01126 dbus_message_new_empty_header (void)
01127 {
01128   DBusMessage *message;
01129   dbus_bool_t from_cache;
01130 
01131   message = dbus_message_get_cached ();
01132 
01133   if (message != NULL)
01134     {
01135       from_cache = TRUE;
01136     }
01137   else
01138     {
01139       from_cache = FALSE;
01140       message = dbus_new0 (DBusMessage, 1);
01141       if (message == NULL)
01142         return NULL;
01143 #ifndef DBUS_DISABLE_CHECKS
01144       message->generation = _dbus_current_generation;
01145 #endif
01146 
01147 #ifdef HAVE_UNIX_FD_PASSING
01148       message->unix_fds = NULL;
01149       message->n_unix_fds_allocated = 0;
01150 #endif
01151     }
01152 
01153   _dbus_atomic_inc (&message->refcount);
01154 
01155   _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
01156 
01157   message->locked = FALSE;
01158 #ifndef DBUS_DISABLE_CHECKS
01159   message->in_cache = FALSE;
01160 #endif
01161   message->counters = NULL;
01162   message->size_counter_delta = 0;
01163   message->changed_stamp = 0;
01164 
01165 #ifdef HAVE_UNIX_FD_PASSING
01166   message->n_unix_fds = 0;
01167   message->n_unix_fds_allocated = 0;
01168   message->unix_fd_counter_delta = 0;
01169 #endif
01170 
01171   if (!from_cache)
01172     _dbus_data_slot_list_init (&message->slot_list);
01173 
01174   if (from_cache)
01175     {
01176       _dbus_header_reinit (&message->header);
01177       _dbus_string_set_length (&message->body, 0);
01178     }
01179   else
01180     {
01181       if (!_dbus_header_init (&message->header))
01182         {
01183           dbus_free (message);
01184           return NULL;
01185         }
01186 
01187       if (!_dbus_string_init_preallocated (&message->body, 32))
01188         {
01189           _dbus_header_free (&message->header);
01190           dbus_free (message);
01191           return NULL;
01192         }
01193     }
01194 
01195   return message;
01196 }
01197 
01210 DBusMessage*
01211 dbus_message_new (int message_type)
01212 {
01213   DBusMessage *message;
01214 
01215   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01216 
01217   message = dbus_message_new_empty_header ();
01218   if (message == NULL)
01219     return NULL;
01220 
01221   if (!_dbus_header_create (&message->header,
01222                             DBUS_COMPILER_BYTE_ORDER,
01223                             message_type,
01224                             NULL, NULL, NULL, NULL, NULL))
01225     {
01226       dbus_message_unref (message);
01227       return NULL;
01228     }
01229 
01230   return message;
01231 }
01232 
01254 DBusMessage*
01255 dbus_message_new_method_call (const char *destination,
01256                               const char *path,
01257                               const char *interface,
01258                               const char *method)
01259 {
01260   DBusMessage *message;
01261 
01262   _dbus_return_val_if_fail (path != NULL, NULL);
01263   _dbus_return_val_if_fail (method != NULL, NULL);
01264   _dbus_return_val_if_fail (destination == NULL ||
01265                             _dbus_check_is_valid_bus_name (destination), NULL);
01266   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01267   _dbus_return_val_if_fail (interface == NULL ||
01268                             _dbus_check_is_valid_interface (interface), NULL);
01269   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
01270 
01271   message = dbus_message_new_empty_header ();
01272   if (message == NULL)
01273     return NULL;
01274 
01275   if (!_dbus_header_create (&message->header,
01276                             DBUS_COMPILER_BYTE_ORDER,
01277                             DBUS_MESSAGE_TYPE_METHOD_CALL,
01278                             destination, path, interface, method, NULL))
01279     {
01280       dbus_message_unref (message);
01281       return NULL;
01282     }
01283 
01284   return message;
01285 }
01286 
01294 DBusMessage*
01295 dbus_message_new_method_return (DBusMessage *method_call)
01296 {
01297   DBusMessage *message;
01298   const char *sender;
01299 
01300   _dbus_return_val_if_fail (method_call != NULL, NULL);
01301 
01302   sender = dbus_message_get_sender (method_call);
01303 
01304   /* sender is allowed to be null here in peer-to-peer case */
01305 
01306   message = dbus_message_new_empty_header ();
01307   if (message == NULL)
01308     return NULL;
01309 
01310   if (!_dbus_header_create (&message->header,
01311                             DBUS_COMPILER_BYTE_ORDER,
01312                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
01313                             sender, NULL, NULL, NULL, NULL))
01314     {
01315       dbus_message_unref (message);
01316       return NULL;
01317     }
01318 
01319   dbus_message_set_no_reply (message, TRUE);
01320 
01321   if (!dbus_message_set_reply_serial (message,
01322                                       dbus_message_get_serial (method_call)))
01323     {
01324       dbus_message_unref (message);
01325       return NULL;
01326     }
01327 
01328   return message;
01329 }
01330 
01345 DBusMessage*
01346 dbus_message_new_signal (const char *path,
01347                          const char *interface,
01348                          const char *name)
01349 {
01350   DBusMessage *message;
01351 
01352   _dbus_return_val_if_fail (path != NULL, NULL);
01353   _dbus_return_val_if_fail (interface != NULL, NULL);
01354   _dbus_return_val_if_fail (name != NULL, NULL);
01355   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
01356   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
01357   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
01358 
01359   message = dbus_message_new_empty_header ();
01360   if (message == NULL)
01361     return NULL;
01362 
01363   if (!_dbus_header_create (&message->header,
01364                             DBUS_COMPILER_BYTE_ORDER,
01365                             DBUS_MESSAGE_TYPE_SIGNAL,
01366                             NULL, path, interface, name, NULL))
01367     {
01368       dbus_message_unref (message);
01369       return NULL;
01370     }
01371 
01372   dbus_message_set_no_reply (message, TRUE);
01373 
01374   return message;
01375 }
01376 
01391 DBusMessage*
01392 dbus_message_new_error (DBusMessage *reply_to,
01393                         const char  *error_name,
01394                         const char  *error_message)
01395 {
01396   DBusMessage *message;
01397   const char *sender;
01398   DBusMessageIter iter;
01399 
01400   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01401   _dbus_return_val_if_fail (error_name != NULL, NULL);
01402   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01403 
01404   sender = dbus_message_get_sender (reply_to);
01405 
01406   /* sender may be NULL for non-message-bus case or
01407    * when the message bus is dealing with an unregistered
01408    * connection.
01409    */
01410   message = dbus_message_new_empty_header ();
01411   if (message == NULL)
01412     return NULL;
01413 
01414   if (!_dbus_header_create (&message->header,
01415                             DBUS_COMPILER_BYTE_ORDER,
01416                             DBUS_MESSAGE_TYPE_ERROR,
01417                             sender, NULL, NULL, NULL, error_name))
01418     {
01419       dbus_message_unref (message);
01420       return NULL;
01421     }
01422 
01423   dbus_message_set_no_reply (message, TRUE);
01424 
01425   if (!dbus_message_set_reply_serial (message,
01426                                       dbus_message_get_serial (reply_to)))
01427     {
01428       dbus_message_unref (message);
01429       return NULL;
01430     }
01431 
01432   if (error_message != NULL)
01433     {
01434       dbus_message_iter_init_append (message, &iter);
01435       if (!dbus_message_iter_append_basic (&iter,
01436                                            DBUS_TYPE_STRING,
01437                                            &error_message))
01438         {
01439           dbus_message_unref (message);
01440           return NULL;
01441         }
01442     }
01443 
01444   return message;
01445 }
01446 
01463 DBusMessage*
01464 dbus_message_new_error_printf (DBusMessage *reply_to,
01465                                const char  *error_name,
01466                                const char  *error_format,
01467                                ...)
01468 {
01469   va_list args;
01470   DBusString str;
01471   DBusMessage *message;
01472 
01473   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01474   _dbus_return_val_if_fail (error_name != NULL, NULL);
01475   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
01476 
01477   if (!_dbus_string_init (&str))
01478     return NULL;
01479 
01480   va_start (args, error_format);
01481 
01482   if (_dbus_string_append_printf_valist (&str, error_format, args))
01483     message = dbus_message_new_error (reply_to, error_name,
01484                                       _dbus_string_get_const_data (&str));
01485   else
01486     message = NULL;
01487 
01488   _dbus_string_free (&str);
01489 
01490   va_end (args);
01491 
01492   return message;
01493 }
01494 
01495 
01508 DBusMessage *
01509 dbus_message_copy (const DBusMessage *message)
01510 {
01511   DBusMessage *retval;
01512 
01513   _dbus_return_val_if_fail (message != NULL, NULL);
01514 
01515   retval = dbus_new0 (DBusMessage, 1);
01516   if (retval == NULL)
01517     return NULL;
01518 
01519   _dbus_atomic_inc (&retval->refcount);
01520 
01521   retval->locked = FALSE;
01522 #ifndef DBUS_DISABLE_CHECKS
01523   retval->generation = message->generation;
01524 #endif
01525 
01526   if (!_dbus_header_copy (&message->header, &retval->header))
01527     {
01528       dbus_free (retval);
01529       return NULL;
01530     }
01531 
01532   if (!_dbus_string_init_preallocated (&retval->body,
01533                                        _dbus_string_get_length (&message->body)))
01534     {
01535       _dbus_header_free (&retval->header);
01536       dbus_free (retval);
01537       return NULL;
01538     }
01539 
01540   if (!_dbus_string_copy (&message->body, 0,
01541                           &retval->body, 0))
01542     goto failed_copy;
01543 
01544 #ifdef HAVE_UNIX_FD_PASSING
01545   retval->unix_fds = dbus_new(int, message->n_unix_fds);
01546   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
01547     goto failed_copy;
01548 
01549   retval->n_unix_fds_allocated = message->n_unix_fds;
01550 
01551   for (retval->n_unix_fds = 0;
01552        retval->n_unix_fds < message->n_unix_fds;
01553        retval->n_unix_fds++)
01554     {
01555       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
01556 
01557       if (retval->unix_fds[retval->n_unix_fds] < 0)
01558         goto failed_copy;
01559     }
01560 
01561 #endif
01562 
01563   _dbus_message_trace_ref (retval, 0, 1, "copy");
01564   return retval;
01565 
01566  failed_copy:
01567   _dbus_header_free (&retval->header);
01568   _dbus_string_free (&retval->body);
01569 
01570 #ifdef HAVE_UNIX_FD_PASSING
01571   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
01572   dbus_free(retval->unix_fds);
01573 #endif
01574 
01575   dbus_free (retval);
01576 
01577   return NULL;
01578 }
01579 
01580 
01588 DBusMessage *
01589 dbus_message_ref (DBusMessage *message)
01590 {
01591   dbus_int32_t old_refcount;
01592 
01593   _dbus_return_val_if_fail (message != NULL, NULL);
01594   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
01595   _dbus_return_val_if_fail (!message->in_cache, NULL);
01596 
01597   old_refcount = _dbus_atomic_inc (&message->refcount);
01598   _dbus_assert (old_refcount >= 1);
01599   _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
01600 
01601   return message;
01602 }
01603 
01611 void
01612 dbus_message_unref (DBusMessage *message)
01613 {
01614  dbus_int32_t old_refcount;
01615 
01616   _dbus_return_if_fail (message != NULL);
01617   _dbus_return_if_fail (message->generation == _dbus_current_generation);
01618   _dbus_return_if_fail (!message->in_cache);
01619 
01620   old_refcount = _dbus_atomic_dec (&message->refcount);
01621 
01622   _dbus_assert (old_refcount >= 1);
01623 
01624   _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
01625 
01626   if (old_refcount == 1)
01627     {
01628       /* Calls application callbacks! */
01629       dbus_message_cache_or_finalize (message);
01630     }
01631 }
01632 
01643 int
01644 dbus_message_get_type (DBusMessage *message)
01645 {
01646   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
01647 
01648   return _dbus_header_get_message_type (&message->header);
01649 }
01650 
01713 dbus_bool_t
01714 dbus_message_append_args (DBusMessage *message,
01715                           int          first_arg_type,
01716                           ...)
01717 {
01718   dbus_bool_t retval;
01719   va_list var_args;
01720 
01721   _dbus_return_val_if_fail (message != NULL, FALSE);
01722 
01723   va_start (var_args, first_arg_type);
01724   retval = dbus_message_append_args_valist (message,
01725                                             first_arg_type,
01726                                             var_args);
01727   va_end (var_args);
01728 
01729   return retval;
01730 }
01731 
01745 dbus_bool_t
01746 dbus_message_append_args_valist (DBusMessage *message,
01747                                  int          first_arg_type,
01748                                  va_list      var_args)
01749 {
01750   int type;
01751   DBusMessageIter iter;
01752 
01753   _dbus_return_val_if_fail (message != NULL, FALSE);
01754 
01755   type = first_arg_type;
01756 
01757   dbus_message_iter_init_append (message, &iter);
01758 
01759   while (type != DBUS_TYPE_INVALID)
01760     {
01761       if (dbus_type_is_basic (type))
01762         {
01763           const DBusBasicValue *value;
01764           value = va_arg (var_args, const DBusBasicValue*);
01765 
01766           if (!dbus_message_iter_append_basic (&iter,
01767                                                type,
01768                                                value))
01769             goto failed;
01770         }
01771       else if (type == DBUS_TYPE_ARRAY)
01772         {
01773           int element_type;
01774           DBusMessageIter array;
01775           char buf[2];
01776 
01777           element_type = va_arg (var_args, int);
01778               
01779           buf[0] = element_type;
01780           buf[1] = '\0';
01781           if (!dbus_message_iter_open_container (&iter,
01782                                                  DBUS_TYPE_ARRAY,
01783                                                  buf,
01784                                                  &array))
01785             goto failed;
01786 
01787           if (dbus_type_is_fixed (element_type) &&
01788               element_type != DBUS_TYPE_UNIX_FD)
01789             {
01790               const DBusBasicValue **value;
01791               int n_elements;
01792 
01793               value = va_arg (var_args, const DBusBasicValue**);
01794               n_elements = va_arg (var_args, int);
01795               
01796               if (!dbus_message_iter_append_fixed_array (&array,
01797                                                          element_type,
01798                                                          value,
01799                                                          n_elements)) {
01800                 dbus_message_iter_abandon_container (&iter, &array);
01801                 goto failed;
01802               }
01803             }
01804           else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
01805             {
01806               const char ***value_p;
01807               const char **value;
01808               int n_elements;
01809               int i;
01810               
01811               value_p = va_arg (var_args, const char***);
01812               n_elements = va_arg (var_args, int);
01813 
01814               value = *value_p;
01815               
01816               i = 0;
01817               while (i < n_elements)
01818                 {
01819                   if (!dbus_message_iter_append_basic (&array,
01820                                                        element_type,
01821                                                        &value[i])) {
01822                     dbus_message_iter_abandon_container (&iter, &array);
01823                     goto failed;
01824                   }
01825                   ++i;
01826                 }
01827             }
01828           else
01829             {
01830               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
01831                           _dbus_type_to_string (element_type),
01832                           _DBUS_FUNCTION_NAME);
01833               goto failed;
01834             }
01835 
01836           if (!dbus_message_iter_close_container (&iter, &array))
01837             goto failed;
01838         }
01839 #ifndef DBUS_DISABLE_CHECKS
01840       else
01841         {
01842           _dbus_warn ("type %s isn't supported yet in %s\n",
01843                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
01844           goto failed;
01845         }
01846 #endif
01847 
01848       type = va_arg (var_args, int);
01849     }
01850 
01851   return TRUE;
01852 
01853  failed:
01854   return FALSE;
01855 }
01856 
01901 dbus_bool_t
01902 dbus_message_get_args (DBusMessage     *message,
01903                        DBusError       *error,
01904                        int              first_arg_type,
01905                        ...)
01906 {
01907   dbus_bool_t retval;
01908   va_list var_args;
01909 
01910   _dbus_return_val_if_fail (message != NULL, FALSE);
01911   _dbus_return_val_if_error_is_set (error, FALSE);
01912 
01913   va_start (var_args, first_arg_type);
01914   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
01915   va_end (var_args);
01916 
01917   return retval;
01918 }
01919 
01930 dbus_bool_t
01931 dbus_message_get_args_valist (DBusMessage     *message,
01932                               DBusError       *error,
01933                               int              first_arg_type,
01934                               va_list          var_args)
01935 {
01936   DBusMessageIter iter;
01937 
01938   _dbus_return_val_if_fail (message != NULL, FALSE);
01939   _dbus_return_val_if_error_is_set (error, FALSE);
01940 
01941   dbus_message_iter_init (message, &iter);
01942   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
01943 }
01944 
01945 static void
01946 _dbus_message_iter_init_common (DBusMessage         *message,
01947                                 DBusMessageRealIter *real,
01948                                 int                  iter_type)
01949 {
01950   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
01951 
01952   /* Since the iterator will read or write who-knows-what from the
01953    * message, we need to get in the right byte order
01954    */
01955   ensure_byte_order (message);
01956   
01957   real->message = message;
01958   real->changed_stamp = message->changed_stamp;
01959   real->iter_type = iter_type;
01960   real->sig_refcount = 0;
01961 }
01962 
01985 dbus_bool_t
01986 dbus_message_iter_init (DBusMessage     *message,
01987                         DBusMessageIter *iter)
01988 {
01989   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
01990   const DBusString *type_str;
01991   int type_pos;
01992 
01993   _dbus_return_val_if_fail (message != NULL, FALSE);
01994   _dbus_return_val_if_fail (iter != NULL, FALSE);
01995 
01996   get_const_signature (&message->header, &type_str, &type_pos);
01997 
01998   _dbus_message_iter_init_common (message, real,
01999                                   DBUS_MESSAGE_ITER_TYPE_READER);
02000 
02001   _dbus_type_reader_init (&real->u.reader,
02002                           _dbus_header_get_byte_order (&message->header),
02003                           type_str, type_pos,
02004                           &message->body,
02005                           0);
02006 
02007   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
02008 }
02009 
02016 dbus_bool_t
02017 dbus_message_iter_has_next (DBusMessageIter *iter)
02018 {
02019   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02020 
02021   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02022   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02023 
02024   return _dbus_type_reader_has_next (&real->u.reader);
02025 }
02026 
02035 dbus_bool_t
02036 dbus_message_iter_next (DBusMessageIter *iter)
02037 {
02038   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02039 
02040   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
02041   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02042 
02043   return _dbus_type_reader_next (&real->u.reader);
02044 }
02045 
02060 int
02061 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02062 {
02063   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02064 
02065   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02066   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
02067 
02068   return _dbus_type_reader_get_current_type (&real->u.reader);
02069 }
02070 
02079 int
02080 dbus_message_iter_get_element_type (DBusMessageIter *iter)
02081 {
02082   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02083 
02084   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02085   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
02086   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
02087 
02088   return _dbus_type_reader_get_element_type (&real->u.reader);
02089 }
02090 
02116 void
02117 dbus_message_iter_recurse (DBusMessageIter  *iter,
02118                            DBusMessageIter  *sub)
02119 {
02120   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02121   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02122 
02123   _dbus_return_if_fail (_dbus_message_iter_check (real));
02124   _dbus_return_if_fail (sub != NULL);
02125 
02126   *real_sub = *real;
02127   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
02128 }
02129 
02141 char *
02142 dbus_message_iter_get_signature (DBusMessageIter *iter)
02143 {
02144   const DBusString *sig;
02145   DBusString retstr;
02146   char *ret;
02147   int start, len;
02148   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02149 
02150   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
02151 
02152   if (!_dbus_string_init (&retstr))
02153     return NULL;
02154 
02155   _dbus_type_reader_get_signature (&real->u.reader, &sig,
02156                                    &start, &len);
02157   if (!_dbus_string_append_len (&retstr,
02158                                 _dbus_string_get_const_data (sig) + start,
02159                                 len))
02160     return NULL;
02161   if (!_dbus_string_steal_data (&retstr, &ret))
02162     return NULL;
02163   _dbus_string_free (&retstr);
02164   return ret;
02165 }
02166 
02214 void
02215 dbus_message_iter_get_basic (DBusMessageIter  *iter,
02216                              void             *value)
02217 {
02218   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02219 
02220   _dbus_return_if_fail (_dbus_message_iter_check (real));
02221   _dbus_return_if_fail (value != NULL);
02222 
02223   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
02224     {
02225 #ifdef HAVE_UNIX_FD_PASSING
02226       DBusBasicValue idx;
02227 
02228       _dbus_type_reader_read_basic(&real->u.reader, &idx);
02229 
02230       if (idx.u32 >= real->message->n_unix_fds) {
02231         /* Hmm, we cannot really signal an error here, so let's make
02232            sure to return an invalid fd. */
02233         *((int*) value) = -1;
02234         return;
02235       }
02236 
02237       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
02238 #else
02239       *((int*) value) = -1;
02240 #endif
02241     }
02242   else
02243     {
02244       _dbus_type_reader_read_basic (&real->u.reader,
02245                                     value);
02246     }
02247 }
02248 
02267 int
02268 dbus_message_iter_get_array_len (DBusMessageIter *iter)
02269 {
02270   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02271 
02272   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
02273 
02274   return _dbus_type_reader_get_array_length (&real->u.reader);
02275 }
02276 
02312 void
02313 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
02314                                    void             *value,
02315                                    int              *n_elements)
02316 {
02317   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02318 #ifndef DBUS_DISABLE_CHECKS
02319   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
02320 
02321   _dbus_return_if_fail (_dbus_message_iter_check (real));
02322   _dbus_return_if_fail (value != NULL);
02323   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
02324                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
02325 #endif
02326 
02327   _dbus_type_reader_read_fixed_multi (&real->u.reader,
02328                                       value, n_elements);
02329 }
02330 
02342 void
02343 dbus_message_iter_init_append (DBusMessage     *message,
02344                                DBusMessageIter *iter)
02345 {
02346   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02347 
02348   _dbus_return_if_fail (message != NULL);
02349   _dbus_return_if_fail (iter != NULL);
02350 
02351   _dbus_message_iter_init_common (message, real,
02352                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
02353 
02354   /* We create the signature string and point iterators at it "on demand"
02355    * when a value is actually appended. That means that init() never fails
02356    * due to OOM.
02357    */
02358   _dbus_type_writer_init_types_delayed (&real->u.writer,
02359                                         _dbus_header_get_byte_order (&message->header),
02360                                         &message->body,
02361                                         _dbus_string_get_length (&message->body));
02362 }
02363 
02372 static dbus_bool_t
02373 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
02374 {
02375   DBusString *str;
02376   const DBusString *current_sig;
02377   int current_sig_pos;
02378 
02379   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02380 
02381   if (real->u.writer.type_str != NULL)
02382     {
02383       _dbus_assert (real->sig_refcount > 0);
02384       real->sig_refcount += 1;
02385       return TRUE;
02386     }
02387 
02388   str = dbus_new (DBusString, 1);
02389   if (str == NULL)
02390     return FALSE;
02391 
02392   if (!_dbus_header_get_field_raw (&real->message->header,
02393                                    DBUS_HEADER_FIELD_SIGNATURE,
02394                                    &current_sig, &current_sig_pos))
02395     current_sig = NULL;
02396 
02397   if (current_sig)
02398     {
02399       int current_len;
02400 
02401       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
02402       current_sig_pos += 1; /* move on to sig data */
02403 
02404       if (!_dbus_string_init_preallocated (str, current_len + 4))
02405         {
02406           dbus_free (str);
02407           return FALSE;
02408         }
02409 
02410       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
02411                                   str, 0))
02412         {
02413           _dbus_string_free (str);
02414           dbus_free (str);
02415           return FALSE;
02416         }
02417     }
02418   else
02419     {
02420       if (!_dbus_string_init_preallocated (str, 4))
02421         {
02422           dbus_free (str);
02423           return FALSE;
02424         }
02425     }
02426 
02427   real->sig_refcount = 1;
02428 
02429   _dbus_type_writer_add_types (&real->u.writer,
02430                                str, _dbus_string_get_length (str));
02431   return TRUE;
02432 }
02433 
02443 static dbus_bool_t
02444 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
02445 {
02446   DBusString *str;
02447   const char *v_STRING;
02448   dbus_bool_t retval;
02449 
02450   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02451   _dbus_assert (real->u.writer.type_str != NULL);
02452   _dbus_assert (real->sig_refcount > 0);
02453 
02454   real->sig_refcount -= 1;
02455 
02456   if (real->sig_refcount > 0)
02457     return TRUE;
02458   _dbus_assert (real->sig_refcount == 0);
02459 
02460   retval = TRUE;
02461 
02462   str = real->u.writer.type_str;
02463 
02464   v_STRING = _dbus_string_get_const_data (str);
02465   if (!_dbus_header_set_field_basic (&real->message->header,
02466                                      DBUS_HEADER_FIELD_SIGNATURE,
02467                                      DBUS_TYPE_SIGNATURE,
02468                                      &v_STRING))
02469     retval = FALSE;
02470 
02471   _dbus_type_writer_remove_types (&real->u.writer);
02472   _dbus_string_free (str);
02473   dbus_free (str);
02474 
02475   return retval;
02476 }
02477 
02485 static void
02486 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
02487 {
02488   DBusString *str;
02489 
02490   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02491   _dbus_assert (real->u.writer.type_str != NULL);
02492   _dbus_assert (real->sig_refcount > 0);
02493 
02494   real->sig_refcount -= 1;
02495 
02496   if (real->sig_refcount > 0)
02497     return;
02498   _dbus_assert (real->sig_refcount == 0);
02499 
02500   str = real->u.writer.type_str;
02501 
02502   _dbus_type_writer_remove_types (&real->u.writer);
02503   _dbus_string_free (str);
02504   dbus_free (str);
02505 }
02506 
02507 #ifndef DBUS_DISABLE_CHECKS
02508 static dbus_bool_t
02509 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
02510 {
02511   if (!_dbus_message_iter_check (iter))
02512     return FALSE;
02513 
02514   if (iter->message->locked)
02515     {
02516       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
02517       return FALSE;
02518     }
02519 
02520   return TRUE;
02521 }
02522 #endif /* DBUS_DISABLE_CHECKS */
02523 
02524 #ifdef HAVE_UNIX_FD_PASSING
02525 static int *
02526 expand_fd_array(DBusMessage *m,
02527                 unsigned     n)
02528 {
02529   _dbus_assert(m);
02530 
02531   /* This makes space for adding n new fds to the array and returns a
02532      pointer to the place were the first fd should be put. */
02533 
02534   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
02535     {
02536       unsigned k;
02537       int *p;
02538 
02539       /* Make twice as much space as necessary */
02540       k = (m->n_unix_fds + n) * 2;
02541 
02542       /* Allocate at least four */
02543       if (k < 4)
02544         k = 4;
02545 
02546       p = dbus_realloc(m->unix_fds, k * sizeof(int));
02547       if (p == NULL)
02548         return NULL;
02549 
02550       m->unix_fds = p;
02551       m->n_unix_fds_allocated = k;
02552     }
02553 
02554   return m->unix_fds + m->n_unix_fds;
02555 }
02556 #endif
02557 
02577 dbus_bool_t
02578 dbus_message_iter_append_basic (DBusMessageIter *iter,
02579                                 int              type,
02580                                 const void      *value)
02581 {
02582   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02583   dbus_bool_t ret;
02584 
02585   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02586   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02587   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
02588   _dbus_return_val_if_fail (value != NULL, FALSE);
02589 
02590 #ifndef DBUS_DISABLE_CHECKS
02591   switch (type)
02592     {
02593       const char * const *string_p;
02594       const dbus_bool_t *bool_p;
02595 
02596       case DBUS_TYPE_STRING:
02597         string_p = value;
02598         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
02599         break;
02600 
02601       case DBUS_TYPE_OBJECT_PATH:
02602         string_p = value;
02603         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
02604         break;
02605 
02606       case DBUS_TYPE_SIGNATURE:
02607         string_p = value;
02608         _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
02609         break;
02610 
02611       case DBUS_TYPE_BOOLEAN:
02612         bool_p = value;
02613         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
02614         break;
02615 
02616       default:
02617           {
02618             /* nothing to check, all possible values are allowed */
02619           }
02620     }
02621 #endif
02622 
02623   if (!_dbus_message_iter_open_signature (real))
02624     return FALSE;
02625 
02626   if (type == DBUS_TYPE_UNIX_FD)
02627     {
02628 #ifdef HAVE_UNIX_FD_PASSING
02629       int *fds;
02630       dbus_uint32_t u;
02631 
02632       /* First step, include the fd in the fd list of this message */
02633       if (!(fds = expand_fd_array(real->message, 1)))
02634         return FALSE;
02635 
02636       *fds = _dbus_dup(*(int*) value, NULL);
02637       if (*fds < 0)
02638         return FALSE;
02639 
02640       u = real->message->n_unix_fds;
02641 
02642       /* Second step, write the index to the fd */
02643       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
02644         _dbus_close(*fds, NULL);
02645         return FALSE;
02646       }
02647 
02648       real->message->n_unix_fds += 1;
02649       u += 1;
02650 
02651       /* Final step, update the header accordingly */
02652       ret = _dbus_header_set_field_basic (&real->message->header,
02653                                           DBUS_HEADER_FIELD_UNIX_FDS,
02654                                           DBUS_TYPE_UINT32,
02655                                           &u);
02656 
02657       /* If any of these operations fail the message is
02658          hosed. However, no memory or fds should be leaked since what
02659          has been added to message has been added to the message, and
02660          can hence be accounted for when the message is being
02661          freed. */
02662 #else
02663       ret = FALSE;
02664 #endif
02665     }
02666   else
02667     {
02668       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
02669     }
02670 
02671   if (!_dbus_message_iter_close_signature (real))
02672     ret = FALSE;
02673 
02674   return ret;
02675 }
02676 
02712 dbus_bool_t
02713 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
02714                                       int              element_type,
02715                                       const void      *value,
02716                                       int              n_elements)
02717 {
02718   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02719   dbus_bool_t ret;
02720 
02721   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02722   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02723   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
02724   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
02725   _dbus_return_val_if_fail (value != NULL, FALSE);
02726   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
02727   _dbus_return_val_if_fail (n_elements <=
02728                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
02729                             FALSE);
02730 
02731 #ifndef DBUS_DISABLE_CHECKS
02732   if (element_type == DBUS_TYPE_BOOLEAN)
02733     {
02734       const dbus_bool_t * const *bools = value;
02735       int i;
02736 
02737       for (i = 0; i < n_elements; i++)
02738         {
02739           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
02740         }
02741     }
02742 #endif
02743 
02744   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
02745 
02746   return ret;
02747 }
02748 
02770 dbus_bool_t
02771 dbus_message_iter_open_container (DBusMessageIter *iter,
02772                                   int              type,
02773                                   const char      *contained_signature,
02774                                   DBusMessageIter *sub)
02775 {
02776   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02777   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02778   DBusString contained_str;
02779 
02780   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02781   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02782   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
02783   _dbus_return_val_if_fail (sub != NULL, FALSE);
02784   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
02785                              contained_signature == NULL) ||
02786                             (type == DBUS_TYPE_DICT_ENTRY &&
02787                              contained_signature == NULL) ||
02788                             (type == DBUS_TYPE_VARIANT &&
02789                              contained_signature != NULL) ||
02790                             (type == DBUS_TYPE_ARRAY &&
02791                              contained_signature != NULL), FALSE);
02792   
02793   /* this would fail if the contained_signature is a dict entry, since
02794    * dict entries are invalid signatures standalone (they must be in
02795    * an array)
02796    */
02797   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
02798                             (contained_signature == NULL ||
02799                              _dbus_check_is_valid_signature (contained_signature)),
02800                             FALSE);
02801 
02802   if (!_dbus_message_iter_open_signature (real))
02803     return FALSE;
02804 
02805   *real_sub = *real;
02806 
02807   if (contained_signature != NULL)
02808     {
02809       _dbus_string_init_const (&contained_str, contained_signature);
02810 
02811       return _dbus_type_writer_recurse (&real->u.writer,
02812                                         type,
02813                                         &contained_str, 0,
02814                                         &real_sub->u.writer);
02815     }
02816   else
02817     {
02818       return _dbus_type_writer_recurse (&real->u.writer,
02819                                         type,
02820                                         NULL, 0,
02821                                         &real_sub->u.writer);
02822     } 
02823 }
02824 
02825 
02839 dbus_bool_t
02840 dbus_message_iter_close_container (DBusMessageIter *iter,
02841                                    DBusMessageIter *sub)
02842 {
02843   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02844   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02845   dbus_bool_t ret;
02846 
02847   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
02848   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02849   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
02850   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
02851 
02852   ret = _dbus_type_writer_unrecurse (&real->u.writer,
02853                                      &real_sub->u.writer);
02854 
02855   if (!_dbus_message_iter_close_signature (real))
02856     ret = FALSE;
02857 
02858   return ret;
02859 }
02860 
02872 void
02873 dbus_message_iter_abandon_container (DBusMessageIter *iter,
02874                                      DBusMessageIter *sub)
02875 {
02876   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02877 #ifndef DBUS_DISABLE_CHECKS
02878   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
02879 
02880   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
02881   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02882   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
02883   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
02884 #endif
02885 
02886   _dbus_message_iter_abandon_signature (real);
02887 }
02888 
02905 void
02906 dbus_message_set_no_reply (DBusMessage *message,
02907                            dbus_bool_t  no_reply)
02908 {
02909   _dbus_return_if_fail (message != NULL);
02910   _dbus_return_if_fail (!message->locked);
02911 
02912   _dbus_header_toggle_flag (&message->header,
02913                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
02914                             no_reply);
02915 }
02916 
02924 dbus_bool_t
02925 dbus_message_get_no_reply (DBusMessage *message)
02926 {
02927   _dbus_return_val_if_fail (message != NULL, FALSE);
02928 
02929   return _dbus_header_get_flag (&message->header,
02930                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
02931 }
02932 
02947 void
02948 dbus_message_set_auto_start (DBusMessage *message,
02949                              dbus_bool_t  auto_start)
02950 {
02951   _dbus_return_if_fail (message != NULL);
02952   _dbus_return_if_fail (!message->locked);
02953 
02954   _dbus_header_toggle_flag (&message->header,
02955                             DBUS_HEADER_FLAG_NO_AUTO_START,
02956                             !auto_start);
02957 }
02958 
02966 dbus_bool_t
02967 dbus_message_get_auto_start (DBusMessage *message)
02968 {
02969   _dbus_return_val_if_fail (message != NULL, FALSE);
02970 
02971   return !_dbus_header_get_flag (&message->header,
02972                                  DBUS_HEADER_FLAG_NO_AUTO_START);
02973 }
02974 
02975 
02988 dbus_bool_t
02989 dbus_message_set_path (DBusMessage   *message,
02990                        const char    *object_path)
02991 {
02992   _dbus_return_val_if_fail (message != NULL, FALSE);
02993   _dbus_return_val_if_fail (!message->locked, FALSE);
02994   _dbus_return_val_if_fail (object_path == NULL ||
02995                             _dbus_check_is_valid_path (object_path),
02996                             FALSE);
02997 
02998   return set_or_delete_string_field (message,
02999                                      DBUS_HEADER_FIELD_PATH,
03000                                      DBUS_TYPE_OBJECT_PATH,
03001                                      object_path);
03002 }
03003 
03017 const char*
03018 dbus_message_get_path (DBusMessage   *message)
03019 {
03020   const char *v;
03021 
03022   _dbus_return_val_if_fail (message != NULL, NULL);
03023 
03024   v = NULL; /* in case field doesn't exist */
03025   _dbus_header_get_field_basic (&message->header,
03026                                 DBUS_HEADER_FIELD_PATH,
03027                                 DBUS_TYPE_OBJECT_PATH,
03028                                 (void *) &v);
03029   return v;
03030 }
03031 
03041 dbus_bool_t
03042 dbus_message_has_path (DBusMessage   *message,
03043                        const char    *path)
03044 {
03045   const char *msg_path;
03046   msg_path = dbus_message_get_path (message);
03047   
03048   if (msg_path == NULL)
03049     {
03050       if (path == NULL)
03051         return TRUE;
03052       else
03053         return FALSE;
03054     }
03055 
03056   if (path == NULL)
03057     return FALSE;
03058    
03059   if (strcmp (msg_path, path) == 0)
03060     return TRUE;
03061 
03062   return FALSE;
03063 }
03064 
03085 dbus_bool_t
03086 dbus_message_get_path_decomposed (DBusMessage   *message,
03087                                   char        ***path)
03088 {
03089   const char *v;
03090 
03091   _dbus_return_val_if_fail (message != NULL, FALSE);
03092   _dbus_return_val_if_fail (path != NULL, FALSE);
03093 
03094   *path = NULL;
03095 
03096   v = dbus_message_get_path (message);
03097   if (v != NULL)
03098     {
03099       if (!_dbus_decompose_path (v, strlen (v),
03100                                  path, NULL))
03101         return FALSE;
03102     }
03103   return TRUE;
03104 }
03105 
03119 dbus_bool_t
03120 dbus_message_set_interface (DBusMessage  *message,
03121                             const char   *interface)
03122 {
03123   _dbus_return_val_if_fail (message != NULL, FALSE);
03124   _dbus_return_val_if_fail (!message->locked, FALSE);
03125   _dbus_return_val_if_fail (interface == NULL ||
03126                             _dbus_check_is_valid_interface (interface),
03127                             FALSE);
03128 
03129   return set_or_delete_string_field (message,
03130                                      DBUS_HEADER_FIELD_INTERFACE,
03131                                      DBUS_TYPE_STRING,
03132                                      interface);
03133 }
03134 
03148 const char*
03149 dbus_message_get_interface (DBusMessage *message)
03150 {
03151   const char *v;
03152 
03153   _dbus_return_val_if_fail (message != NULL, NULL);
03154 
03155   v = NULL; /* in case field doesn't exist */
03156   _dbus_header_get_field_basic (&message->header,
03157                                 DBUS_HEADER_FIELD_INTERFACE,
03158                                 DBUS_TYPE_STRING,
03159                                 (void *) &v);
03160   return v;
03161 }
03162 
03170 dbus_bool_t
03171 dbus_message_has_interface (DBusMessage   *message,
03172                             const char    *interface)
03173 {
03174   const char *msg_interface;
03175   msg_interface = dbus_message_get_interface (message);
03176    
03177   if (msg_interface == NULL)
03178     {
03179       if (interface == NULL)
03180         return TRUE;
03181       else
03182         return FALSE;
03183     }
03184 
03185   if (interface == NULL)
03186     return FALSE;
03187      
03188   if (strcmp (msg_interface, interface) == 0)
03189     return TRUE;
03190 
03191   return FALSE;
03192 
03193 }
03194 
03207 dbus_bool_t
03208 dbus_message_set_member (DBusMessage  *message,
03209                          const char   *member)
03210 {
03211   _dbus_return_val_if_fail (message != NULL, FALSE);
03212   _dbus_return_val_if_fail (!message->locked, FALSE);
03213   _dbus_return_val_if_fail (member == NULL ||
03214                             _dbus_check_is_valid_member (member),
03215                             FALSE);
03216 
03217   return set_or_delete_string_field (message,
03218                                      DBUS_HEADER_FIELD_MEMBER,
03219                                      DBUS_TYPE_STRING,
03220                                      member);
03221 }
03222 
03234 const char*
03235 dbus_message_get_member (DBusMessage *message)
03236 {
03237   const char *v;
03238 
03239   _dbus_return_val_if_fail (message != NULL, NULL);
03240 
03241   v = NULL; /* in case field doesn't exist */
03242   _dbus_header_get_field_basic (&message->header,
03243                                 DBUS_HEADER_FIELD_MEMBER,
03244                                 DBUS_TYPE_STRING,
03245                                 (void *) &v);
03246   return v;
03247 }
03248 
03256 dbus_bool_t
03257 dbus_message_has_member (DBusMessage   *message,
03258                          const char    *member)
03259 {
03260   const char *msg_member;
03261   msg_member = dbus_message_get_member (message);
03262  
03263   if (msg_member == NULL)
03264     {
03265       if (member == NULL)
03266         return TRUE;
03267       else
03268         return FALSE;
03269     }
03270 
03271   if (member == NULL)
03272     return FALSE;
03273     
03274   if (strcmp (msg_member, member) == 0)
03275     return TRUE;
03276 
03277   return FALSE;
03278 
03279 }
03280 
03292 dbus_bool_t
03293 dbus_message_set_error_name (DBusMessage  *message,
03294                              const char   *error_name)
03295 {
03296   _dbus_return_val_if_fail (message != NULL, FALSE);
03297   _dbus_return_val_if_fail (!message->locked, FALSE);
03298   _dbus_return_val_if_fail (error_name == NULL ||
03299                             _dbus_check_is_valid_error_name (error_name),
03300                             FALSE);
03301 
03302   return set_or_delete_string_field (message,
03303                                      DBUS_HEADER_FIELD_ERROR_NAME,
03304                                      DBUS_TYPE_STRING,
03305                                      error_name);
03306 }
03307 
03318 const char*
03319 dbus_message_get_error_name (DBusMessage *message)
03320 {
03321   const char *v;
03322 
03323   _dbus_return_val_if_fail (message != NULL, NULL);
03324 
03325   v = NULL; /* in case field doesn't exist */
03326   _dbus_header_get_field_basic (&message->header,
03327                                 DBUS_HEADER_FIELD_ERROR_NAME,
03328                                 DBUS_TYPE_STRING,
03329                                 (void *) &v);
03330   return v;
03331 }
03332 
03346 dbus_bool_t
03347 dbus_message_set_destination (DBusMessage  *message,
03348                               const char   *destination)
03349 {
03350   _dbus_return_val_if_fail (message != NULL, FALSE);
03351   _dbus_return_val_if_fail (!message->locked, FALSE);
03352   _dbus_return_val_if_fail (destination == NULL ||
03353                             _dbus_check_is_valid_bus_name (destination),
03354                             FALSE);
03355 
03356   return set_or_delete_string_field (message,
03357                                      DBUS_HEADER_FIELD_DESTINATION,
03358                                      DBUS_TYPE_STRING,
03359                                      destination);
03360 }
03361 
03371 const char*
03372 dbus_message_get_destination (DBusMessage *message)
03373 {
03374   const char *v;
03375 
03376   _dbus_return_val_if_fail (message != NULL, NULL);
03377 
03378   v = NULL; /* in case field doesn't exist */
03379   _dbus_header_get_field_basic (&message->header,
03380                                 DBUS_HEADER_FIELD_DESTINATION,
03381                                 DBUS_TYPE_STRING,
03382                                 (void *) &v);
03383   return v;
03384 }
03385 
03400 dbus_bool_t
03401 dbus_message_set_sender (DBusMessage  *message,
03402                          const char   *sender)
03403 {
03404   _dbus_return_val_if_fail (message != NULL, FALSE);
03405   _dbus_return_val_if_fail (!message->locked, FALSE);
03406   _dbus_return_val_if_fail (sender == NULL ||
03407                             _dbus_check_is_valid_bus_name (sender),
03408                             FALSE);
03409 
03410   return set_or_delete_string_field (message,
03411                                      DBUS_HEADER_FIELD_SENDER,
03412                                      DBUS_TYPE_STRING,
03413                                      sender);
03414 }
03415 
03431 const char*
03432 dbus_message_get_sender (DBusMessage *message)
03433 {
03434   const char *v;
03435 
03436   _dbus_return_val_if_fail (message != NULL, NULL);
03437 
03438   v = NULL; /* in case field doesn't exist */
03439   _dbus_header_get_field_basic (&message->header,
03440                                 DBUS_HEADER_FIELD_SENDER,
03441                                 DBUS_TYPE_STRING,
03442                                 (void *) &v);
03443   return v;
03444 }
03445 
03464 const char*
03465 dbus_message_get_signature (DBusMessage *message)
03466 {
03467   const DBusString *type_str;
03468   int type_pos;
03469 
03470   _dbus_return_val_if_fail (message != NULL, NULL);
03471 
03472   get_const_signature (&message->header, &type_str, &type_pos);
03473 
03474   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
03475 }
03476 
03477 static dbus_bool_t
03478 _dbus_message_has_type_interface_member (DBusMessage *message,
03479                                          int          type,
03480                                          const char  *interface,
03481                                          const char  *member)
03482 {
03483   const char *n;
03484 
03485   _dbus_assert (message != NULL);
03486   _dbus_assert (interface != NULL);
03487   _dbus_assert (member != NULL);
03488 
03489   if (dbus_message_get_type (message) != type)
03490     return FALSE;
03491 
03492   /* Optimize by checking the short member name first
03493    * instead of the longer interface name
03494    */
03495 
03496   n = dbus_message_get_member (message);
03497 
03498   if (n && strcmp (n, member) == 0)
03499     {
03500       n = dbus_message_get_interface (message);
03501 
03502       if (n == NULL || strcmp (n, interface) == 0)
03503         return TRUE;
03504     }
03505 
03506   return FALSE;
03507 }
03508 
03523 dbus_bool_t
03524 dbus_message_is_method_call (DBusMessage *message,
03525                              const char  *interface,
03526                              const char  *method)
03527 {
03528   _dbus_return_val_if_fail (message != NULL, FALSE);
03529   _dbus_return_val_if_fail (interface != NULL, FALSE);
03530   _dbus_return_val_if_fail (method != NULL, FALSE);
03531   /* don't check that interface/method are valid since it would be
03532    * expensive, and not catch many common errors
03533    */
03534 
03535   return _dbus_message_has_type_interface_member (message,
03536                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
03537                                                   interface, method);
03538 }
03539 
03551 dbus_bool_t
03552 dbus_message_is_signal (DBusMessage *message,
03553                         const char  *interface,
03554                         const char  *signal_name)
03555 {
03556   _dbus_return_val_if_fail (message != NULL, FALSE);
03557   _dbus_return_val_if_fail (interface != NULL, FALSE);
03558   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
03559   /* don't check that interface/name are valid since it would be
03560    * expensive, and not catch many common errors
03561    */
03562 
03563   return _dbus_message_has_type_interface_member (message,
03564                                                   DBUS_MESSAGE_TYPE_SIGNAL,
03565                                                   interface, signal_name);
03566 }
03567 
03578 dbus_bool_t
03579 dbus_message_is_error (DBusMessage *message,
03580                        const char  *error_name)
03581 {
03582   const char *n;
03583 
03584   _dbus_return_val_if_fail (message != NULL, FALSE);
03585   _dbus_return_val_if_fail (error_name != NULL, FALSE);
03586   /* don't check that error_name is valid since it would be expensive,
03587    * and not catch many common errors
03588    */
03589 
03590   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03591     return FALSE;
03592 
03593   n = dbus_message_get_error_name (message);
03594 
03595   if (n && strcmp (n, error_name) == 0)
03596     return TRUE;
03597   else
03598     return FALSE;
03599 }
03600 
03611 dbus_bool_t
03612 dbus_message_has_destination (DBusMessage  *message,
03613                               const char   *name)
03614 {
03615   const char *s;
03616 
03617   _dbus_return_val_if_fail (message != NULL, FALSE);
03618   _dbus_return_val_if_fail (name != NULL, FALSE);
03619   /* don't check that name is valid since it would be expensive, and
03620    * not catch many common errors
03621    */
03622 
03623   s = dbus_message_get_destination (message);
03624 
03625   if (s && strcmp (s, name) == 0)
03626     return TRUE;
03627   else
03628     return FALSE;
03629 }
03630 
03646 dbus_bool_t
03647 dbus_message_has_sender (DBusMessage  *message,
03648                          const char   *name)
03649 {
03650   const char *s;
03651 
03652   _dbus_return_val_if_fail (message != NULL, FALSE);
03653   _dbus_return_val_if_fail (name != NULL, FALSE);
03654   /* don't check that name is valid since it would be expensive, and
03655    * not catch many common errors
03656    */
03657 
03658   s = dbus_message_get_sender (message);
03659 
03660   if (s && strcmp (s, name) == 0)
03661     return TRUE;
03662   else
03663     return FALSE;
03664 }
03665 
03675 dbus_bool_t
03676 dbus_message_has_signature (DBusMessage   *message,
03677                             const char    *signature)
03678 {
03679   const char *s;
03680 
03681   _dbus_return_val_if_fail (message != NULL, FALSE);
03682   _dbus_return_val_if_fail (signature != NULL, FALSE);
03683   /* don't check that signature is valid since it would be expensive,
03684    * and not catch many common errors
03685    */
03686 
03687   s = dbus_message_get_signature (message);
03688 
03689   if (s && strcmp (s, signature) == 0)
03690     return TRUE;
03691   else
03692     return FALSE;
03693 }
03694 
03717 dbus_bool_t
03718 dbus_set_error_from_message (DBusError   *error,
03719                              DBusMessage *message)
03720 {
03721   const char *str;
03722 
03723   _dbus_return_val_if_fail (message != NULL, FALSE);
03724   _dbus_return_val_if_error_is_set (error, FALSE);
03725 
03726   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
03727     return FALSE;
03728 
03729   str = NULL;
03730   dbus_message_get_args (message, NULL,
03731                          DBUS_TYPE_STRING, &str,
03732                          DBUS_TYPE_INVALID);
03733 
03734   dbus_set_error (error, dbus_message_get_error_name (message),
03735                   str ? "%s" : NULL, str);
03736 
03737   return TRUE;
03738 }
03739 
03746 dbus_bool_t
03747 dbus_message_contains_unix_fds(DBusMessage *message)
03748 {
03749 #ifdef HAVE_UNIX_FD_PASSING
03750   _dbus_assert(message);
03751 
03752   return message->n_unix_fds > 0;
03753 #else
03754   return FALSE;
03755 #endif
03756 }
03757 
03776 #define INITIAL_LOADER_DATA_LEN 32
03777 
03784 DBusMessageLoader*
03785 _dbus_message_loader_new (void)
03786 {
03787   DBusMessageLoader *loader;
03788 
03789   loader = dbus_new0 (DBusMessageLoader, 1);
03790   if (loader == NULL)
03791     return NULL;
03792   
03793   loader->refcount = 1;
03794 
03795   loader->corrupted = FALSE;
03796   loader->corruption_reason = DBUS_VALID;
03797 
03798   /* this can be configured by the app, but defaults to the protocol max */
03799   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
03800 
03801   /* We set a very relatively conservative default here since due to how
03802   SCM_RIGHTS works we need to preallocate an fd array of the maximum
03803   number of unix fds we want to receive in advance. A
03804   try-and-reallocate loop is not possible. */
03805   loader->max_message_unix_fds = 1024;
03806 
03807   if (!_dbus_string_init (&loader->data))
03808     {
03809       dbus_free (loader);
03810       return NULL;
03811     }
03812 
03813   /* preallocate the buffer for speed, ignore failure */
03814   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
03815   _dbus_string_set_length (&loader->data, 0);
03816 
03817 #ifdef HAVE_UNIX_FD_PASSING
03818   loader->unix_fds = NULL;
03819   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
03820   loader->unix_fds_outstanding = FALSE;
03821 #endif
03822 
03823   return loader;
03824 }
03825 
03832 DBusMessageLoader *
03833 _dbus_message_loader_ref (DBusMessageLoader *loader)
03834 {
03835   loader->refcount += 1;
03836 
03837   return loader;
03838 }
03839 
03846 void
03847 _dbus_message_loader_unref (DBusMessageLoader *loader)
03848 {
03849   loader->refcount -= 1;
03850   if (loader->refcount == 0)
03851     {
03852 #ifdef HAVE_UNIX_FD_PASSING
03853       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
03854       dbus_free(loader->unix_fds);
03855 #endif
03856       _dbus_list_foreach (&loader->messages,
03857                           (DBusForeachFunction) dbus_message_unref,
03858                           NULL);
03859       _dbus_list_clear (&loader->messages);
03860       _dbus_string_free (&loader->data);
03861       dbus_free (loader);
03862     }
03863 }
03864 
03883 void
03884 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
03885                                  DBusString        **buffer)
03886 {
03887   _dbus_assert (!loader->buffer_outstanding);
03888 
03889   *buffer = &loader->data;
03890 
03891   loader->buffer_outstanding = TRUE;
03892 }
03893 
03904 void
03905 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
03906                                     DBusString         *buffer,
03907                                     int                 bytes_read)
03908 {
03909   _dbus_assert (loader->buffer_outstanding);
03910   _dbus_assert (buffer == &loader->data);
03911 
03912   loader->buffer_outstanding = FALSE;
03913 }
03914 
03925 dbus_bool_t
03926 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
03927                                   int               **fds,
03928                                   unsigned           *max_n_fds)
03929 {
03930 #ifdef HAVE_UNIX_FD_PASSING
03931   _dbus_assert (!loader->unix_fds_outstanding);
03932 
03933   /* Allocate space where we can put the fds we read. We allocate
03934      space for max_message_unix_fds since this is an
03935      upper limit how many fds can be received within a single
03936      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
03937      we are allocating the maximum possible array size right from the
03938      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
03939      there is no better way. */
03940 
03941   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
03942     {
03943       int *a = dbus_realloc(loader->unix_fds,
03944                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
03945 
03946       if (!a)
03947         return FALSE;
03948 
03949       loader->unix_fds = a;
03950       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
03951     }
03952 
03953   *fds = loader->unix_fds + loader->n_unix_fds;
03954   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
03955 
03956   loader->unix_fds_outstanding = TRUE;
03957   return TRUE;
03958 #else
03959   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03960   return FALSE;
03961 #endif
03962 }
03963 
03974 void
03975 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
03976                                      int                *fds,
03977                                      unsigned            n_fds)
03978 {
03979 #ifdef HAVE_UNIX_FD_PASSING
03980   _dbus_assert(loader->unix_fds_outstanding);
03981   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
03982   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
03983 
03984   loader->n_unix_fds += n_fds;
03985   loader->unix_fds_outstanding = FALSE;
03986 #else
03987   _dbus_assert_not_reached("Platform doesn't support unix fd passing");
03988 #endif
03989 }
03990 
03991 /*
03992  * FIXME when we move the header out of the buffer, that memmoves all
03993  * buffered messages. Kind of crappy.
03994  *
03995  * Also we copy the header and body, which is kind of crappy.  To
03996  * avoid this, we have to allow header and body to be in a single
03997  * memory block, which is good for messages we read and bad for
03998  * messages we are creating. But we could move_len() the buffer into
03999  * this single memory block, and move_len() will just swap the buffers
04000  * if you're moving the entire buffer replacing the dest string.
04001  *
04002  * We could also have the message loader tell the transport how many
04003  * bytes to read; so it would first ask for some arbitrary number like
04004  * 256, then if the message was incomplete it would use the
04005  * header/body len to ask for exactly the size of the message (or
04006  * blocks the size of a typical kernel buffer for the socket). That
04007  * way we don't get trailing bytes in the buffer that have to be
04008  * memmoved. Though I suppose we also don't have a chance of reading a
04009  * bunch of small messages at once, so the optimization may be stupid.
04010  *
04011  * Another approach would be to keep a "start" index into
04012  * loader->data and only delete it occasionally, instead of after
04013  * each message is loaded.
04014  *
04015  * load_message() returns FALSE if not enough memory OR the loader was corrupted
04016  */
04017 static dbus_bool_t
04018 load_message (DBusMessageLoader *loader,
04019               DBusMessage       *message,
04020               int                byte_order,
04021               int                fields_array_len,
04022               int                header_len,
04023               int                body_len)
04024 {
04025   dbus_bool_t oom;
04026   DBusValidity validity;
04027   const DBusString *type_str;
04028   int type_pos;
04029   DBusValidationMode mode;
04030   dbus_uint32_t n_unix_fds = 0;
04031 
04032   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
04033   
04034   oom = FALSE;
04035 
04036 #if 0
04037   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
04038 #endif
04039 
04040   /* 1. VALIDATE AND COPY OVER HEADER */
04041   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
04042   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
04043 
04044   if (!_dbus_header_load (&message->header,
04045                           mode,
04046                           &validity,
04047                           byte_order,
04048                           fields_array_len,
04049                           header_len,
04050                           body_len,
04051                           &loader->data, 0,
04052                           _dbus_string_get_length (&loader->data)))
04053     {
04054       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
04055 
04056       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
04057          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
04058       _dbus_assert (validity != DBUS_VALID);
04059 
04060       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
04061         oom = TRUE;
04062       else
04063         {
04064           loader->corrupted = TRUE;
04065           loader->corruption_reason = validity;
04066         }
04067       goto failed;
04068     }
04069 
04070   _dbus_assert (validity == DBUS_VALID);
04071 
04072   /* 2. VALIDATE BODY */
04073   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
04074     {
04075       get_const_signature (&message->header, &type_str, &type_pos);
04076       
04077       /* Because the bytes_remaining arg is NULL, this validates that the
04078        * body is the right length
04079        */
04080       validity = _dbus_validate_body_with_reason (type_str,
04081                                                   type_pos,
04082                                                   byte_order,
04083                                                   NULL,
04084                                                   &loader->data,
04085                                                   header_len,
04086                                                   body_len);
04087       if (validity != DBUS_VALID)
04088         {
04089           _dbus_verbose ("Failed to validate message body code %d\n", validity);
04090 
04091           loader->corrupted = TRUE;
04092           loader->corruption_reason = validity;
04093           
04094           goto failed;
04095         }
04096     }
04097 
04098   /* 3. COPY OVER UNIX FDS */
04099   _dbus_header_get_field_basic(&message->header,
04100                                DBUS_HEADER_FIELD_UNIX_FDS,
04101                                DBUS_TYPE_UINT32,
04102                                &n_unix_fds);
04103 
04104 #ifdef HAVE_UNIX_FD_PASSING
04105 
04106   if (n_unix_fds > loader->n_unix_fds)
04107     {
04108       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
04109                     n_unix_fds, loader->n_unix_fds);
04110 
04111       loader->corrupted = TRUE;
04112       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04113       goto failed;
04114     }
04115 
04116   /* If this was a recycled message there might still be
04117      some memory allocated for the fds */
04118   dbus_free(message->unix_fds);
04119 
04120   if (n_unix_fds > 0)
04121     {
04122       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
04123       if (message->unix_fds == NULL)
04124         {
04125           _dbus_verbose ("Failed to allocate file descriptor array\n");
04126           oom = TRUE;
04127           goto failed;
04128         }
04129 
04130       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
04131       loader->n_unix_fds -= n_unix_fds;
04132       memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds);
04133     }
04134   else
04135     message->unix_fds = NULL;
04136 
04137 #else
04138 
04139   if (n_unix_fds > 0)
04140     {
04141       _dbus_verbose ("Hmm, message claims to come with file descriptors "
04142                      "but that's not supported on our platform, disconnecting.\n");
04143 
04144       loader->corrupted = TRUE;
04145       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
04146       goto failed;
04147     }
04148 
04149 #endif
04150 
04151   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
04152 
04153   if (!_dbus_list_append (&loader->messages, message))
04154     {
04155       _dbus_verbose ("Failed to append new message to loader queue\n");
04156       oom = TRUE;
04157       goto failed;
04158     }
04159 
04160   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
04161   _dbus_assert (_dbus_string_get_length (&loader->data) >=
04162                 (header_len + body_len));
04163 
04164   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
04165     {
04166       _dbus_verbose ("Failed to move body into new message\n");
04167       oom = TRUE;
04168       goto failed;
04169     }
04170 
04171   _dbus_string_delete (&loader->data, 0, header_len + body_len);
04172 
04173   /* don't waste more than 2k of memory */
04174   _dbus_string_compact (&loader->data, 2048);
04175 
04176   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
04177   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
04178 
04179   _dbus_verbose ("Loaded message %p\n", message);
04180 
04181   _dbus_assert (!oom);
04182   _dbus_assert (!loader->corrupted);
04183   _dbus_assert (loader->messages != NULL);
04184   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04185 
04186   return TRUE;
04187 
04188  failed:
04189 
04190   /* Clean up */
04191 
04192   /* does nothing if the message isn't in the list */
04193   _dbus_list_remove_last (&loader->messages, message);
04194   
04195   if (oom)
04196     _dbus_assert (!loader->corrupted);
04197   else
04198     _dbus_assert (loader->corrupted);
04199 
04200   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
04201 
04202   return FALSE;
04203 }
04204 
04219 dbus_bool_t
04220 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
04221 {
04222   while (!loader->corrupted &&
04223          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
04224     {
04225       DBusValidity validity;
04226       int byte_order, fields_array_len, header_len, body_len;
04227 
04228       if (_dbus_header_have_message_untrusted (loader->max_message_size,
04229                                                &validity,
04230                                                &byte_order,
04231                                                &fields_array_len,
04232                                                &header_len,
04233                                                &body_len,
04234                                                &loader->data, 0,
04235                                                _dbus_string_get_length (&loader->data)))
04236         {
04237           DBusMessage *message;
04238 
04239           _dbus_assert (validity == DBUS_VALID);
04240 
04241           message = dbus_message_new_empty_header ();
04242           if (message == NULL)
04243             return FALSE;
04244 
04245           if (!load_message (loader, message,
04246                              byte_order, fields_array_len,
04247                              header_len, body_len))
04248             {
04249               dbus_message_unref (message);
04250               /* load_message() returns false if corrupted or OOM; if
04251                * corrupted then return TRUE for not OOM
04252                */
04253               return loader->corrupted;
04254             }
04255 
04256           _dbus_assert (loader->messages != NULL);
04257           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
04258         }
04259       else
04260         {
04261           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
04262                          validity);
04263           if (validity != DBUS_VALID)
04264             {
04265               loader->corrupted = TRUE;
04266               loader->corruption_reason = validity;
04267             }
04268           return TRUE;
04269         }
04270     }
04271 
04272   return TRUE;
04273 }
04274 
04282 DBusMessage*
04283 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
04284 {
04285   if (loader->messages)
04286     return loader->messages->data;
04287   else
04288     return NULL;
04289 }
04290 
04299 DBusMessage*
04300 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
04301 {
04302   return _dbus_list_pop_first (&loader->messages);
04303 }
04304 
04313 DBusList*
04314 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
04315 {
04316   return _dbus_list_pop_first_link (&loader->messages);
04317 }
04318 
04325 void
04326 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
04327                                            DBusList           *link)
04328 {
04329   _dbus_list_prepend_link (&loader->messages, link);
04330 }
04331 
04341 dbus_bool_t
04342 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
04343 {
04344   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04345                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04346   return loader->corrupted;
04347 }
04348 
04355 DBusValidity
04356 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
04357 {
04358   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
04359                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
04360 
04361   return loader->corruption_reason;
04362 }
04363 
04370 void
04371 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
04372                                            long                size)
04373 {
04374   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
04375     {
04376       _dbus_verbose ("clamping requested max message size %ld to %d\n",
04377                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
04378       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
04379     }
04380   loader->max_message_size = size;
04381 }
04382 
04389 long
04390 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
04391 {
04392   return loader->max_message_size;
04393 }
04394 
04401 void
04402 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
04403                                                long                n)
04404 {
04405   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
04406     {
04407       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
04408                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
04409       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
04410     }
04411   loader->max_message_unix_fds = n;
04412 }
04413 
04420 long
04421 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
04422 {
04423   return loader->max_message_unix_fds;
04424 }
04425 
04426 static DBusDataSlotAllocator slot_allocator;
04427 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
04428 
04443 dbus_bool_t
04444 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
04445 {
04446   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04447                                           &_DBUS_LOCK_NAME (message_slots),
04448                                           slot_p);
04449 }
04450 
04462 void
04463 dbus_message_free_data_slot (dbus_int32_t *slot_p)
04464 {
04465   _dbus_return_if_fail (*slot_p >= 0);
04466 
04467   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04468 }
04469 
04483 dbus_bool_t
04484 dbus_message_set_data (DBusMessage     *message,
04485                        dbus_int32_t     slot,
04486                        void            *data,
04487                        DBusFreeFunction free_data_func)
04488 {
04489   DBusFreeFunction old_free_func;
04490   void *old_data;
04491   dbus_bool_t retval;
04492 
04493   _dbus_return_val_if_fail (message != NULL, FALSE);
04494   _dbus_return_val_if_fail (slot >= 0, FALSE);
04495 
04496   retval = _dbus_data_slot_list_set (&slot_allocator,
04497                                      &message->slot_list,
04498                                      slot, data, free_data_func,
04499                                      &old_free_func, &old_data);
04500 
04501   if (retval)
04502     {
04503       /* Do the actual free outside the message lock */
04504       if (old_free_func)
04505         (* old_free_func) (old_data);
04506     }
04507 
04508   return retval;
04509 }
04510 
04519 void*
04520 dbus_message_get_data (DBusMessage   *message,
04521                        dbus_int32_t   slot)
04522 {
04523   void *res;
04524 
04525   _dbus_return_val_if_fail (message != NULL, NULL);
04526 
04527   res = _dbus_data_slot_list_get (&slot_allocator,
04528                                   &message->slot_list,
04529                                   slot);
04530 
04531   return res;
04532 }
04533 
04547 int
04548 dbus_message_type_from_string (const char *type_str)
04549 {
04550   if (strcmp (type_str, "method_call") == 0)
04551     return DBUS_MESSAGE_TYPE_METHOD_CALL;
04552   if (strcmp (type_str, "method_return") == 0)
04553     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
04554   else if (strcmp (type_str, "signal") == 0)
04555     return DBUS_MESSAGE_TYPE_SIGNAL;
04556   else if (strcmp (type_str, "error") == 0)
04557     return DBUS_MESSAGE_TYPE_ERROR;
04558   else
04559     return DBUS_MESSAGE_TYPE_INVALID;
04560 }
04561 
04575 const char *
04576 dbus_message_type_to_string (int type)
04577 {
04578   switch (type)
04579     {
04580     case DBUS_MESSAGE_TYPE_METHOD_CALL:
04581       return "method_call";
04582     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
04583       return "method_return";
04584     case DBUS_MESSAGE_TYPE_SIGNAL:
04585       return "signal";
04586     case DBUS_MESSAGE_TYPE_ERROR:
04587       return "error";
04588     default:
04589       return "invalid";
04590     }
04591 }
04592 
04605 dbus_bool_t
04606 dbus_message_marshal (DBusMessage  *msg,
04607                       char        **marshalled_data_p,
04608                       int          *len_p)
04609 {
04610   DBusString tmp;
04611   dbus_bool_t was_locked;
04612 
04613   _dbus_return_val_if_fail (msg != NULL, FALSE);
04614   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
04615   _dbus_return_val_if_fail (len_p != NULL, FALSE);
04616   
04617   if (!_dbus_string_init (&tmp))
04618     return FALSE;
04619 
04620   /* Ensure the message is locked, to ensure the length header is filled in. */
04621   was_locked = msg->locked;
04622 
04623   if (!was_locked)
04624     dbus_message_lock (msg);
04625 
04626   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
04627     goto fail;
04628 
04629   *len_p = _dbus_string_get_length (&tmp);
04630 
04631   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
04632     goto fail;
04633 
04634   *len_p = _dbus_string_get_length (&tmp);
04635 
04636   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
04637     goto fail;
04638 
04639   _dbus_string_free (&tmp);
04640 
04641   if (!was_locked)
04642     msg->locked = FALSE;
04643 
04644   return TRUE;
04645 
04646  fail:
04647   _dbus_string_free (&tmp);
04648 
04649   if (!was_locked)
04650     msg->locked = FALSE;
04651 
04652   return FALSE;
04653 }
04654 
04667 DBusMessage *
04668 dbus_message_demarshal (const char *str,
04669                         int         len,
04670                         DBusError  *error)
04671 {
04672   DBusMessageLoader *loader;
04673   DBusString *buffer;
04674   DBusMessage *msg;
04675 
04676   _dbus_return_val_if_fail (str != NULL, NULL);
04677 
04678   loader = _dbus_message_loader_new ();
04679 
04680   if (loader == NULL)
04681     return NULL;
04682 
04683   _dbus_message_loader_get_buffer (loader, &buffer);
04684   _dbus_string_append_len (buffer, str, len);
04685   _dbus_message_loader_return_buffer (loader, buffer, len);
04686 
04687   if (!_dbus_message_loader_queue_messages (loader))
04688     goto fail_oom;
04689 
04690   if (_dbus_message_loader_get_is_corrupted (loader))
04691     goto fail_corrupt;
04692 
04693   msg = _dbus_message_loader_pop_message (loader);
04694 
04695   if (!msg)
04696     goto fail_oom;
04697 
04698   _dbus_message_loader_unref (loader);
04699   return msg;
04700 
04701  fail_corrupt:
04702   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
04703                   _dbus_validity_to_error_message (loader->corruption_reason));
04704   _dbus_message_loader_unref (loader);
04705   return NULL;
04706 
04707  fail_oom:
04708   _DBUS_SET_OOM (error);
04709   _dbus_message_loader_unref (loader);
04710   return NULL;
04711 }
04712 
04726 int 
04727 dbus_message_demarshal_bytes_needed(const char *buf, 
04728                                     int         len)
04729 {
04730   DBusString str;
04731   int byte_order, fields_array_len, header_len, body_len;
04732   DBusValidity validity = DBUS_VALID;
04733   int have_message;
04734 
04735   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
04736     return 0;
04737 
04738   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
04739     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
04740   _dbus_string_init_const_len (&str, buf, len);
04741   
04742   validity = DBUS_VALID;
04743   have_message
04744     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
04745                                           &validity, &byte_order,
04746                                           &fields_array_len,
04747                                           &header_len,
04748                                           &body_len,
04749                                           &str, 0,
04750                                           len);
04751   _dbus_string_free (&str);
04752 
04753   if (validity == DBUS_VALID)
04754     {
04755       _dbus_assert (have_message || (header_len + body_len) > len);
04756       (void) have_message; /* unused unless asserting */
04757       return header_len + body_len;
04758     }
04759   else
04760     {
04761       return -1; /* broken! */
04762     }
04763 }
04764 
04767 /* tests in dbus-message-util.c */