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

dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 1.2
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-marshal.h"
00027 #include "dbus-message.h"
00028 #include "dbus-message-internal.h"
00029 #include "dbus-memory.h"
00030 #include "dbus-list.h"
00031 #include "dbus-message-builder.h"
00032 #include "dbus-dataslot.h"
00033 #include <string.h>
00034 
00048 typedef struct
00049 {
00050   int name_offset;  
00051   int value_offset; 
00052 } HeaderField;
00053 
00055 #define BYTE_ORDER_OFFSET    0
00056 
00057 #define TYPE_OFFSET          1
00058 
00059 #define FLAGS_OFFSET         2
00060 
00061 #define VERSION_OFFSET       3
00062 
00063 #define HEADER_LENGTH_OFFSET 4
00064 
00065 #define BODY_LENGTH_OFFSET   8
00066 
00067 #define CLIENT_SERIAL_OFFSET 12
00068 
00069 
00077 struct DBusMessage
00078 {
00079   DBusAtomic refcount; 
00081   DBusString header; 
00086   HeaderField header_fields[DBUS_HEADER_FIELD_LAST + 1]; 
00090   dbus_uint32_t client_serial; 
00091   dbus_uint32_t reply_serial;  
00093   int header_padding; 
00095   DBusString body;   
00097   char byte_order; 
00099   DBusList *size_counters;   
00100   long size_counter_delta;   
00102   dbus_uint32_t changed_stamp; 
00104   unsigned int locked : 1; 
00106   DBusDataSlotList slot_list;   
00108   DBusString signature; 
00109 };
00110 
00111 enum {
00112   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
00113   DBUS_MESSAGE_ITER_TYPE_ARRAY,
00114   DBUS_MESSAGE_ITER_TYPE_DICT
00115 };
00116 
00118 typedef struct DBusMessageRealIter DBusMessageRealIter;
00119 
00125 struct DBusMessageRealIter
00126 {
00127   DBusMessageRealIter *parent_iter; 
00128   DBusMessage *message; 
00129   dbus_uint32_t changed_stamp; 
00131   /* This is an int instead of an enum to get a guaranteed size for the dummy: */
00132   int type; 
00134   int pos; 
00135   int end; 
00136   int container_start; 
00137   int container_length_pos; 
00139   int wrote_dict_key; 
00141   int array_type_pos; 
00142   int array_type_done; 
00143 };
00144 
00155 void
00156 _dbus_message_get_network_data (DBusMessage          *message,
00157                                 const DBusString    **header,
00158                                 const DBusString    **body)
00159 {
00160   _dbus_assert (message->locked);
00161   
00162   *header = &message->header;
00163   *body = &message->body;
00164 }
00165 
00166 static void
00167 clear_header_padding (DBusMessage *message)
00168 {
00169   _dbus_string_shorten (&message->header,
00170                         message->header_padding);
00171   message->header_padding = 0;
00172 }              
00173 
00174 static dbus_bool_t
00175 append_header_padding (DBusMessage *message)
00176 {
00177   int old_len;
00178   old_len = _dbus_string_get_length (&message->header);
00179   if (!_dbus_string_align_length (&message->header, 8))
00180     return FALSE;
00181 
00182   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
00183 
00184   return TRUE;
00185 }
00186 
00187 #ifdef DBUS_BUILD_TESTS
00188 /* tests-only until it's actually used */
00189 static dbus_int32_t
00190 get_int_field (DBusMessage *message,
00191                int          field)
00192 {
00193   int offset;
00194 
00195   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00196   
00197   offset = message->header_fields[field].value_offset;
00198   
00199   if (offset < 0)
00200     return -1; /* useless if -1 is a valid value of course */
00201   
00202   return _dbus_demarshal_int32 (&message->header,
00203                                 message->byte_order,
00204                                 offset,
00205                                 NULL);
00206 }
00207 #endif
00208 
00209 static dbus_uint32_t
00210 get_uint_field (DBusMessage *message,
00211                 int          field)
00212 {
00213   int offset;
00214   
00215   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00216   
00217   offset = message->header_fields[field].value_offset;
00218   
00219   if (offset < 0)
00220     return 0; /* useless if 0 is a valid value of course */
00221   
00222   return _dbus_demarshal_uint32 (&message->header,
00223                                  message->byte_order,
00224                                  offset,
00225                                  NULL);
00226 }
00227 
00228 static const char*
00229 get_string_field (DBusMessage *message,
00230                   int          field,
00231                   int         *len)
00232 {
00233   int offset;
00234   const char *data;
00235 
00236   offset = message->header_fields[field].value_offset;
00237 
00238   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00239   
00240   if (offset < 0)
00241     return NULL;
00242 
00243   /* offset points to string length, string data follows it */
00244   /* FIXME _dbus_demarshal_const_string() that returned
00245    * a reference to the string plus its len might be nice.
00246    */
00247   
00248   if (len)
00249     *len = _dbus_demarshal_uint32 (&message->header,
00250                                    message->byte_order,
00251                                    offset,
00252                                    NULL);
00253 
00254   data = _dbus_string_get_const_data (&message->header);
00255   
00256   return data + (offset + 4); 
00257 }
00258 
00259 /* returns FALSE if no memory, TRUE with NULL path if no field */
00260 static dbus_bool_t
00261 get_path_field_decomposed (DBusMessage  *message,
00262                            int           field,
00263                            char       ***path)
00264 {
00265   int offset;
00266 
00267   offset = message->header_fields[field].value_offset;
00268 
00269   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00270   
00271   if (offset < 0)
00272     {
00273       *path = NULL;
00274       return TRUE;
00275     }
00276 
00277   return _dbus_demarshal_object_path (&message->header,
00278                                       message->byte_order,
00279                                       offset,
00280                                       NULL,
00281                                       path, NULL);
00282 }
00283 
00284 #ifdef DBUS_BUILD_TESTS
00285 static dbus_bool_t
00286 append_int_field (DBusMessage *message,
00287                   int          field,
00288                   int          value)
00289 {
00290   _dbus_assert (!message->locked);
00291 
00292   clear_header_padding (message);
00293   
00294   message->header_fields[field].name_offset =
00295     _dbus_string_get_length (&message->header);
00296   
00297   if (!_dbus_string_append_byte (&message->header, field))
00298     goto failed;
00299 
00300   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
00301     goto failed;
00302 
00303   if (!_dbus_string_align_length (&message->header, 4))
00304     goto failed;
00305   
00306   message->header_fields[field].value_offset =
00307     _dbus_string_get_length (&message->header);
00308   
00309   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
00310                             value))
00311     goto failed;
00312 
00313   if (!append_header_padding (message))
00314     goto failed;
00315   
00316   return TRUE;
00317   
00318  failed:
00319   _dbus_string_set_length (&message->header,
00320                            message->header_fields[field].name_offset);
00321   message->header_fields[field].name_offset  = -1;
00322   message->header_fields[field].value_offset = -1;
00323 
00324   /* this must succeed because it was allocated on function entry and
00325    * DBusString doesn't ever realloc smaller
00326    */
00327   if (!append_header_padding (message))
00328     _dbus_assert_not_reached ("failed to reappend header padding");
00329   return FALSE;
00330 }
00331 #endif
00332 
00333 static dbus_bool_t
00334 append_uint_field (DBusMessage *message,
00335                    int          field,
00336                    int          value)
00337 {
00338   _dbus_assert (!message->locked);
00339 
00340   clear_header_padding (message);
00341   
00342   message->header_fields[field].name_offset =
00343     _dbus_string_get_length (&message->header);
00344   
00345   if (!_dbus_string_append_byte (&message->header, field))
00346     goto failed;
00347 
00348   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_UINT32))
00349     goto failed;
00350 
00351   if (!_dbus_string_align_length (&message->header, 4))
00352     goto failed;
00353   
00354   message->header_fields[field].value_offset =
00355     _dbus_string_get_length (&message->header);
00356   
00357   if (!_dbus_marshal_uint32 (&message->header, message->byte_order,
00358                              value))
00359     goto failed;
00360 
00361   if (!append_header_padding (message))
00362     goto failed;
00363   
00364   return TRUE;
00365   
00366  failed:
00367   _dbus_string_set_length (&message->header,
00368                            message->header_fields[field].name_offset);
00369   message->header_fields[field].name_offset  = -1;
00370   message->header_fields[field].value_offset = -1;
00371 
00372   /* this must succeed because it was allocated on function entry and
00373    * DBusString doesn't ever realloc smaller
00374    */
00375   if (!append_header_padding (message))
00376     _dbus_assert_not_reached ("failed to reappend header padding");
00377   return FALSE;
00378 }
00379 
00380 #define MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING (1 + 1 + 3 + 1 + 8)
00381 static dbus_bool_t
00382 append_string_field (DBusMessage *message,
00383                      int          field,
00384                      int          type,
00385                      const char  *value)
00386 {
00387   _dbus_assert (!message->locked);
00388 
00389   clear_header_padding (message);
00390   
00391   message->header_fields[field].name_offset =
00392     _dbus_string_get_length (&message->header);
00393   
00394   if (!_dbus_string_append_byte (&message->header, field))
00395     goto failed;
00396   
00397   if (!_dbus_string_append_byte (&message->header, type))
00398     goto failed;
00399 
00400   if (!_dbus_string_align_length (&message->header, 4))
00401     goto failed;
00402   
00403   message->header_fields[field].value_offset =
00404     _dbus_string_get_length (&message->header);
00405   
00406   if (!_dbus_marshal_string (&message->header, message->byte_order,
00407                              value))
00408     goto failed;
00409 
00410   if (!append_header_padding (message))
00411     goto failed;
00412   
00413   return TRUE;
00414   
00415  failed:
00416   _dbus_string_set_length (&message->header,
00417                            message->header_fields[field].name_offset);
00418   message->header_fields[field].name_offset  = -1;
00419   message->header_fields[field].value_offset = -1;
00420 
00421   /* this must succeed because it was allocated on function entry and
00422    * DBusString doesn't ever realloc smaller
00423    */
00424   if (!append_header_padding (message))
00425     _dbus_assert_not_reached ("failed to reappend header padding");
00426   
00427   return FALSE;
00428 }
00429 
00430 static int
00431 get_type_alignment (int type)
00432 {
00433   int alignment;
00434   
00435   switch (type)
00436     {
00437     case DBUS_TYPE_NIL:
00438     case DBUS_TYPE_BYTE:
00439     case DBUS_TYPE_BOOLEAN:
00440       alignment = 0;
00441       break;
00442 
00443     case DBUS_TYPE_INT32:
00444     case DBUS_TYPE_UINT32:
00445     case DBUS_TYPE_STRING:
00446     case DBUS_TYPE_OBJECT_PATH:
00447       /* These are aligned 4 because they have a length as the
00448        * first field;
00449        */
00450     case DBUS_TYPE_CUSTOM:
00451     case DBUS_TYPE_DICT:
00452       alignment = 4;
00453       break;
00454 
00455     case DBUS_TYPE_INT64:
00456     case DBUS_TYPE_UINT64:
00457     case DBUS_TYPE_DOUBLE:
00458       alignment = 8;
00459       break;
00460 
00461     case DBUS_TYPE_ARRAY:
00462       _dbus_assert_not_reached ("passed an ARRAY type to get_type_alignment()");
00463       break;
00464 
00465     case DBUS_TYPE_INVALID:
00466     default:
00467       _dbus_assert_not_reached ("passed an invalid or unknown type to get_type_alignment()");
00468       break;
00469     }
00470 
00471   return alignment;
00472 }
00473 
00474 static dbus_bool_t
00475 iterate_one_field (const DBusString *str,
00476                    int               byte_order,
00477                    int               name_offset,
00478                    int              *next_offset_p,
00479                    int              *field_name_p,
00480                    DBusString       *append_copy_to,
00481                    int              *copy_name_offset_p,
00482                    int              *copy_value_offset_p)
00483 {
00484   int name, type, array_type;
00485   int alignment;
00486   int type_len;
00487   int type_pos;
00488   int value_pos;
00489   int value_len;
00490   int value_end;
00491   int pos;
00492 
00493   _dbus_verbose ("%s: name_offset=%d, append to %p\n",
00494                  _DBUS_FUNCTION_NAME, name_offset, append_copy_to);
00495   
00496   pos = name_offset;
00497   
00498   name = _dbus_string_get_byte (str, name_offset);
00499   pos++;
00500 
00501   type_pos = pos;
00502   type = _dbus_string_get_byte (str, type_pos);
00503   pos++;
00504   type_len = 1;
00505 
00506   array_type = type;
00507   /* find out the type of our array */
00508   while (array_type == DBUS_TYPE_ARRAY)
00509     {
00510       pos++;
00511       type_len++;
00512       array_type = _dbus_string_get_byte (str, pos);
00513     }
00514 
00515   _dbus_verbose ("%s: name %d, type '%c' %d at %d len %d, array type '%c' %d\n",
00516                  _DBUS_FUNCTION_NAME,
00517                  name, type, type, type_pos, type_len, array_type, array_type);
00518   
00519 #ifndef DBUS_DISABLE_ASSERT
00520   if (!_dbus_type_is_valid (array_type))
00521     {
00522       _dbus_warn ("type '%c' %d is not valid in %s\n",
00523                   array_type, array_type, _DBUS_FUNCTION_NAME);
00524       _dbus_assert_not_reached ("invalid type");
00525     }
00526 #endif
00527       
00528   alignment = get_type_alignment (array_type);
00529       
00530   if (alignment > 0)
00531     pos = _DBUS_ALIGN_VALUE (pos, alignment);
00532 
00533   _dbus_verbose ("%s: alignment %d value at pos %d\n",
00534                  _DBUS_FUNCTION_NAME, alignment, pos);
00535   
00536   /* pos now points to our value */
00537   if (!_dbus_marshal_get_arg_end_pos (str, byte_order,
00538                                       type, pos, &value_end))
00539     _dbus_assert_not_reached ("failed to get the byte after this header");
00540 
00541   value_pos = pos;
00542   value_len = value_end - value_pos;
00543 
00544   _dbus_verbose ("%s: value_pos %d value_len %d value_end %d\n",
00545                  _DBUS_FUNCTION_NAME, value_pos, value_len, value_end);
00546   
00547   if (next_offset_p)
00548     *next_offset_p = pos + value_len;
00549 
00550   if (field_name_p)
00551     *field_name_p = name;
00552 
00553   if (append_copy_to)
00554     {
00555       int orig_len;
00556 
00557       orig_len = _dbus_string_get_length (append_copy_to);
00558 
00559       if (copy_name_offset_p)
00560         *copy_name_offset_p = orig_len;
00561       
00562       if (!_dbus_string_append_byte (append_copy_to, name))
00563         goto failed_copy;
00564 
00565       if (!_dbus_string_copy_len (str, type_pos, type_len,
00566                                   append_copy_to,
00567                                   _dbus_string_get_length (append_copy_to)))
00568         goto failed_copy;
00569 
00570       if (!_dbus_string_align_length (append_copy_to, alignment))
00571         goto failed_copy;
00572 
00573       if (copy_value_offset_p)
00574         *copy_value_offset_p = _dbus_string_get_length (append_copy_to);
00575       
00576       if (!_dbus_string_copy_len (str, value_pos, value_len,
00577                                   append_copy_to,
00578                                   _dbus_string_get_length (append_copy_to)))
00579         goto failed_copy;
00580       
00581       return TRUE;
00582 
00583     failed_copy:
00584       _dbus_verbose ("%s: Failed copying old fields to new string\n",
00585                      _DBUS_FUNCTION_NAME);
00586       _dbus_string_set_length (append_copy_to, orig_len);
00587       return FALSE;
00588     }
00589   else
00590     return TRUE;
00591 }
00592 
00593 #ifndef DBUS_DISABLE_ASSERT
00594 static void
00595 verify_header_fields (DBusMessage *message)
00596 {
00597   int i;
00598   i = 0;
00599   while (i < DBUS_HEADER_FIELD_LAST)
00600     {
00601       if (message->header_fields[i].name_offset >= 0)
00602         _dbus_assert (_dbus_string_get_byte (&message->header,
00603                                              message->header_fields[i].name_offset) ==
00604                       i);
00605       ++i;
00606     }
00607 }
00608 #else /* DBUS_DISABLE_ASSERT */
00609 #define verify_header_fields(x)
00610 #endif /* DBUS_DISABLE_ASSERT */
00611 
00612 /* In this function we delete one field and re-align all the fields
00613  * following it.
00614  */
00615 static dbus_bool_t
00616 delete_one_and_re_align (DBusMessage *message,
00617                          int          name_offset_to_delete)
00618 {
00619   DBusString copy;
00620   int new_fields_front_padding;
00621   int next_offset;
00622   int field_name;
00623   dbus_bool_t retval;
00624   HeaderField new_header_fields[DBUS_HEADER_FIELD_LAST];
00625   
00626   _dbus_assert (name_offset_to_delete < _dbus_string_get_length (&message->header));
00627   verify_header_fields (message);
00628 
00629   _dbus_verbose ("%s: Deleting one field at offset %d\n",
00630                  _DBUS_FUNCTION_NAME,
00631                  name_offset_to_delete);
00632   
00633   retval = FALSE;
00634 
00635   clear_header_padding (message);
00636   
00637   if (!_dbus_string_init_preallocated (&copy,
00638                                        _dbus_string_get_length (&message->header) -
00639                                        name_offset_to_delete + 8))
00640     {
00641       _dbus_verbose ("%s: Failed to init string to hold copy of fields\n",
00642                      _DBUS_FUNCTION_NAME);
00643       goto out_0;
00644     }
00645   
00646   /* Align the name offset of the first field in the same way it's
00647    * aligned in the real header
00648    */
00649   new_fields_front_padding = name_offset_to_delete % 8;
00650 
00651   if (!_dbus_string_insert_bytes (&copy, 0, new_fields_front_padding,
00652                                   '\0'))
00653     _dbus_assert_not_reached ("Should not have failed to insert bytes into preallocated string\n");
00654 
00655   memcpy (new_header_fields, message->header_fields,
00656           sizeof (new_header_fields));
00657   
00658   /* Now just re-marshal each field in the header to our temporary
00659    * buffer, skipping the first one. The tricky part is that the
00660    * fields are padded as if for previous_name_offset, but are in fact
00661    * at unaligned_name_offset
00662    */
00663 
00664   if (!iterate_one_field (&message->header,
00665                           message->byte_order,
00666                           name_offset_to_delete,
00667                           &next_offset,
00668                           &field_name, NULL, NULL, NULL))
00669     _dbus_assert_not_reached ("shouldn't have failed to alloc memory to skip the deleted field");
00670 
00671   if (field_name < DBUS_HEADER_FIELD_LAST)
00672     {
00673       new_header_fields[field_name].name_offset = -1;
00674       new_header_fields[field_name].value_offset = -1;
00675     }
00676   
00677   while (next_offset < _dbus_string_get_length (&message->header))
00678     {
00679       int copy_name_offset;
00680       int copy_value_offset;
00681 
00682       if (!iterate_one_field (&message->header,
00683                               message->byte_order,
00684                               next_offset,
00685                               &next_offset,
00686                               &field_name,
00687                               &copy,
00688                               &copy_name_offset,
00689                               &copy_value_offset))
00690         {
00691           _dbus_verbose ("%s: OOM iterating one field\n",
00692                          _DBUS_FUNCTION_NAME);
00693           goto out_1;
00694         }
00695       
00696       if (field_name < DBUS_HEADER_FIELD_LAST)
00697         {
00698           new_header_fields[field_name].name_offset = copy_name_offset - new_fields_front_padding + name_offset_to_delete;
00699           new_header_fields[field_name].value_offset = copy_value_offset - new_fields_front_padding + name_offset_to_delete;
00700         }
00701     }
00702 
00703   if (!_dbus_string_replace_len (&copy,
00704                                  new_fields_front_padding,
00705                                  _dbus_string_get_length (&copy) - new_fields_front_padding,
00706                                  &message->header,
00707                                  name_offset_to_delete,
00708                                  _dbus_string_get_length (&message->header) - name_offset_to_delete))
00709     {
00710       _dbus_verbose ("%s: OOM moving copy back into header\n",
00711                      _DBUS_FUNCTION_NAME);
00712       goto out_1;
00713     }
00714   
00715   memcpy (message->header_fields, new_header_fields,
00716           sizeof (new_header_fields));
00717   verify_header_fields (message);
00718   
00719   retval = TRUE;
00720   
00721  out_1:
00722   _dbus_string_free (&copy);
00723   
00724  out_0:
00725   if (!append_header_padding (message))
00726     _dbus_assert_not_reached ("Failed to re-append header padding in re_align_field_recurse()");
00727   
00728   return retval;
00729 }
00730 
00731 static dbus_bool_t
00732 delete_field (DBusMessage *message,
00733               int          field,
00734               int          prealloc_header_space)
00735 {
00736   int offset;
00737 
00738   _dbus_assert (!message->locked);
00739 
00740   /* Prealloc */
00741   if (!_dbus_string_lengthen (&message->header, prealloc_header_space))
00742     {
00743       _dbus_verbose ("failed to prealloc %d bytes header space\n",
00744                      prealloc_header_space);
00745       return FALSE;
00746     }
00747   _dbus_string_shorten (&message->header, prealloc_header_space);
00748 
00749   /* Delete */
00750   offset = message->header_fields[field].name_offset;
00751   if (offset < 0)
00752     {
00753       _dbus_verbose ("header field didn't exist, no need to delete\n");
00754       return TRUE; /* field didn't exist */
00755     }
00756 
00757   return delete_one_and_re_align (message, offset);
00758 }
00759 
00760 #ifdef DBUS_BUILD_TESTS
00761 static dbus_bool_t
00762 set_int_field (DBusMessage *message,
00763                int          field,
00764                int          value)
00765 {
00766   int offset = message->header_fields[field].value_offset;
00767 
00768   _dbus_assert (!message->locked);
00769   
00770   if (offset < 0)
00771     {
00772       /* need to append the field */
00773       return append_int_field (message, field, value);
00774     }
00775   else
00776     {
00777       _dbus_marshal_set_int32 (&message->header,
00778                                message->byte_order,
00779                                offset, value);
00780 
00781       return TRUE;
00782     }
00783 }
00784 #endif
00785 
00786 static dbus_bool_t
00787 set_uint_field (DBusMessage  *message,
00788                 int           field,
00789                 dbus_uint32_t value)
00790 {
00791   int offset = message->header_fields[field].value_offset;
00792 
00793   _dbus_assert (!message->locked);
00794   
00795   if (offset < 0)
00796     {
00797       /* need to append the field */
00798       return append_uint_field (message, field, value);
00799     }
00800   else
00801     {
00802       _dbus_marshal_set_uint32 (&message->header,
00803                                 message->byte_order,
00804                                 offset, value);
00805 
00806       return TRUE;
00807     }
00808 }
00809 
00810 static dbus_bool_t
00811 set_string_field (DBusMessage *message,
00812                   int          field,
00813                   int          type,
00814                   const char  *value)
00815 {
00816   int prealloc;
00817   
00818   _dbus_assert (!message->locked);
00819 
00820   /* the prealloc is so the append_string_field()
00821    * below won't fail, leaving us in inconsistent state
00822    */
00823   prealloc = (value ? strlen (value) : 0) + MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING;
00824 
00825   _dbus_verbose ("set_string_field() field %d prealloc %d\n",
00826                  field, prealloc);
00827   
00828   if (!delete_field (message, field, prealloc))
00829     return FALSE;
00830 
00831   if (value != NULL)
00832     {
00833       /* need to append the field */
00834       if (!append_string_field (message, field, type, value))
00835         _dbus_assert_not_reached ("Appending string field shouldn't have failed, due to preallocation");
00836     }
00837   
00838   return TRUE;
00839 }
00840 
00848 void
00849 _dbus_message_set_serial (DBusMessage  *message,
00850                           dbus_int32_t  serial)
00851 {
00852   _dbus_assert (!message->locked);
00853   _dbus_assert (dbus_message_get_serial (message) == 0);
00854 
00855   _dbus_marshal_set_uint32 (&message->header,
00856                             message->byte_order,
00857                             CLIENT_SERIAL_OFFSET,
00858                             serial);
00859 
00860   message->client_serial = serial;
00861 }
00862 
00871 dbus_bool_t
00872 dbus_message_set_reply_serial (DBusMessage   *message,
00873                                dbus_uint32_t  reply_serial)
00874 {
00875   _dbus_assert (!message->locked);
00876 
00877   if (set_uint_field (message,
00878                       DBUS_HEADER_FIELD_REPLY_SERIAL,
00879                       reply_serial))
00880     {
00881       message->reply_serial = reply_serial;
00882       return TRUE;
00883     }
00884   else
00885     return FALSE;
00886 }
00887 
00898 dbus_uint32_t
00899 dbus_message_get_serial (DBusMessage *message)
00900 {
00901   return message->client_serial;
00902 }
00903 
00910 dbus_uint32_t
00911 dbus_message_get_reply_serial  (DBusMessage *message)
00912 {
00913   return message->reply_serial;
00914 }
00915 
00928 void
00929 _dbus_message_add_size_counter_link (DBusMessage  *message,
00930                                      DBusList     *link)
00931 {
00932   /* right now we don't recompute the delta when message
00933    * size changes, and that's OK for current purposes
00934    * I think, but could be important to change later.
00935    * Do recompute it whenever there are no outstanding counters,
00936    * since it's basically free.
00937    */
00938   if (message->size_counters == NULL)
00939     {
00940       message->size_counter_delta =
00941         _dbus_string_get_length (&message->header) +
00942         _dbus_string_get_length (&message->body);
00943       
00944 #if 0
00945       _dbus_verbose ("message has size %ld\n",
00946                      message->size_counter_delta);
00947 #endif
00948     }
00949   
00950   _dbus_list_append_link (&message->size_counters, link);
00951   
00952   _dbus_counter_adjust (link->data, message->size_counter_delta);
00953 }
00954 
00964 dbus_bool_t
00965 _dbus_message_add_size_counter (DBusMessage *message,
00966                                 DBusCounter *counter)
00967 {
00968   DBusList *link;
00969 
00970   link = _dbus_list_alloc_link (counter);
00971   if (link == NULL)
00972     return FALSE;
00973 
00974   _dbus_counter_ref (counter);
00975   _dbus_message_add_size_counter_link (message, link);
00976 
00977   return TRUE;
00978 }
00979 
00988 void
00989 _dbus_message_remove_size_counter (DBusMessage  *message,
00990                                    DBusCounter  *counter,
00991                                    DBusList    **link_return)
00992 {
00993   DBusList *link;
00994 
00995   link = _dbus_list_find_last (&message->size_counters,
00996                                counter);
00997   _dbus_assert (link != NULL);
00998 
00999   _dbus_list_unlink (&message->size_counters,
01000                      link);
01001   if (link_return)
01002     *link_return = link;
01003   else
01004     _dbus_list_free_link (link);
01005 
01006   _dbus_counter_adjust (counter, message->size_counter_delta);
01007 
01008   _dbus_counter_unref (counter);
01009 }
01010 
01011 static dbus_bool_t
01012 dbus_message_create_header (DBusMessage *message,
01013                             int          type,
01014                             const char  *service,
01015                             const char  *path,
01016                             const char  *interface,
01017                             const char  *member,
01018                             const char  *error_name)
01019 {
01020   unsigned int flags;
01021 
01022   _dbus_assert ((interface && member) ||
01023                 (error_name) ||
01024                 !(interface || member || error_name));
01025   
01026   if (!_dbus_string_append_byte (&message->header, message->byte_order))
01027     return FALSE;
01028 
01029   if (!_dbus_string_append_byte (&message->header, type))
01030     return FALSE;
01031   
01032   flags = 0;
01033   if (!_dbus_string_append_byte (&message->header, flags))
01034     return FALSE;
01035 
01036   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
01037     return FALSE;
01038 
01039   /* header length */
01040   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01041     return FALSE;
01042 
01043   /* body length */
01044   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01045     return FALSE;
01046 
01047   /* serial */
01048   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01049     return FALSE;
01050   
01051   /* Marshal all the fields (Marshall Fields?) */
01052   
01053   if (path != NULL)
01054     {
01055       if (!append_string_field (message,
01056                                 DBUS_HEADER_FIELD_PATH,
01057                                 DBUS_TYPE_OBJECT_PATH,
01058                                 path))
01059         return FALSE;
01060     }
01061   
01062   if (service != NULL)
01063     {
01064       if (!append_string_field (message,
01065                                 DBUS_HEADER_FIELD_SERVICE,
01066                                 DBUS_TYPE_STRING,
01067                                 service))
01068         return FALSE;
01069     }
01070 
01071   if (interface != NULL)
01072     {
01073       if (!append_string_field (message,
01074                                 DBUS_HEADER_FIELD_INTERFACE,
01075                                 DBUS_TYPE_STRING,
01076                                 interface))
01077         return FALSE;
01078     }
01079 
01080   if (member != NULL)
01081     {
01082       if (!append_string_field (message,
01083                                 DBUS_HEADER_FIELD_MEMBER,
01084                                 DBUS_TYPE_STRING,
01085                                 member))
01086         return FALSE;
01087     }
01088 
01089   if (error_name != NULL)
01090     {
01091       if (!append_string_field (message,
01092                                 DBUS_HEADER_FIELD_ERROR_NAME,
01093                                 DBUS_TYPE_STRING,
01094                                 error_name))
01095         return FALSE;
01096     }
01097   
01098   return TRUE;
01099 }
01100 
01110 void
01111 _dbus_message_lock (DBusMessage  *message)
01112 {
01113   if (!message->locked)
01114     {
01115       /* Fill in our lengths */
01116       _dbus_marshal_set_uint32 (&message->header,
01117                                 message->byte_order,
01118                                 HEADER_LENGTH_OFFSET,
01119                                 _dbus_string_get_length (&message->header));
01120 
01121       _dbus_marshal_set_uint32 (&message->header,
01122                                 message->byte_order,
01123                                 BODY_LENGTH_OFFSET,
01124                                 _dbus_string_get_length (&message->body));
01125 
01126       message->locked = TRUE;
01127     }
01128 }
01129 
01152 static DBusMessage*
01153 dbus_message_new_empty_header (void)
01154 {
01155   DBusMessage *message;
01156   int i;
01157   
01158   message = dbus_new0 (DBusMessage, 1);
01159   if (message == NULL)
01160     return NULL;
01161   
01162   message->refcount.value = 1;
01163   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
01164   message->client_serial = 0;
01165   message->reply_serial = 0;
01166 
01167   _dbus_data_slot_list_init (&message->slot_list);
01168   
01169   i = 0;
01170   while (i <= DBUS_HEADER_FIELD_LAST)
01171     {
01172       message->header_fields[i].name_offset  = -1;
01173       message->header_fields[i].value_offset = -1;
01174       ++i;
01175     }
01176   
01177   if (!_dbus_string_init_preallocated (&message->header, 64))
01178     {
01179       dbus_free (message);
01180       return NULL;
01181     }
01182   
01183   if (!_dbus_string_init_preallocated (&message->body, 64))
01184     {
01185       _dbus_string_free (&message->header);
01186       dbus_free (message);
01187       return NULL;
01188     }
01189 
01190   if (!_dbus_string_init_preallocated (&message->signature, 4))
01191     {
01192       _dbus_string_free (&message->header);
01193       _dbus_string_free (&message->body);
01194       dbus_free (message);
01195       return NULL;
01196     }
01197   
01198   return message;
01199 }
01200 
01209 DBusMessage*
01210 dbus_message_new (int message_type)
01211 {
01212   DBusMessage *message;
01213 
01214   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01215   
01216   message = dbus_message_new_empty_header ();
01217   if (message == NULL)
01218     return NULL;
01219   
01220   if (!dbus_message_create_header (message,
01221                                    message_type,
01222                                    NULL, NULL, NULL, NULL, NULL))
01223     {
01224       dbus_message_unref (message);
01225       return NULL;
01226     }
01227   
01228   return message;
01229 }
01230 
01248 DBusMessage*
01249 dbus_message_new_method_call (const char *service,
01250                               const char *path,
01251                               const char *interface,
01252                               const char *method)
01253 {
01254   DBusMessage *message;
01255 
01256   _dbus_return_val_if_fail (path != NULL, NULL);
01257   _dbus_return_val_if_fail (method != NULL, NULL);
01258   
01259   message = dbus_message_new_empty_header ();
01260   if (message == NULL)
01261     return NULL;
01262   
01263   if (!dbus_message_create_header (message,
01264                                    DBUS_MESSAGE_TYPE_METHOD_CALL,
01265                                    service, path, interface, method, NULL))
01266     {
01267       dbus_message_unref (message);
01268       return NULL;
01269     }
01270   
01271   return message;
01272 }
01273 
01283 DBusMessage*
01284 dbus_message_new_method_return (DBusMessage *method_call)
01285 {
01286   DBusMessage *message;
01287   const char *sender;
01288 
01289   _dbus_return_val_if_fail (method_call != NULL, NULL);
01290   
01291   sender = get_string_field (method_call,
01292                              DBUS_HEADER_FIELD_SENDER_SERVICE,
01293                              NULL);
01294   
01295   /* sender is allowed to be null here in peer-to-peer case */
01296 
01297   message = dbus_message_new_empty_header ();
01298   if (message == NULL)
01299     return NULL;
01300   
01301   if (!dbus_message_create_header (message,
01302                                    DBUS_MESSAGE_TYPE_METHOD_RETURN,
01303                                    sender, NULL, NULL, NULL, NULL))
01304     {
01305       dbus_message_unref (message);
01306       return NULL;
01307     }
01308 
01309   dbus_message_set_no_reply (message, TRUE);
01310 
01311   if (!dbus_message_set_reply_serial (message,
01312                                       dbus_message_get_serial (method_call)))
01313     {
01314       dbus_message_unref (message);
01315       return NULL;
01316     }
01317 
01318   return message;
01319 }
01320 
01333 DBusMessage*
01334 dbus_message_new_signal (const char *path,
01335                          const char *interface,
01336                          const char *name)
01337 {
01338   DBusMessage *message;
01339 
01340   _dbus_return_val_if_fail (path != NULL, NULL);
01341   _dbus_return_val_if_fail (interface != NULL, NULL);
01342   _dbus_return_val_if_fail (name != NULL, NULL);
01343   
01344   message = dbus_message_new_empty_header ();
01345   if (message == NULL)
01346     return NULL;
01347   
01348   if (!dbus_message_create_header (message,
01349                                    DBUS_MESSAGE_TYPE_SIGNAL,
01350                                    NULL, path, interface, name, NULL))
01351     {
01352       dbus_message_unref (message);
01353       return NULL;
01354     }
01355 
01356   dbus_message_set_no_reply (message, TRUE);
01357   
01358   return message;
01359 }
01360 
01370 DBusMessage*
01371 dbus_message_new_error (DBusMessage *reply_to,
01372                         const char  *error_name,
01373                         const char  *error_message)
01374 {
01375   DBusMessage *message;
01376   const char *sender;
01377   DBusMessageIter iter;
01378 
01379   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01380   _dbus_return_val_if_fail (error_name != NULL, NULL);
01381   
01382   sender = get_string_field (reply_to,
01383                              DBUS_HEADER_FIELD_SENDER_SERVICE,
01384                              NULL);
01385 
01386   /* sender may be NULL for non-message-bus case or
01387    * when the message bus is dealing with an unregistered
01388    * connection.
01389    */
01390   message = dbus_message_new_empty_header ();
01391   if (message == NULL)
01392     return NULL;
01393   
01394   if (!dbus_message_create_header (message,
01395                                    DBUS_MESSAGE_TYPE_ERROR,
01396                                    sender, NULL, NULL, NULL, error_name))
01397     {
01398       dbus_message_unref (message);
01399       return NULL;
01400     }
01401 
01402   dbus_message_set_no_reply (message, TRUE);
01403   
01404   if (!dbus_message_set_reply_serial (message,
01405                                       dbus_message_get_serial (reply_to)))
01406     {
01407       dbus_message_unref (message);
01408       return NULL;
01409     }
01410 
01411   if (error_message != NULL)
01412     {
01413       dbus_message_append_iter_init (message, &iter);
01414       if (!dbus_message_iter_append_string (&iter, error_message))
01415         {
01416           dbus_message_unref (message);
01417           return NULL;
01418         }
01419     }
01420   
01421   return message;
01422 }
01423 
01431 DBusMessage *
01432 dbus_message_copy (const DBusMessage *message)
01433 {
01434   DBusMessage *retval;
01435   int i;
01436 
01437   _dbus_return_val_if_fail (message != NULL, NULL);
01438   
01439   retval = dbus_new0 (DBusMessage, 1);
01440   if (retval == NULL)
01441     return NULL;
01442   
01443   retval->refcount.value = 1;
01444   retval->byte_order = message->byte_order;
01445   retval->client_serial = message->client_serial;
01446   retval->reply_serial = message->reply_serial;
01447   retval->header_padding = message->header_padding;
01448   retval->locked = FALSE;
01449   
01450   if (!_dbus_string_init_preallocated (&retval->header,
01451                                        _dbus_string_get_length (&message->header)))
01452     {
01453       dbus_free (retval);
01454       return NULL;
01455     }
01456   
01457   if (!_dbus_string_init_preallocated (&retval->body,
01458                                        _dbus_string_get_length (&message->body)))
01459     {
01460       _dbus_string_free (&retval->header);
01461       dbus_free (retval);
01462       return NULL;
01463     }
01464 
01465   if (!_dbus_string_init_preallocated (&retval->signature,
01466                                        _dbus_string_get_length (&message->signature)))
01467     {
01468       _dbus_string_free (&retval->header);
01469       _dbus_string_free (&retval->body);
01470       dbus_free (retval);
01471       return NULL;
01472     }
01473   
01474   if (!_dbus_string_copy (&message->header, 0,
01475                           &retval->header, 0))
01476     goto failed_copy;
01477 
01478   if (!_dbus_string_copy (&message->body, 0,
01479                           &retval->body, 0))
01480     goto failed_copy;
01481 
01482   if (!_dbus_string_copy (&message->signature, 0,
01483                           &retval->signature, 0))
01484     goto failed_copy;
01485   
01486   for (i = 0; i <= DBUS_HEADER_FIELD_LAST; i++)
01487     {
01488       retval->header_fields[i] = message->header_fields[i];
01489     }
01490   
01491   return retval;
01492 
01493  failed_copy:
01494   _dbus_string_free (&retval->header);
01495   _dbus_string_free (&retval->body);
01496   _dbus_string_free (&retval->signature);
01497   dbus_free (retval);
01498   
01499   return NULL;  
01500 }
01501 
01502 
01509 void
01510 dbus_message_ref (DBusMessage *message)
01511 {
01512   dbus_int32_t old_refcount;
01513 
01514   _dbus_return_if_fail (message != NULL);
01515   
01516   old_refcount = _dbus_atomic_inc (&message->refcount);
01517   _dbus_assert (old_refcount >= 1);
01518 }
01519 
01520 static void
01521 free_size_counter (void *element,
01522                    void *data)
01523 {
01524   DBusCounter *counter = element;
01525   DBusMessage *message = data;
01526   
01527   _dbus_counter_adjust (counter, - message->size_counter_delta);
01528 
01529   _dbus_counter_unref (counter);
01530 }
01531 
01538 void
01539 dbus_message_unref (DBusMessage *message)
01540 {
01541  dbus_int32_t old_refcount;
01542 
01543   _dbus_return_if_fail (message != NULL);
01544   
01545   old_refcount = _dbus_atomic_dec (&message->refcount);
01546   
01547   _dbus_assert (old_refcount >= 0);
01548 
01549   if (old_refcount == 1)
01550     {
01551       /* This calls application callbacks! */
01552       _dbus_data_slot_list_free (&message->slot_list);
01553       
01554       _dbus_list_foreach (&message->size_counters,
01555                           free_size_counter, message);
01556       _dbus_list_clear (&message->size_counters);
01557       
01558       _dbus_string_free (&message->header);
01559       _dbus_string_free (&message->body);
01560       _dbus_string_free (&message->signature);
01561       
01562       dbus_free (message);
01563     }
01564 }
01565 
01577 int
01578 dbus_message_get_type (DBusMessage *message)
01579 {
01580   int type;
01581 
01582   type = _dbus_string_get_byte (&message->header, 1);
01583   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
01584 
01585   return type;
01586 }
01587 
01597 dbus_bool_t
01598 dbus_message_set_path (DBusMessage   *message,
01599                        const char    *object_path)
01600 {
01601   _dbus_return_val_if_fail (message != NULL, FALSE);
01602   _dbus_return_val_if_fail (!message->locked, FALSE);
01603 
01604   return set_string_field (message,
01605                            DBUS_HEADER_FIELD_PATH,
01606                            DBUS_TYPE_OBJECT_PATH,
01607                            object_path);
01608 }
01609 
01618 const char*
01619 dbus_message_get_path (DBusMessage   *message)
01620 {
01621   _dbus_return_val_if_fail (message != NULL, NULL);
01622   
01623   return get_string_field (message, DBUS_HEADER_FIELD_PATH, NULL);
01624 }
01625 
01641 dbus_bool_t
01642 dbus_message_get_path_decomposed (DBusMessage   *message,
01643                                   char        ***path)
01644 {
01645   _dbus_return_val_if_fail (message != NULL, FALSE);
01646   _dbus_return_val_if_fail (path != NULL, FALSE);
01647 
01648   return get_path_field_decomposed (message,
01649                                     DBUS_HEADER_FIELD_PATH,
01650                                     path);
01651 }
01652 
01663 dbus_bool_t
01664 dbus_message_set_interface (DBusMessage  *message,
01665                             const char   *interface)
01666 {
01667   _dbus_return_val_if_fail (message != NULL, FALSE);
01668   _dbus_return_val_if_fail (!message->locked, FALSE);
01669 
01670   return set_string_field (message,
01671                            DBUS_HEADER_FIELD_INTERFACE,
01672                            DBUS_TYPE_STRING,
01673                            interface);
01674 }
01675 
01685 const char*
01686 dbus_message_get_interface (DBusMessage *message)
01687 {
01688   _dbus_return_val_if_fail (message != NULL, NULL);
01689   
01690   return get_string_field (message, DBUS_HEADER_FIELD_INTERFACE, NULL);
01691 }
01692 
01703 dbus_bool_t
01704 dbus_message_set_member (DBusMessage  *message,
01705                        const char   *member)
01706 {
01707   _dbus_return_val_if_fail (message != NULL, FALSE);
01708   _dbus_return_val_if_fail (!message->locked, FALSE);
01709 
01710   return set_string_field (message,
01711                            DBUS_HEADER_FIELD_MEMBER,
01712                            DBUS_TYPE_STRING,
01713                            member);
01714 }
01715 
01724 const char*
01725 dbus_message_get_member (DBusMessage *message)
01726 {
01727   _dbus_return_val_if_fail (message != NULL, NULL);
01728   
01729   return get_string_field (message,
01730                            DBUS_HEADER_FIELD_MEMBER,
01731                            NULL);
01732 }
01733 
01742 dbus_bool_t
01743 dbus_message_set_error_name (DBusMessage  *message,
01744                              const char   *error_name)
01745 {
01746   _dbus_return_val_if_fail (message != NULL, FALSE);
01747   _dbus_return_val_if_fail (!message->locked, FALSE);
01748 
01749   return set_string_field (message,
01750                            DBUS_HEADER_FIELD_ERROR_NAME,
01751                            DBUS_TYPE_STRING,
01752                            error_name);
01753 }
01754 
01761 const char*
01762 dbus_message_get_error_name (DBusMessage *message)
01763 {
01764   _dbus_return_val_if_fail (message != NULL, NULL);
01765   
01766   return get_string_field (message,
01767                            DBUS_HEADER_FIELD_ERROR_NAME,
01768                            NULL);
01769 }
01770 
01778 dbus_bool_t
01779 dbus_message_set_destination (DBusMessage  *message,
01780                               const char   *destination)
01781 {
01782   _dbus_return_val_if_fail (message != NULL, FALSE);
01783   _dbus_return_val_if_fail (!message->locked, FALSE);
01784 
01785   return set_string_field (message,
01786                            DBUS_HEADER_FIELD_SERVICE,
01787                            DBUS_TYPE_STRING,
01788                            destination);
01789 }
01790 
01797 const char*
01798 dbus_message_get_destination (DBusMessage *message)
01799 {
01800   _dbus_return_val_if_fail (message != NULL, NULL);
01801   
01802   return get_string_field (message,
01803                            DBUS_HEADER_FIELD_SERVICE,
01804                            NULL);
01805 }
01806 
01825 dbus_bool_t
01826 dbus_message_append_args (DBusMessage *message,
01827                           int first_arg_type,
01828                           ...)
01829 {
01830   dbus_bool_t retval;
01831   va_list var_args;
01832 
01833   _dbus_return_val_if_fail (message != NULL, FALSE);
01834   
01835   va_start (var_args, first_arg_type);
01836   retval = dbus_message_append_args_valist (message,
01837                                             first_arg_type,
01838                                             var_args);
01839   va_end (var_args);
01840 
01841   return retval;
01842 }
01843 
01857 dbus_bool_t
01858 dbus_message_append_args_valist (DBusMessage *message,
01859                                  int          first_arg_type,
01860                                  va_list      var_args)
01861 {
01862   int type, old_len;
01863   DBusMessageIter iter;
01864 
01865   _dbus_return_val_if_fail (message != NULL, FALSE);
01866   
01867   old_len = _dbus_string_get_length (&message->body);
01868   
01869   type = first_arg_type;
01870 
01871   dbus_message_append_iter_init (message, &iter);
01872   
01873   while (type != DBUS_TYPE_INVALID)
01874     {
01875       switch (type)
01876         {
01877         case DBUS_TYPE_NIL:
01878           if (!dbus_message_iter_append_nil (&iter))
01879             goto errorout;
01880           break;
01881         case DBUS_TYPE_BOOLEAN:
01882           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
01883             goto errorout;
01884           break;
01885         case DBUS_TYPE_INT32:
01886           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
01887             goto errorout;
01888           break;
01889         case DBUS_TYPE_UINT32:
01890           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
01891             goto errorout;          
01892           break;
01893 #ifdef DBUS_HAVE_INT64
01894         case DBUS_TYPE_INT64:
01895           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
01896             goto errorout;
01897           break;
01898         case DBUS_TYPE_UINT64:
01899           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
01900             goto errorout;          
01901           break;
01902 #endif /* DBUS_HAVE_INT64 */
01903         case DBUS_TYPE_DOUBLE:
01904           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
01905             goto errorout;
01906           break;
01907         case DBUS_TYPE_STRING:
01908           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
01909             goto errorout;
01910           break;
01911         case DBUS_TYPE_OBJECT_PATH:
01912 
01913           break;
01914         case DBUS_TYPE_CUSTOM:
01915           {
01916             const char *name;
01917             unsigned char *data;
01918             int len;
01919  
01920             name = va_arg (var_args, const char *);
01921             data = va_arg (var_args, unsigned char *);
01922             len = va_arg (var_args, int);
01923 
01924             if (!dbus_message_iter_append_custom (&iter, name, data, len))
01925               goto errorout;
01926             break;
01927           }
01928         case DBUS_TYPE_ARRAY:
01929           {
01930             void *data;
01931             int len, type;
01932  
01933             type = va_arg (var_args, int);
01934             data = va_arg (var_args, void *);
01935             len = va_arg (var_args, int);
01936 
01937             switch (type)
01938               {
01939               case DBUS_TYPE_BYTE:
01940                 if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
01941                   goto errorout;
01942                 break;
01943               case DBUS_TYPE_BOOLEAN:
01944                 if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
01945                   goto errorout;
01946                 break;
01947               case DBUS_TYPE_INT32:
01948                 if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
01949                   goto errorout;
01950                 break;
01951               case DBUS_TYPE_UINT32:
01952                 if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
01953                   goto errorout;
01954                 break;
01955 #ifdef DBUS_HAVE_INT64
01956               case DBUS_TYPE_INT64:
01957                 if (!dbus_message_iter_append_int64_array (&iter, (dbus_int64_t *)data, len))
01958                   goto errorout;
01959                 break;
01960               case DBUS_TYPE_UINT64:
01961                 if (!dbus_message_iter_append_uint64_array (&iter, (dbus_uint64_t *)data, len))
01962                   goto errorout;
01963                 break;
01964 #endif /* DBUS_HAVE_INT64 */
01965               case DBUS_TYPE_DOUBLE:
01966                 if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
01967                   goto errorout;
01968                 break;
01969               case DBUS_TYPE_STRING:
01970                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
01971                   goto errorout;
01972                 break;
01973               case DBUS_TYPE_NIL:
01974               case DBUS_TYPE_ARRAY:
01975               case DBUS_TYPE_CUSTOM:
01976               case DBUS_TYPE_DICT:
01977                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
01978                 goto errorout;
01979               default:
01980                 _dbus_warn ("Unknown field type %d\n", type);
01981                 goto errorout;
01982               }
01983           }
01984           break;
01985           
01986         case DBUS_TYPE_DICT:
01987           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
01988           goto errorout;
01989         default:
01990           _dbus_warn ("Unknown field type %d\n", type);
01991           goto errorout;
01992         }
01993 
01994       type = va_arg (var_args, int);
01995     }
01996 
01997   return TRUE;
01998 
01999  errorout:
02000   return FALSE;
02001 }
02002 
02003 
02016 dbus_bool_t
02017 dbus_message_get_args (DBusMessage     *message,
02018                        DBusError       *error,
02019                        int              first_arg_type,
02020                        ...)
02021 {
02022   dbus_bool_t retval;
02023   va_list var_args;
02024 
02025   _dbus_return_val_if_fail (message != NULL, FALSE);
02026   _dbus_return_val_if_error_is_set (error, FALSE);
02027   
02028   va_start (var_args, first_arg_type);
02029   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
02030   va_end (var_args);
02031 
02032   return retval;
02033 }
02034 
02047 dbus_bool_t
02048 dbus_message_get_args_valist (DBusMessage     *message,
02049                               DBusError       *error,
02050                               int              first_arg_type,
02051                               va_list          var_args)
02052 {
02053   DBusMessageIter iter;
02054 
02055   _dbus_return_val_if_fail (message != NULL, FALSE);
02056   _dbus_return_val_if_error_is_set (error, FALSE);
02057   
02058   dbus_message_iter_init (message, &iter);
02059   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
02060 }
02061 
02074 dbus_bool_t
02075 dbus_message_iter_get_args (DBusMessageIter *iter,
02076                             DBusError       *error,
02077                             int              first_arg_type,
02078                             ...)
02079 {
02080   dbus_bool_t retval;
02081   va_list var_args;
02082 
02083   _dbus_return_val_if_fail (iter != NULL, FALSE);
02084   _dbus_return_val_if_error_is_set (error, FALSE);
02085   
02086   va_start (var_args, first_arg_type);
02087   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
02088   va_end (var_args);
02089 
02090   return retval;
02091 }
02092 
02115 dbus_bool_t
02116 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
02117                                    DBusError       *error,
02118                                    int              first_arg_type,
02119                                    va_list          var_args)
02120 {
02121   int spec_type, msg_type, i;
02122   dbus_bool_t retval;
02123 
02124   _dbus_return_val_if_fail (iter != NULL, FALSE);
02125   _dbus_return_val_if_error_is_set (error, FALSE);
02126 
02127   retval = FALSE;
02128   
02129   spec_type = first_arg_type;
02130   i = 0;
02131   
02132   while (spec_type != 0)
02133     {
02134       msg_type = dbus_message_iter_get_arg_type (iter);      
02135       
02136       if (msg_type != spec_type)
02137         {
02138           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02139                           "Argument %d is specified to be of type \"%s\", but "
02140                           "is actually of type \"%s\"\n", i,
02141                           _dbus_type_to_string (spec_type),
02142                           _dbus_type_to_string (msg_type));
02143 
02144           goto out;
02145         }
02146 
02147       switch (spec_type)
02148         {
02149         case DBUS_TYPE_NIL:
02150           break;
02151         case DBUS_TYPE_BYTE:
02152           {
02153             unsigned char *ptr;
02154 
02155             ptr = va_arg (var_args, unsigned char *);
02156 
02157             *ptr = dbus_message_iter_get_byte (iter);
02158             break;
02159           }
02160         case DBUS_TYPE_BOOLEAN:
02161           {
02162             dbus_bool_t *ptr;
02163 
02164             ptr = va_arg (var_args, dbus_bool_t *);
02165 
02166             *ptr = dbus_message_iter_get_boolean (iter);
02167             break;
02168           }
02169         case DBUS_TYPE_INT32:
02170           {
02171             dbus_int32_t *ptr;
02172 
02173             ptr = va_arg (var_args, dbus_int32_t *);
02174 
02175             *ptr = dbus_message_iter_get_int32 (iter);
02176             break;
02177           }
02178         case DBUS_TYPE_UINT32:
02179           {
02180             dbus_uint32_t *ptr;
02181 
02182             ptr = va_arg (var_args, dbus_uint32_t *);
02183 
02184             *ptr = dbus_message_iter_get_uint32 (iter);
02185             break;
02186           }
02187 #ifdef DBUS_HAVE_INT64
02188         case DBUS_TYPE_INT64:
02189           {
02190             dbus_int64_t *ptr;
02191 
02192             ptr = va_arg (var_args, dbus_int64_t *);
02193 
02194             *ptr = dbus_message_iter_get_int64 (iter);
02195             break;
02196           }
02197         case DBUS_TYPE_UINT64:
02198           {
02199             dbus_uint64_t *ptr;
02200 
02201             ptr = va_arg (var_args, dbus_uint64_t *);
02202 
02203             *ptr = dbus_message_iter_get_uint64 (iter);
02204             break;
02205           }
02206 #endif /* DBUS_HAVE_INT64 */
02207           
02208         case DBUS_TYPE_DOUBLE:
02209           {
02210             double *ptr;
02211 
02212             ptr = va_arg (var_args, double *);
02213 
02214             *ptr = dbus_message_iter_get_double (iter);
02215             break;
02216           }
02217 
02218         case DBUS_TYPE_STRING:
02219           {
02220             char **ptr;
02221 
02222             ptr = va_arg (var_args, char **);
02223 
02224             *ptr = dbus_message_iter_get_string (iter);
02225 
02226             if (!*ptr)
02227               {
02228                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02229                 goto out;
02230               }
02231             
02232             break;
02233           }
02234 
02235         case DBUS_TYPE_CUSTOM:
02236           {
02237             char **name;
02238             unsigned char **data;
02239             int *len;
02240  
02241             name = va_arg (var_args, char **);
02242             data = va_arg (var_args, unsigned char **);
02243             len = va_arg (var_args, int *);
02244 
02245             if (!dbus_message_iter_get_custom (iter, name, data, len))
02246               {
02247                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02248                 goto out;
02249               }
02250           }
02251           break;
02252         case DBUS_TYPE_ARRAY:
02253           {
02254             void **data;
02255             int *len, type;
02256  
02257             type = va_arg (var_args, int);
02258             data = va_arg (var_args, void *);
02259             len = va_arg (var_args, int *);
02260 
02261             _dbus_return_val_if_fail (data != NULL, FALSE);
02262             _dbus_return_val_if_fail (len != NULL, FALSE);
02263             
02264             if (dbus_message_iter_get_array_type (iter) != type)
02265               {
02266                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02267                                 "Argument %d is specified to be of type \"array of %s\", but "
02268                                 "is actually of type \"array of %s\"\n", i,
02269                                 _dbus_type_to_string (type),
02270                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
02271                 goto out;
02272               }
02273             
02274             switch (type)
02275               {
02276               case DBUS_TYPE_BYTE:
02277                 if (!dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len))
02278                   {
02279                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02280                     goto out;
02281                   }
02282                 break;
02283               case DBUS_TYPE_BOOLEAN:
02284                 if (!dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len))
02285                   {
02286                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02287                     goto out;
02288                   }
02289                 break;
02290               case DBUS_TYPE_INT32:
02291                 if (!dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len))
02292                   {
02293                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02294                     goto out;
02295                   }
02296                 break;
02297               case DBUS_TYPE_UINT32:
02298                 if (!dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len))
02299                   {
02300                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02301                     goto out;
02302                   }
02303                 break;
02304 #ifdef DBUS_HAVE_INT64
02305               case DBUS_TYPE_INT64:
02306                 if (!dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len))
02307                   {
02308                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02309                     goto out;
02310                   }
02311                 break;
02312               case DBUS_TYPE_UINT64:
02313                 if (!dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len))
02314                   {
02315                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02316                     goto out;
02317                   }
02318                 break;
02319 #endif /* DBUS_HAVE_INT64 */
02320               case DBUS_TYPE_DOUBLE:
02321                 if (!dbus_message_iter_get_double_array (iter, (double **)data, len))
02322                   {
02323                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02324                     goto out;
02325                   }
02326                 break;
02327               case DBUS_TYPE_STRING:
02328                 if (!dbus_message_iter_get_string_array (iter, (char ***)data, len))
02329                   {
02330                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02331                     goto out;
02332                   }
02333                 break;
02334               case DBUS_TYPE_NIL:
02335               case DBUS_TYPE_ARRAY:
02336               case DBUS_TYPE_CUSTOM:
02337               case DBUS_TYPE_DICT:
02338                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
02339                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02340                 goto out;
02341               default:
02342                 _dbus_warn ("Unknown field type %d\n", type);
02343                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02344                 goto out;
02345               }
02346           }
02347           break;
02348         case DBUS_TYPE_DICT:
02349           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
02350           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02351           goto out;
02352         default:          
02353           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02354           _dbus_warn ("Unknown field type %d\n", spec_type);
02355           goto out;
02356         }
02357       
02358       spec_type = va_arg (var_args, int);
02359       if (spec_type != 0 && !dbus_message_iter_next (iter))
02360         {
02361           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02362                           "Message has only %d arguments, but more were expected", i);
02363           goto out;
02364         }
02365 
02366       i++;
02367     }
02368   
02369   retval = TRUE;
02370   
02371  out:
02372   
02373   return retval;
02374 }
02375 
02376 
02384 void
02385 dbus_message_iter_init (DBusMessage     *message,
02386                         DBusMessageIter *iter)
02387 {
02388   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02389 
02390   _dbus_return_if_fail (message != NULL);
02391   _dbus_return_if_fail (iter != NULL);
02392   
02393   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
02394   
02395   real->message = message;
02396   real->parent_iter = NULL;
02397   real->changed_stamp = message->changed_stamp;
02398   
02399   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
02400   real->pos = 0;
02401   real->end = _dbus_string_get_length (&message->body);
02402   
02403   real->container_start = 0;
02404   real->container_length_pos = 0;
02405   real->wrote_dict_key = 0;
02406   real->array_type_pos = 0;
02407 }
02408 
02409 #ifndef DBUS_DISABLE_CHECKS
02410 static dbus_bool_t
02411 dbus_message_iter_check (DBusMessageRealIter *iter)
02412 {
02413   if (iter == NULL)
02414     {
02415       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
02416       return FALSE;
02417     }
02418   
02419   if (iter->changed_stamp != iter->message->changed_stamp)
02420     {
02421       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
02422       return FALSE;
02423     }
02424   
02425   if (iter->pos < 0 || iter->pos > iter->end)
02426     {
02427       _dbus_warn ("dbus iterator check failed: invalid position\n");
02428       return FALSE;
02429     }
02430 
02431   return TRUE;
02432 }
02433 #endif /* DBUS_DISABLE_CHECKS */
02434 
02435 static int
02436 skip_array_type (DBusMessageRealIter *iter, int pos)
02437 {
02438   const char *data;
02439 
02440   do
02441     {
02442       data = _dbus_string_get_const_data_len (&iter->message->body,
02443                                               pos++, 1);
02444     }
02445   while (*data == DBUS_TYPE_ARRAY);
02446   
02447   return pos;
02448 }
02449 
02450 /* FIXME what are these _dbus_type_is_valid() checks for?
02451  * haven't we validated the message?
02452  */
02453 static int
02454 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
02455 {
02456   const char *data;
02457   int pos, len;
02458   
02459   switch (iter->type)
02460     {
02461     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02462       data = _dbus_string_get_const_data_len (&iter->message->body,
02463                                               iter->pos, 1);
02464       if (_dbus_type_is_valid (*data))
02465         *type = *data;
02466       else
02467         *type = DBUS_TYPE_INVALID;
02468       
02469       return skip_array_type (iter, iter->pos);
02470       
02471     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02472       data = _dbus_string_get_const_data_len (&iter->message->body,
02473                                               iter->array_type_pos, 1);
02474       if (_dbus_type_is_valid (*data))
02475         *type = *data;
02476       else
02477         *type = DBUS_TYPE_INVALID;
02478       
02479       return iter->pos;
02480       
02481     case DBUS_MESSAGE_ITER_TYPE_DICT:
02482       /* Get the length of the string */
02483       len = _dbus_demarshal_uint32 (&iter->message->body,
02484                                     iter->message->byte_order,
02485                                     iter->pos, &pos);
02486       pos = pos + len + 1;
02487 
02488       data = _dbus_string_get_const_data_len (&iter->message->body,
02489                                               pos, 1);
02490       if (_dbus_type_is_valid (*data))
02491         *type = *data;
02492       else
02493         *type = DBUS_TYPE_INVALID;
02494 
02495       return skip_array_type (iter, pos);
02496       
02497     default:
02498       _dbus_assert_not_reached ("Invalid iter type");
02499       break;
02500     }
02501   *type = DBUS_TYPE_INVALID;
02502   return iter->pos;
02503 }
02504 
02505 
02513 dbus_bool_t
02514 dbus_message_iter_has_next (DBusMessageIter *iter)
02515 {
02516   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02517   int end_pos;
02518   int type, pos;
02519 
02520   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02521 
02522   if (real->pos >= real->end)
02523     return FALSE;
02524   
02525   pos = dbus_message_iter_get_data_start (real, &type);
02526   
02527   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02528                                       real->message->byte_order,
02529                                       type, pos, &end_pos))
02530     return FALSE;
02531   
02532   if (end_pos >= real->end)
02533     return FALSE;
02534 
02535   return TRUE;  
02536 }
02537 
02544 dbus_bool_t
02545 dbus_message_iter_next (DBusMessageIter *iter)
02546 {
02547   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02548   int end_pos;
02549   int type, pos;
02550 
02551   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02552 
02553   pos = dbus_message_iter_get_data_start (real, &type);
02554   
02555   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02556                                       real->message->byte_order,
02557                                       type, pos, &end_pos))
02558     return FALSE;
02559 
02560   if (end_pos >= real->end)
02561     return FALSE;
02562 
02563   real->pos = end_pos;
02564 
02565   return TRUE;
02566 }
02567 
02575 int
02576 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02577 {
02578   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02579   int type, pos;
02580 
02581   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02582 
02583   if (real->pos >= real->end)
02584     {
02585       _dbus_verbose ("  iterator at or beyond end of message\n");
02586       return DBUS_TYPE_INVALID;
02587     }
02588 
02589   pos = dbus_message_iter_get_data_start (real, &type);
02590   
02591   return type;
02592 }
02593 
02594 /* FIXME why do we validate the typecode in here, hasn't the message
02595  * already been verified?
02596  */
02597 static int
02598 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
02599 {
02600   const char *data;
02601   int _array_type_pos;
02602   int len, pos;
02603   
02604   switch (iter->type)
02605     {
02606     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02607       _array_type_pos = iter->pos + 1;
02608       break;
02609     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02610       _array_type_pos = iter->array_type_pos + 1;
02611       break;
02612     case DBUS_MESSAGE_ITER_TYPE_DICT:
02613       /* Get the length of the string */
02614       len = _dbus_demarshal_uint32 (&iter->message->body,
02615                                     iter->message->byte_order,
02616                                     iter->pos, &pos);
02617       pos = pos + len + 1;
02618       data = _dbus_string_get_const_data_len (&iter->message->body,
02619                                               pos + 1, 1);
02620       _array_type_pos = pos + 1;
02621       break;
02622     default:
02623       _dbus_assert_not_reached ("wrong iter type");
02624       return DBUS_TYPE_INVALID;
02625     }
02626 
02627   if (array_type_pos != NULL)
02628     *array_type_pos = _array_type_pos;
02629   
02630   data = _dbus_string_get_const_data_len (&iter->message->body,
02631                                           _array_type_pos, 1);
02632   if (_dbus_type_is_valid (*data))
02633     return  *data;
02634   
02635   return DBUS_TYPE_INVALID;
02636 }
02637 
02638 
02648 int
02649 dbus_message_iter_get_array_type (DBusMessageIter *iter)
02650 {
02651   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02652   int type, pos;
02653 
02654   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02655 
02656   if (real->pos >= real->end)
02657     return DBUS_TYPE_INVALID;
02658 
02659   pos = dbus_message_iter_get_data_start (real, &type);
02660 
02661   _dbus_assert (type == DBUS_TYPE_ARRAY);
02662 
02663   return iter_get_array_type (real, NULL);
02664 }
02665 
02666 
02676 char *
02677 dbus_message_iter_get_string (DBusMessageIter *iter)
02678 {
02679   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02680   int type, pos;
02681 
02682   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02683 
02684   pos = dbus_message_iter_get_data_start (real, &type);
02685   
02686   _dbus_assert (type == DBUS_TYPE_STRING);
02687 
02688   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02689                                  pos, NULL);
02690 }
02691 
02692 #if 0
02693 
02705 char *
02706 dbus_message_iter_get_object_path (DBusMessageIter  *iter)
02707 {
02708   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02709   int type, pos;
02710 
02711   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02712 
02713   pos = dbus_message_iter_get_data_start (real, &type);
02714   
02715   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
02716 
02717   return _dbus_demarshal_object_path (&real->message->body, real->message->byte_order,
02718                                       pos, NULL);
02719 }
02720 #endif
02721 
02735 dbus_bool_t
02736 dbus_message_iter_get_custom (DBusMessageIter   *iter,
02737                               char             **name,
02738                               unsigned char    **value,
02739                               int               *len)
02740 {
02741   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02742   int type, pos;
02743   char *_name;
02744 
02745   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02746 
02747   pos = dbus_message_iter_get_data_start (real, &type);
02748   
02749   _dbus_assert (type == DBUS_TYPE_CUSTOM);
02750   
02751   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02752                                   pos, &pos);
02753 
02754   if (_name == NULL)
02755     return FALSE;
02756   
02757   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
02758                                    pos, NULL, value, len))
02759     {
02760       dbus_free (_name);
02761       return FALSE;
02762     }
02763 
02764   *name = _name;
02765   
02766   return TRUE;
02767 }
02768 
02778 unsigned char
02779 dbus_message_iter_get_byte (DBusMessageIter *iter)
02780 {
02781   unsigned char value;
02782   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02783   int type, pos;
02784 
02785   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02786 
02787   pos = dbus_message_iter_get_data_start (real, &type);
02788   
02789   _dbus_assert (type == DBUS_TYPE_BYTE);
02790 
02791   value = _dbus_string_get_byte (&real->message->body, pos);
02792   
02793   return value;
02794 }
02795 
02796 
02806 dbus_bool_t
02807 dbus_message_iter_get_boolean (DBusMessageIter *iter)
02808 {
02809   unsigned char value;
02810   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02811   int type, pos;
02812 
02813   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02814 
02815   pos = dbus_message_iter_get_data_start (real, &type);
02816   
02817   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
02818 
02819   value = _dbus_string_get_byte (&real->message->body, pos);
02820   
02821   return value;
02822 }
02823 
02833 dbus_int32_t
02834 dbus_message_iter_get_int32 (DBusMessageIter *iter)
02835 {
02836   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02837   int type, pos;
02838 
02839   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02840 
02841   pos = dbus_message_iter_get_data_start (real, &type);
02842   
02843   _dbus_assert (type == DBUS_TYPE_INT32);
02844   
02845   return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
02846                                 pos, NULL);
02847 }
02848 
02858 dbus_uint32_t
02859 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
02860 {
02861   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02862   int type, pos;
02863 
02864   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02865 
02866   pos = dbus_message_iter_get_data_start (real, &type);
02867   
02868   _dbus_assert (type == DBUS_TYPE_UINT32);
02869   
02870   return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
02871                                  pos, NULL);
02872 }
02873 
02874 #ifdef DBUS_HAVE_INT64
02875 
02887 dbus_int64_t
02888 dbus_message_iter_get_int64 (DBusMessageIter *iter)
02889 {
02890   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02891   int type, pos;
02892 
02893   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02894 
02895   pos = dbus_message_iter_get_data_start (real, &type);
02896   
02897   _dbus_assert (type == DBUS_TYPE_INT64);
02898   
02899   return _dbus_demarshal_int64 (&real->message->body, real->message->byte_order,
02900                                 pos, NULL);
02901 }
02902 
02914 dbus_uint64_t
02915 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
02916 {
02917   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02918   int type, pos;
02919 
02920   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02921 
02922   pos = dbus_message_iter_get_data_start (real, &type);
02923   
02924   _dbus_assert (type == DBUS_TYPE_UINT64);
02925   
02926   return _dbus_demarshal_uint64 (&real->message->body, real->message->byte_order,
02927                                  pos, NULL);
02928 }
02929 
02930 #endif /* DBUS_HAVE_INT64 */
02931 
02941 double
02942 dbus_message_iter_get_double (DBusMessageIter *iter)
02943 {
02944   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02945   int type, pos;
02946 
02947   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0.0);
02948 
02949   pos = dbus_message_iter_get_data_start (real, &type);
02950   
02951   _dbus_assert (type == DBUS_TYPE_DOUBLE);
02952   
02953   return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
02954                                  pos, NULL);
02955 }
02956 
02969 void
02970 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
02971                                        DBusMessageIter *array_iter,
02972                                        int             *array_type)
02973 {
02974   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02975   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
02976   int type, pos, len_pos, len, array_type_pos;
02977   int _array_type;
02978 
02979   _dbus_return_if_fail (dbus_message_iter_check (real));
02980 
02981   pos = dbus_message_iter_get_data_start (real, &type);
02982   
02983   _dbus_assert (type == DBUS_TYPE_ARRAY);
02984 
02985   _array_type = iter_get_array_type (real, &array_type_pos);
02986   
02987   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
02988   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
02989                                 pos, &pos);
02990   
02991   array_real->parent_iter = real;
02992   array_real->message = real->message;
02993   array_real->changed_stamp = real->message->changed_stamp;
02994   
02995   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
02996   array_real->pos = pos;
02997   array_real->end = pos + len;
02998   
02999   array_real->container_start = pos;
03000   array_real->container_length_pos = len_pos;
03001   array_real->wrote_dict_key = 0;
03002   array_real->array_type_pos = array_type_pos;
03003   array_real->array_type_done = TRUE;
03004   
03005   if (array_type != NULL)
03006     *array_type = _array_type;
03007 }
03008 
03009 
03018 void
03019 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
03020                                       DBusMessageIter *dict_iter)
03021 {
03022   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03023   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
03024   int type, pos, len_pos, len;
03025 
03026   _dbus_return_if_fail (dbus_message_iter_check (real));
03027 
03028   pos = dbus_message_iter_get_data_start (real, &type);
03029   
03030   _dbus_assert (type == DBUS_TYPE_DICT);
03031 
03032   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
03033   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
03034                                 pos, &pos);
03035   
03036   dict_real->parent_iter = real;
03037   dict_real->message = real->message;
03038   dict_real->changed_stamp = real->message->changed_stamp;
03039   
03040   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
03041   dict_real->pos = pos;
03042   dict_real->end = pos + len;
03043   
03044   dict_real->container_start = pos;
03045   dict_real->container_length_pos = len_pos;
03046   dict_real->wrote_dict_key = 0;
03047 }
03048 
03059 dbus_bool_t
03060 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
03061                                   unsigned char   **value,
03062                                   int              *len)
03063 {
03064   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03065   int type, pos;
03066 
03067   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03068 
03069   pos = dbus_message_iter_get_data_start (real, &type);
03070   
03071   _dbus_assert (type == DBUS_TYPE_ARRAY);
03072 
03073   type = iter_get_array_type (real, NULL);
03074 
03075   _dbus_assert (type == DBUS_TYPE_BYTE);
03076 
03077   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
03078                                    pos, NULL, value, len))
03079     return FALSE;
03080   else
03081     return TRUE;
03082 }
03083 
03094 dbus_bool_t
03095 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
03096                                      unsigned char    **value,
03097                                      int               *len)
03098 {
03099   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03100   int type, pos;
03101 
03102   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03103 
03104   pos = dbus_message_iter_get_data_start (real, &type);
03105   
03106   _dbus_assert (type == DBUS_TYPE_ARRAY);
03107 
03108   type = iter_get_array_type (real, NULL);
03109 
03110   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
03111 
03112   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
03113                                    pos, NULL, value, len))
03114     return FALSE;
03115   else
03116     return TRUE;
03117 }
03118 
03129 dbus_bool_t
03130 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
03131                                     dbus_int32_t   **value,
03132                                     int             *len)
03133 {
03134   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03135   int type, pos;
03136 
03137   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03138 
03139   pos = dbus_message_iter_get_data_start (real, &type);
03140   
03141   _dbus_assert (type == DBUS_TYPE_ARRAY);
03142 
03143   type = iter_get_array_type (real, NULL);
03144   
03145   _dbus_assert (type == DBUS_TYPE_INT32);
03146 
03147   if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
03148                                     pos, NULL, value, len))
03149     return FALSE;
03150   else
03151     return TRUE;
03152 }
03153 
03164 dbus_bool_t
03165 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
03166                                      dbus_uint32_t  **value,
03167                                      int             *len)
03168 {
03169   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03170   int type, pos;
03171 
03172   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03173 
03174   pos = dbus_message_iter_get_data_start (real, &type);
03175   
03176   _dbus_assert (type == DBUS_TYPE_ARRAY);
03177 
03178   type = iter_get_array_type (real, NULL);
03179   _dbus_assert (type == DBUS_TYPE_UINT32);
03180 
03181   if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
03182                                     pos, NULL, value, len))
03183     return FALSE;
03184   else
03185     return TRUE;
03186 }
03187 
03188 #ifdef DBUS_HAVE_INT64
03189 
03202 dbus_bool_t
03203 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
03204                                     dbus_int64_t   **value,
03205                                     int             *len)
03206 {
03207   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03208   int type, pos;
03209 
03210   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03211 
03212   pos = dbus_message_iter_get_data_start (real, &type);
03213   
03214   _dbus_assert (type == DBUS_TYPE_ARRAY);
03215 
03216   type = iter_get_array_type (real, NULL);
03217   
03218   _dbus_assert (type == DBUS_TYPE_INT64);
03219 
03220   if (!_dbus_demarshal_int64_array (&real->message->body, real->message->byte_order,
03221                                     pos, NULL, value, len))
03222     return FALSE;
03223   else
03224     return TRUE;
03225 }
03226 
03239 dbus_bool_t
03240 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
03241                                      dbus_uint64_t  **value,
03242                                      int             *len)
03243 {
03244   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03245   int type, pos;
03246 
03247   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03248 
03249   pos = dbus_message_iter_get_data_start (real, &type);
03250   
03251   _dbus_assert (type == DBUS_TYPE_ARRAY);
03252 
03253   type = iter_get_array_type (real, NULL);
03254   _dbus_assert (type == DBUS_TYPE_UINT64);
03255 
03256   if (!_dbus_demarshal_uint64_array (&real->message->body, real->message->byte_order,
03257                                     pos, NULL, value, len))
03258     return FALSE;
03259   else
03260     return TRUE;
03261 }
03262 
03263 #endif /* DBUS_HAVE_INT64 */
03264 
03275 dbus_bool_t
03276 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
03277                                      double         **value,
03278                                      int             *len)
03279 {
03280   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03281   int type, pos;
03282 
03283   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03284 
03285   pos = dbus_message_iter_get_data_start (real, &type);
03286   
03287   _dbus_assert (type == DBUS_TYPE_ARRAY);
03288 
03289   type = iter_get_array_type (real, NULL);
03290   _dbus_assert (type == DBUS_TYPE_DOUBLE);
03291 
03292   if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
03293                                      pos, NULL, value, len))
03294     return FALSE;
03295   else
03296     return TRUE;
03297 }
03298 
03314 dbus_bool_t
03315 dbus_message_iter_get_string_array (DBusMessageIter *iter,
03316                                     char          ***value,
03317                                     int             *len)
03318 {
03319   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03320   int type, pos;
03321 
03322   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03323 
03324   pos = dbus_message_iter_get_data_start (real, &type);
03325   
03326   _dbus_assert (type == DBUS_TYPE_ARRAY);
03327 
03328   type = iter_get_array_type (real, NULL);
03329   _dbus_assert (type == DBUS_TYPE_STRING);
03330 
03331   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
03332                                      pos, NULL, value, len))
03333     return FALSE;
03334   else
03335     return TRUE;
03336 }
03337 
03338 #if 0
03339 
03357 dbus_bool_t
03358 dbus_message_iter_get_object_path_array (DBusMessageIter *iter,
03359                                          char          ***value,
03360                                          int             *len)
03361 {
03362   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03363   int type, pos;
03364 
03365   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03366 
03367   pos = dbus_message_iter_get_data_start (real, &type);
03368   
03369   _dbus_assert (type == DBUS_TYPE_ARRAY);
03370 
03371   type = iter_get_array_type (real, NULL);
03372   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
03373 
03374   if (!_dbus_demarshal_object_path_array (&real->message->body, real->message->byte_order,
03375                                           pos, NULL, value, len))
03376     return FALSE;
03377   else
03378     return TRUE;
03379 }
03380 #endif
03381 
03391 char *
03392 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
03393 {
03394   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03395 
03396   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
03397 
03398   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03399 
03400   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
03401                                  real->pos, NULL);
03402 }
03403 
03412 void
03413 dbus_message_append_iter_init (DBusMessage     *message,
03414                                DBusMessageIter *iter)
03415 {
03416   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03417 
03418   _dbus_return_if_fail (message != NULL);
03419   _dbus_return_if_fail (iter != NULL);
03420   
03421   real->message = message;
03422   real->parent_iter = NULL;
03423   real->changed_stamp = message->changed_stamp;
03424   
03425   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
03426   real->end = _dbus_string_get_length (&real->message->body);
03427   real->pos = real->end;
03428   
03429   real->container_length_pos = 0;
03430   real->wrote_dict_key = 0;
03431 }
03432 
03433 #ifndef DBUS_DISABLE_CHECKS
03434 static dbus_bool_t
03435 dbus_message_iter_append_check (DBusMessageRealIter *iter)
03436 {
03437   if (iter == NULL)
03438     {
03439       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
03440       return FALSE;
03441     }
03442   
03443   if (iter->message->locked)
03444     {
03445       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
03446       return FALSE;
03447     }
03448       
03449   if (iter->changed_stamp != iter->message->changed_stamp)
03450     {
03451       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
03452       return FALSE;
03453     }
03454   
03455   if (iter->pos != iter->end)
03456     {
03457       _dbus_warn ("dbus iterator check failed: can only append at end of message");
03458       return FALSE;
03459     }
03460   
03461   if (iter->pos != _dbus_string_get_length (&iter->message->body))
03462     {
03463       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
03464       return FALSE;
03465     }
03466 
03467   return TRUE;
03468 }
03469 #endif /* DBUS_DISABLE_CHECKS */
03470 
03471 static dbus_bool_t
03472 dbus_message_iter_append_type (DBusMessageRealIter *iter,
03473                                int                  type)
03474 {
03475   const char *data;
03476   switch (iter->type)
03477     {
03478     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
03479       if (!_dbus_string_append_byte (&iter->message->signature, type))
03480         return FALSE;
03481       
03482       if (!_dbus_string_append_byte (&iter->message->body, type))
03483         {
03484           _dbus_string_shorten (&iter->message->signature, 1);
03485           return FALSE;
03486         }
03487       break;
03488       
03489     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
03490       data = _dbus_string_get_const_data_len (&iter->message->body,
03491                                               iter->array_type_pos, 1);
03492       if (type != *data)
03493         {
03494           _dbus_warn ("Appended element of wrong type for array\n");
03495           return FALSE;
03496         }
03497       break;
03498       
03499     case DBUS_MESSAGE_ITER_TYPE_DICT:
03500       if (!iter->wrote_dict_key)
03501         {
03502           _dbus_warn ("Appending dict data before key name\n");
03503           return FALSE;
03504         }
03505       
03506       if (!_dbus_string_append_byte (&iter->message->body, type))
03507         return FALSE;
03508       
03509       break;
03510       
03511     default:
03512       _dbus_assert_not_reached ("Invalid iter type");
03513       break;
03514     }
03515   
03516   return TRUE;
03517 }
03518 
03519 static void
03520 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
03521 {
03522   iter->changed_stamp = iter->message->changed_stamp;
03523   
03524   /* Set new end of iter */
03525   iter->end = _dbus_string_get_length (&iter->message->body);
03526   iter->pos = iter->end;
03527 
03528   /* Set container length */
03529   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
03530       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
03531     _dbus_marshal_set_uint32 (&iter->message->body,
03532                               iter->message->byte_order,
03533                               iter->container_length_pos,
03534                               iter->end - iter->container_start);
03535   
03536   if (iter->parent_iter)
03537     dbus_message_iter_update_after_change (iter->parent_iter);
03538 }
03539 
03540 static void
03541 dbus_message_iter_append_done (DBusMessageRealIter *iter)
03542 {
03543   iter->message->changed_stamp++;
03544   dbus_message_iter_update_after_change (iter);
03545   iter->wrote_dict_key = FALSE;
03546 }
03547 
03554 dbus_bool_t
03555 dbus_message_iter_append_nil (DBusMessageIter *iter)
03556 {
03557   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03558 
03559   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03560 
03561   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
03562     return FALSE;
03563   
03564   dbus_message_iter_append_done (real);
03565   
03566   return TRUE;
03567 }
03568 
03576 dbus_bool_t
03577 dbus_message_iter_append_boolean (DBusMessageIter *iter,
03578                                   dbus_bool_t     value)
03579 {
03580   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03581 
03582   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03583 
03584   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
03585     return FALSE;
03586   
03587   if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
03588     {
03589       _dbus_string_set_length (&real->message->body, real->pos);
03590       return FALSE;
03591     }
03592 
03593   dbus_message_iter_append_done (real);
03594   
03595   return TRUE;
03596 }
03597 
03605 dbus_bool_t
03606 dbus_message_iter_append_byte (DBusMessageIter *iter,
03607                                unsigned char    value)
03608 {
03609   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03610 
03611   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03612 
03613   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
03614     return FALSE;
03615   
03616   if (!_dbus_string_append_byte (&real->message->body, value))
03617     {
03618       _dbus_string_set_length (&real->message->body, real->pos);
03619       return FALSE;
03620     }
03621 
03622   dbus_message_iter_append_done (real);
03623   
03624   return TRUE;
03625 }
03626 
03627 
03635 dbus_bool_t
03636 dbus_message_iter_append_int32   (DBusMessageIter *iter,
03637                                   dbus_int32_t  value)
03638 {
03639   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03640 
03641   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03642 
03643   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
03644     return FALSE;
03645   
03646   if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
03647     {
03648       _dbus_string_set_length (&real->message->body, real->pos);
03649       return FALSE;
03650     }
03651 
03652   dbus_message_iter_append_done (real);
03653   
03654   return TRUE;
03655 }
03656 
03664 dbus_bool_t
03665 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
03666                                  dbus_uint32_t    value)
03667 {
03668   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03669 
03670   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03671 
03672   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
03673     return FALSE;
03674   
03675   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
03676     {
03677       _dbus_string_set_length (&real->message->body, real->pos);
03678       return FALSE;
03679     }
03680 
03681   dbus_message_iter_append_done (real);
03682   
03683   return TRUE;
03684 }
03685 
03686 #ifdef DBUS_HAVE_INT64
03687 
03697 dbus_bool_t
03698 dbus_message_iter_append_int64   (DBusMessageIter *iter,
03699                                   dbus_int64_t  value)
03700 {
03701   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03702 
03703   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03704 
03705   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT64))
03706     return FALSE;
03707   
03708   if (!_dbus_marshal_int64 (&real->message->body, real->message->byte_order, value))
03709     {
03710       _dbus_string_set_length (&real->message->body, real->pos);
03711       return FALSE;
03712     }
03713 
03714   dbus_message_iter_append_done (real);
03715   
03716   return TRUE;
03717 }
03718 
03728 dbus_bool_t
03729 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
03730                                  dbus_uint64_t    value)
03731 {
03732   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03733 
03734   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03735 
03736   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT64))
03737     return FALSE;
03738   
03739   if (!_dbus_marshal_uint64 (&real->message->body, real->message->byte_order, value))
03740     {
03741       _dbus_string_set_length (&real->message->body, real->pos);
03742       return FALSE;
03743     }
03744 
03745   dbus_message_iter_append_done (real);
03746   
03747   return TRUE;
03748 }
03749 
03750 #endif /* DBUS_HAVE_INT64 */
03751 
03759 dbus_bool_t
03760 dbus_message_iter_append_double (DBusMessageIter *iter,
03761                                  double           value)
03762 {
03763   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03764 
03765   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03766 
03767   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
03768     return FALSE;
03769   
03770   if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
03771     {
03772       _dbus_string_set_length (&real->message->body, real->pos);
03773       return FALSE;
03774     }
03775 
03776   dbus_message_iter_append_done (real);
03777   
03778   return TRUE;
03779 }
03780 
03790 dbus_bool_t
03791 dbus_message_iter_append_string (DBusMessageIter *iter,
03792                                  const char      *value)
03793 {
03794   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03795 
03796   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03797   
03798   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
03799     return FALSE;
03800   
03801   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03802     {
03803       _dbus_string_set_length (&real->message->body, real->pos);
03804       return FALSE;
03805     }
03806 
03807   dbus_message_iter_append_done (real);
03808   
03809   return TRUE;
03810 }
03811 
03824 dbus_bool_t
03825 dbus_message_iter_append_custom (DBusMessageIter      *iter,
03826                                  const char           *name,
03827                                  const unsigned char  *data,
03828                                  int                   len)
03829 {
03830   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03831 
03832   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03833 
03834   if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
03835     return FALSE;
03836   
03837    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
03838     {
03839       _dbus_string_set_length (&real->message->body, real->pos);
03840       return FALSE;
03841     }
03842    
03843   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
03844     {
03845       _dbus_string_set_length (&real->message->body, real->pos);
03846       return FALSE;
03847     }
03848 
03849   dbus_message_iter_append_done (real);
03850   
03851   return TRUE;
03852 }
03853 
03854 
03863 dbus_bool_t
03864 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
03865                                    const char      *value)
03866 {
03867   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03868 
03869   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03870   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03871   
03872   if (real->wrote_dict_key)
03873     {
03874       _dbus_warn ("Appendinging multiple dict key names\n");
03875       return FALSE;
03876     }
03877   
03878   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03879     {
03880       return FALSE;
03881     }
03882 
03883   dbus_message_iter_append_done (real);
03884   real->wrote_dict_key = TRUE;
03885   
03886   return TRUE;
03887 }
03888 
03889 static dbus_bool_t
03890 array_iter_type_mark_done (DBusMessageRealIter *iter)
03891 {
03892   int len_pos;
03893   
03894   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
03895     array_iter_type_mark_done (iter->parent_iter);
03896   else
03897     return TRUE;
03898 
03899   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
03900                                sizeof (dbus_uint32_t));
03901 
03902   /* Empty length for now, backfill later */
03903   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
03904     {
03905       _dbus_string_set_length (&iter->message->body, iter->pos);
03906       return FALSE;
03907     }
03908 
03909   iter->container_start = _dbus_string_get_length (&iter->message->body);
03910   iter->container_length_pos = len_pos;
03911   iter->array_type_done = TRUE;
03912 
03913   return TRUE;
03914 }
03915 
03916 static dbus_bool_t
03917 append_array_type (DBusMessageRealIter *real,
03918                    int                  element_type,
03919                    dbus_bool_t         *array_type_done,
03920                    int                 *array_type_pos)
03921 {
03922   int existing_element_type;
03923   
03924   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
03925     return FALSE;
03926   
03927   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
03928       real->array_type_done)
03929     {
03930       existing_element_type = iter_get_array_type (real, array_type_pos);
03931       if (existing_element_type != element_type)
03932         {
03933           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
03934                       _dbus_type_to_string (element_type),
03935                       _dbus_type_to_string (existing_element_type));
03936           _dbus_string_set_length (&real->message->body, real->pos);
03937           return FALSE;
03938         }
03939       if (array_type_done != NULL)
03940           *array_type_done = TRUE;
03941     }
03942   else
03943     {
03944       if (array_type_pos != NULL)
03945         *array_type_pos = _dbus_string_get_length (&real->message->body);
03946 
03947 
03948       if (!_dbus_string_append_byte (&real->message->signature, element_type))
03949         {
03950           _dbus_string_set_length (&real->message->body, real->pos);
03951           return FALSE;
03952         }
03953       
03954       /* Append element type */
03955       if (!_dbus_string_append_byte (&real->message->body, element_type))
03956         {
03957           _dbus_string_shorten (&real->message->signature, 1);
03958           _dbus_string_set_length (&real->message->body, real->pos);
03959           return FALSE;
03960         }
03961 
03962       if (array_type_done != NULL)
03963         *array_type_done = element_type != DBUS_TYPE_ARRAY;
03964       
03965       if (element_type != DBUS_TYPE_ARRAY &&
03966           !array_iter_type_mark_done (real))
03967         {
03968           _dbus_string_shorten (&real->message->signature, 1);
03969           return FALSE;
03970         }        
03971     }
03972 
03973   return TRUE;
03974 }
03975 
03985 dbus_bool_t
03986 dbus_message_iter_append_array (DBusMessageIter      *iter,
03987                                 DBusMessageIter      *array_iter,
03988                                 int                   element_type)
03989 {
03990   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03991   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
03992   int len_pos;
03993   int array_type_pos;
03994   dbus_bool_t array_type_done;
03995 
03996   if (element_type == DBUS_TYPE_NIL)
03997     {
03998       _dbus_warn ("Can't create NIL arrays\n");
03999       return FALSE;
04000     }
04001   
04002   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04003 
04004   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
04005     return FALSE;
04006 
04007   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
04008 
04009   if (array_type_done)
04010     {
04011       /* Empty length for now, backfill later */
04012       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
04013         {
04014           _dbus_string_set_length (&real->message->body, real->pos);
04015           return FALSE;
04016         }
04017     }
04018   
04019   array_real->parent_iter = real;
04020   array_real->message = real->message;
04021   array_real->changed_stamp = real->message->changed_stamp;
04022   
04023   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
04024   array_real->pos = _dbus_string_get_length (&real->message->body);
04025   array_real->end = array_real->end;
04026   
04027   array_real->container_start = array_real->pos;
04028   array_real->container_length_pos = len_pos;
04029   array_real->wrote_dict_key = 0;
04030   array_real->array_type_done = array_type_done;
04031   array_real->array_type_pos = array_type_pos;
04032 
04033   dbus_message_iter_append_done (array_real);
04034   
04035   return TRUE;
04036 }
04037 
04046 dbus_bool_t
04047 dbus_message_iter_append_dict (DBusMessageIter      *iter,
04048                                DBusMessageIter      *dict_iter)
04049 {
04050   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04051   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
04052   int len_pos;
04053 
04054   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04055   
04056   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
04057     return FALSE;  
04058   
04059   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
04060 
04061   /* Empty length for now, backfill later */
04062   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
04063     {
04064       _dbus_string_set_length (&real->message->body, real->pos);
04065       return FALSE;
04066     }
04067   
04068   dict_real->parent_iter = real;
04069   dict_real->message = real->message;
04070   dict_real->changed_stamp = real->message->changed_stamp;
04071   
04072   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
04073   dict_real->pos = _dbus_string_get_length (&real->message->body);
04074   dict_real->end = dict_real->end;
04075   
04076   dict_real->container_start = dict_real->pos;
04077   dict_real->container_length_pos = len_pos;
04078   dict_real->wrote_dict_key = 0;
04079 
04080   dbus_message_iter_append_done (dict_real);
04081   
04082   return TRUE;
04083 }
04084 
04085 
04094 dbus_bool_t
04095 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
04096                                         unsigned const char *value,
04097                                         int                  len)
04098 {
04099   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04100 
04101   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04102 
04103   if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
04104     return FALSE;
04105   
04106   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
04107     {
04108       _dbus_string_set_length (&real->message->body, real->pos);
04109       return FALSE;
04110     }
04111 
04112   dbus_message_iter_append_done (real);
04113   
04114   return TRUE;
04115 }
04116 
04125 dbus_bool_t
04126 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
04127                                       const dbus_int32_t *value,
04128                                       int                 len)
04129 {
04130   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04131 
04132   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04133 
04134   if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
04135     return FALSE;
04136   
04137   if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
04138     {
04139       _dbus_string_set_length (&real->message->body, real->pos);
04140       return FALSE;
04141     }
04142 
04143   dbus_message_iter_append_done (real);
04144   
04145   return TRUE;
04146 }
04147 
04156 dbus_bool_t
04157 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
04158                                        const dbus_uint32_t *value,
04159                                        int                  len)
04160 {
04161   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04162 
04163   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04164 
04165   if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
04166     return FALSE;
04167   
04168   if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
04169     {
04170       _dbus_string_set_length (&real->message->body, real->pos);
04171       return FALSE;
04172     }
04173 
04174   dbus_message_iter_append_done (real);
04175   
04176   return TRUE;
04177 }
04178 
04179 #ifdef DBUS_HAVE_INT64
04180 
04191 dbus_bool_t
04192 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
04193                                       const dbus_int64_t *value,
04194                                       int                 len)
04195 {
04196   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04197 
04198   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04199 
04200   if (!append_array_type (real, DBUS_TYPE_INT64, NULL, NULL))
04201     return FALSE;
04202   
04203   if (!_dbus_marshal_int64_array (&real->message->body, real->message->byte_order, value, len))
04204     {
04205       _dbus_string_set_length (&real->message->body, real->pos);
04206       return FALSE;
04207     }
04208 
04209   dbus_message_iter_append_done (real);
04210   
04211   return TRUE;
04212 }
04213 
04224 dbus_bool_t
04225 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
04226                                        const dbus_uint64_t *value,
04227                                        int                  len)
04228 {
04229   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04230 
04231   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04232 
04233   if (!append_array_type (real, DBUS_TYPE_UINT64, NULL, NULL))
04234     return FALSE;
04235   
04236   if (!_dbus_marshal_uint64_array (&real->message->body, real->message->byte_order, value, len))
04237     {
04238       _dbus_string_set_length (&real->message->body, real->pos);
04239       return FALSE;
04240     }
04241 
04242   dbus_message_iter_append_done (real);
04243   
04244   return TRUE;
04245 }
04246 #endif /* DBUS_HAVE_INT64 */
04247 
04256 dbus_bool_t
04257 dbus_message_iter_append_double_array (DBusMessageIter *iter,
04258                                        const double    *value,
04259                                        int              len)
04260 {
04261   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04262 
04263   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04264 
04265   if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
04266     return FALSE;
04267   
04268   if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
04269     {
04270       _dbus_string_set_length (&real->message->body, real->pos);
04271       return FALSE;
04272     }
04273 
04274   dbus_message_iter_append_done (real);
04275   
04276   return TRUE;
04277 }
04278 
04287 dbus_bool_t
04288 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
04289                                      unsigned const char *value,
04290                                      int                  len)
04291 {
04292   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04293 
04294   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04295 
04296   if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
04297     return FALSE;
04298   
04299   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
04300     {
04301       _dbus_string_set_length (&real->message->body, real->pos);
04302       return FALSE;
04303     }
04304 
04305   dbus_message_iter_append_done (real);
04306   
04307   return TRUE;
04308 }
04309 
04318 dbus_bool_t
04319 dbus_message_iter_append_string_array (DBusMessageIter *iter,
04320                                        const char     **value,
04321                                        int              len)
04322 {
04323   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04324 
04325   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04326 
04327   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
04328     return FALSE;
04329   
04330   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04331     {
04332       _dbus_string_set_length (&real->message->body, real->pos);
04333       return FALSE;
04334     }
04335 
04336   dbus_message_iter_append_done (real);
04337   
04338   return TRUE;
04339 }
04340 
04348 dbus_bool_t
04349 dbus_message_set_sender (DBusMessage  *message,
04350                          const char   *sender)
04351 {
04352   _dbus_return_val_if_fail (message != NULL, FALSE);
04353   _dbus_return_val_if_fail (!message->locked, FALSE);
04354 
04355   return set_string_field (message,
04356                            DBUS_HEADER_FIELD_SENDER_SERVICE,
04357                            DBUS_TYPE_STRING,
04358                            sender);
04359 }
04360 
04371 void
04372 dbus_message_set_no_reply (DBusMessage *message,
04373                            dbus_bool_t  no_reply)
04374 {
04375   char *header;
04376 
04377   _dbus_return_if_fail (message != NULL);
04378   _dbus_return_if_fail (!message->locked);
04379   
04380   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04381   
04382   if (no_reply)
04383     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
04384   else
04385     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
04386 }
04387 
04395 dbus_bool_t
04396 dbus_message_get_no_reply (DBusMessage *message)
04397 {
04398   const char *header;
04399 
04400   _dbus_return_val_if_fail (message != NULL, FALSE);
04401   
04402   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04403 
04404   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
04405 }
04406 
04414 const char*
04415 dbus_message_get_sender (DBusMessage *message)
04416 {
04417   _dbus_return_val_if_fail (message != NULL, NULL);
04418   
04419   return get_string_field (message, 
04420                            DBUS_HEADER_FIELD_SENDER_SERVICE,
04421                            NULL);
04422 }
04423 
04439 const char*
04440 dbus_message_get_signature (DBusMessage *message)
04441 {
04442   _dbus_return_val_if_fail (message != NULL, NULL);
04443   
04444   return _dbus_string_get_const_data (&message->signature);
04445 }
04446 
04447 static dbus_bool_t
04448 _dbus_message_has_type_interface_member (DBusMessage *message,
04449                                          int          type,
04450                                          const char  *interface,
04451                                          const char  *method)
04452 {
04453   const char *n;
04454 
04455   _dbus_assert (message != NULL);
04456   _dbus_assert (interface != NULL);
04457   _dbus_assert (method != NULL);
04458 
04459   if (dbus_message_get_type (message) != type)
04460     return FALSE;
04461 
04462   /* Optimize by checking the short method name first
04463    * instead of the longer interface name
04464    */  
04465 
04466   n = dbus_message_get_member (message);
04467 
04468   if (n && strcmp (n, method) == 0)
04469     {
04470       n = dbus_message_get_interface (message);
04471       
04472       if (n && strcmp (n, interface) == 0)
04473         return TRUE;
04474     }
04475 
04476   return FALSE;
04477 }
04478 
04491 dbus_bool_t
04492 dbus_message_is_method_call (DBusMessage *message,
04493                              const char  *interface,
04494                              const char  *method)
04495 {
04496   _dbus_return_val_if_fail (message != NULL, FALSE);
04497   _dbus_return_val_if_fail (interface != NULL, FALSE);
04498   _dbus_return_val_if_fail (method != NULL, FALSE);
04499 
04500   return _dbus_message_has_type_interface_member (message,
04501                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
04502                                                   interface, method);
04503 }
04504 
04517 dbus_bool_t
04518 dbus_message_is_signal (DBusMessage *message,
04519                         const char  *interface,
04520                         const char  *signal_name)
04521 {
04522   _dbus_return_val_if_fail (message != NULL, FALSE);
04523   _dbus_return_val_if_fail (interface != NULL, FALSE);
04524   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
04525 
04526   return _dbus_message_has_type_interface_member (message,
04527                                                   DBUS_MESSAGE_TYPE_SIGNAL,
04528                                                   interface, signal_name);
04529 }
04530 
04541 dbus_bool_t
04542 dbus_message_is_error (DBusMessage *message,
04543                         const char  *error_name)
04544 {
04545   const char *n;
04546   
04547   _dbus_return_val_if_fail (message != NULL, FALSE);
04548   _dbus_return_val_if_fail (error_name != NULL, FALSE);
04549 
04550   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04551     return FALSE;
04552 
04553   n = dbus_message_get_error_name (message);
04554 
04555   if (n && strcmp (n, error_name) == 0)
04556     return TRUE;
04557   else
04558     return FALSE;
04559 }
04560 
04571 dbus_bool_t
04572 dbus_message_has_destination (DBusMessage  *message,
04573                               const char   *service)
04574 {
04575   const char *s;
04576 
04577   _dbus_return_val_if_fail (message != NULL, FALSE);
04578   _dbus_return_val_if_fail (service != NULL, FALSE);
04579   
04580   s = dbus_message_get_destination (message);
04581 
04582   if (s && strcmp (s, service) == 0)
04583     return TRUE;
04584   else
04585     return FALSE;
04586 }
04587 
04602 dbus_bool_t
04603 dbus_message_has_sender (DBusMessage  *message,
04604                          const char   *service)
04605 {
04606   const char *s;
04607 
04608   _dbus_return_val_if_fail (message != NULL, FALSE);
04609   _dbus_return_val_if_fail (service != NULL, FALSE);
04610   
04611   s = dbus_message_get_sender (message);
04612 
04613   if (s && strcmp (s, service) == 0)
04614     return TRUE;
04615   else
04616     return FALSE;
04617 }
04618 
04628 dbus_bool_t
04629 dbus_message_has_signature (DBusMessage   *message,
04630                             const char    *signature)
04631 {
04632   _dbus_return_val_if_fail (message != NULL, FALSE);
04633   _dbus_return_val_if_fail (signature != NULL, FALSE);
04634 
04635   return _dbus_string_equal_c_str (&message->signature, signature);
04636 }
04637 
04655 dbus_bool_t
04656 dbus_set_error_from_message (DBusError   *error,
04657                              DBusMessage *message)
04658 {
04659   char *str;
04660 
04661   _dbus_return_val_if_fail (message != NULL, FALSE);
04662   _dbus_return_val_if_error_is_set (error, FALSE);
04663   
04664   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04665     return FALSE;
04666 
04667   str = NULL;
04668   dbus_message_get_args (message, NULL,
04669                          DBUS_TYPE_STRING, &str,
04670                          DBUS_TYPE_INVALID);
04671 
04672   dbus_set_error (error, dbus_message_get_error_name (message),
04673                   str ? "%s" : NULL, str);
04674 
04675   dbus_free (str);
04676   
04677   return TRUE;
04678 }
04679 
04704 /* we definitely use signed ints for sizes, so don't exceed
04705  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
04706  * over 128M is pretty nuts anyhow.
04707  */
04708 
04712 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
04713 
04718 struct DBusMessageLoader
04719 {
04720   int refcount;        
04722   DBusString data;     
04724   DBusList *messages;  
04726   long max_message_size; 
04728   unsigned int buffer_outstanding : 1; 
04730   unsigned int corrupted : 1; 
04731 };
04732 
04743 #define INITIAL_LOADER_DATA_LEN 32
04744 
04751 DBusMessageLoader*
04752 _dbus_message_loader_new (void)
04753 {
04754   DBusMessageLoader *loader;
04755 
04756   loader = dbus_new0 (DBusMessageLoader, 1);
04757   if (loader == NULL)
04758     return NULL;
04759   
04760   loader->refcount = 1;
04761 
04762   /* Try to cap message size at something that won't *totally* hose
04763    * the system if we have a couple of them.
04764    */
04765   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
04766   
04767   if (!_dbus_string_init (&loader->data))
04768     {
04769       dbus_free (loader);
04770       return NULL;
04771     }
04772 
04773   /* preallocate the buffer for speed, ignore failure */
04774   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
04775   _dbus_string_set_length (&loader->data, 0);
04776   
04777   return loader;
04778 }
04779 
04785 void
04786 _dbus_message_loader_ref (DBusMessageLoader *loader)
04787 {
04788   loader->refcount += 1;
04789 }
04790 
04797 void
04798 _dbus_message_loader_unref (DBusMessageLoader *loader)
04799 {
04800   loader->refcount -= 1;
04801   if (loader->refcount == 0)
04802     {
04803       _dbus_list_foreach (&loader->messages,
04804                           (DBusForeachFunction) dbus_message_unref,
04805                           NULL);
04806       _dbus_list_clear (&loader->messages);
04807       _dbus_string_free (&loader->data);
04808       dbus_free (loader);
04809     }
04810 }
04811 
04830 void
04831 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
04832                                  DBusString        **buffer)
04833 {
04834   _dbus_assert (!loader->buffer_outstanding);
04835 
04836   *buffer = &loader->data;
04837   
04838   loader->buffer_outstanding = TRUE;
04839 }
04840 
04845 #define DBUS_MINIMUM_HEADER_SIZE 16
04846 
04847 static dbus_bool_t
04848 decode_string_field (const DBusString   *data,
04849                      int                 field,
04850                      HeaderField        *header_field,
04851                      DBusString         *field_data,
04852                      int                 pos,
04853                      int                 type)
04854 {
04855   int string_data_pos;
04856 
04857   _dbus_assert (header_field != NULL);
04858   _dbus_assert (field_data != NULL);
04859   
04860   if (header_field->name_offset >= 0)
04861     {
04862       _dbus_verbose ("%s field provided twice\n",
04863                      _dbus_header_field_to_string (field));
04864       return FALSE;
04865     }
04866 
04867   if (type != DBUS_TYPE_STRING)
04868     {
04869       _dbus_verbose ("%s field has wrong type %s\n",
04870                      _dbus_header_field_to_string (field),
04871                      _dbus_type_to_string (type));
04872       return FALSE;
04873     }
04874 
04875   /* skip padding after typecode, skip string length;
04876    * we assume that the string arg has already been validated
04877    * for sanity and UTF-8
04878    */
04879   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
04880   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
04881   
04882   _dbus_string_init_const (field_data,
04883                            _dbus_string_get_const_data (data) + string_data_pos);
04884 
04885   header_field->name_offset  = pos;
04886   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
04887   
04888 #if 0
04889   _dbus_verbose ("Found field %s at offset %d\n",
04890                  _dbus_header_field_to_string (field),
04891                  header_field->value_offset);
04892 #endif
04893 
04894   return TRUE;
04895 }
04896 
04897 /* FIXME because the service/interface/member/error names are already
04898  * validated to be in the particular ASCII subset, UTF-8 validating
04899  * them could be skipped as a probably-interesting optimization.
04900  * The UTF-8 validation definitely shows up in profiles.
04901  */
04902 static dbus_bool_t
04903 decode_header_data (const DBusString   *data,
04904                     int                 header_len,
04905                     int                 byte_order,
04906                     int                 message_type,
04907                     HeaderField         fields[DBUS_HEADER_FIELD_LAST + 1],
04908                     int                *message_padding)
04909 {
04910   DBusString field_data;
04911   int pos, new_pos;
04912   int i;
04913   int field;
04914   int type;
04915   
04916   if (header_len < 16)
04917     {
04918       _dbus_verbose ("Header length %d is too short\n", header_len);
04919       return FALSE;
04920     }
04921   
04922   i = 0;
04923   while (i <= DBUS_HEADER_FIELD_LAST)
04924     {
04925       fields[i].name_offset  = -1;
04926       fields[i].value_offset = -1;
04927       ++i;
04928     }
04929   
04930   pos = 16;
04931   while (pos < header_len)
04932     {
04933       field = _dbus_string_get_byte (data, pos);
04934       if (field == DBUS_HEADER_FIELD_INVALID)
04935         break; /* Must be padding */
04936       pos++;
04937 
04938       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
04939         {
04940           _dbus_verbose ("Failed to validate type of named header field pos = %d\n",
04941                          pos);
04942           return FALSE;
04943         }
04944       
04945       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
04946         {
04947           _dbus_verbose ("Failed to validate argument to named header field pos = %d\n",
04948                          pos);
04949           return FALSE;
04950         }
04951 
04952       if (new_pos > header_len)
04953         {
04954           _dbus_verbose ("Named header field tries to extend beyond header length\n");
04955           return FALSE;
04956         }
04957       
04958       switch (field)
04959         {
04960         case DBUS_HEADER_FIELD_SERVICE:
04961           if (!decode_string_field (data, field, &fields[field],
04962                                     &field_data, pos, type))
04963             return FALSE;
04964 
04965           if (!_dbus_string_validate_service (&field_data, 0,
04966                                               _dbus_string_get_length (&field_data)))
04967             {
04968               _dbus_verbose ("service field has invalid content \"%s\"\n",
04969                              _dbus_string_get_const_data (&field_data));
04970               return FALSE;
04971             }
04972           break;
04973 
04974         case DBUS_HEADER_FIELD_INTERFACE:
04975           if (!decode_string_field (data, field, &fields[field],
04976                                     &field_data, pos, type))
04977             return FALSE;
04978 
04979           if (!_dbus_string_validate_interface (&field_data, 0,
04980                                                 _dbus_string_get_length (&field_data)))
04981             {
04982               _dbus_verbose ("interface field has invalid content \"%s\"\n",
04983                              _dbus_string_get_const_data (&field_data));
04984               return FALSE;
04985             }
04986       
04987           if (_dbus_string_equal_c_str (&field_data,
04988                                         DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
04989             {
04990               _dbus_verbose ("Message is on the local interface\n");
04991               return FALSE;
04992             }
04993           break;
04994 
04995         case DBUS_HEADER_FIELD_MEMBER:
04996           if (!decode_string_field (data, field, &fields[field],
04997                                     &field_data, pos, type))
04998             return FALSE;
04999           
05000           if (!_dbus_string_validate_member (&field_data, 0,
05001                                              _dbus_string_get_length (&field_data)))
05002             {
05003               _dbus_verbose ("member field has invalid content \"%s\"\n",
05004                              _dbus_string_get_const_data (&field_data));
05005               return FALSE;
05006             }
05007           break;
05008 
05009         case DBUS_HEADER_FIELD_ERROR_NAME:
05010           if (!decode_string_field (data, field, &fields[field],
05011                                     &field_data, pos, type))
05012             return FALSE;
05013           
05014           if (!_dbus_string_validate_error_name (&field_data, 0,
05015                                                  _dbus_string_get_length (&field_data)))
05016             {
05017               _dbus_verbose ("error-name field has invalid content \"%s\"\n",
05018                              _dbus_string_get_const_data (&field_data));
05019               return FALSE;
05020             }
05021           break;
05022           
05023         case DBUS_HEADER_FIELD_SENDER_SERVICE:
05024           if (!decode_string_field (data, field, &fields[field],
05025                                     &field_data, pos, type))
05026             return FALSE;
05027           
05028           if (!_dbus_string_validate_service (&field_data, 0,
05029                                               _dbus_string_get_length (&field_data)))
05030             {
05031               _dbus_verbose ("sender-service field has invalid content \"%s\"\n",
05032                              _dbus_string_get_const_data (&field_data));
05033               return FALSE;
05034             }
05035           break;
05036 
05037         case DBUS_HEADER_FIELD_PATH:
05038 
05039           /* Path was already validated as part of standard
05040            * type validation, since there's an OBJECT_PATH
05041            * type.
05042            */
05043           
05044           if (fields[field].name_offset >= 0)
05045             {
05046               _dbus_verbose ("path field provided twice\n");
05047               return FALSE;
05048             }
05049           if (type != DBUS_TYPE_OBJECT_PATH)
05050             {
05051               _dbus_verbose ("path field has wrong type\n");
05052               return FALSE;
05053             }
05054 
05055           fields[field].name_offset  = pos;
05056           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05057 
05058           /* No forging signals from the local path */
05059           {
05060             const char *s;
05061             s = _dbus_string_get_const_data_len (data,
05062                                                  fields[field].value_offset,
05063                                                  _dbus_string_get_length (data) -
05064                                                  fields[field].value_offset);
05065             if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
05066               {
05067                 _dbus_verbose ("Message is on the local path\n");
05068                 return FALSE;
05069               }
05070           }
05071           
05072           _dbus_verbose ("Found path at offset %d\n",
05073                          fields[field].value_offset);
05074           break;
05075           
05076         case DBUS_HEADER_FIELD_REPLY_SERIAL:
05077           if (fields[field].name_offset >= 0)
05078             {
05079               _dbus_verbose ("reply field provided twice\n");
05080               return FALSE;
05081             }
05082 
05083           if (type != DBUS_TYPE_UINT32)
05084             {
05085               _dbus_verbose ("reply field has wrong type\n");
05086               return FALSE;
05087             }
05088           
05089           fields[field].name_offset  = pos;
05090           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05091 
05092           _dbus_verbose ("Found reply serial %u at offset %d\n",
05093                          _dbus_demarshal_uint32 (data,
05094                                                  byte_order,
05095                                                  fields[field].value_offset,
05096                                                  NULL),
05097                          fields[field].value_offset);
05098           break;
05099 
05100         default:
05101           _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
05102                          field, pos);
05103         }
05104       
05105       pos = new_pos;
05106     }
05107 
05108   if (pos < header_len)
05109     {
05110       /* Alignment padding, verify that it's nul */
05111       if ((header_len - pos) >= 8)
05112         {
05113           _dbus_verbose ("too much header alignment padding\n");
05114           return FALSE;
05115         }
05116 
05117       if (!_dbus_string_validate_nul (data,
05118                                       pos, (header_len - pos)))
05119         {
05120           _dbus_verbose ("header alignment padding is not nul\n");
05121           return FALSE;
05122         }
05123     }
05124 
05125   /* Depending on message type, enforce presence of certain fields. */
05126   switch (message_type)
05127     {
05128     case DBUS_MESSAGE_TYPE_SIGNAL:
05129     case DBUS_MESSAGE_TYPE_METHOD_CALL:
05130       if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
05131         {
05132           _dbus_verbose ("No path field provided\n");
05133           return FALSE;
05134         }
05135       /* FIXME make this optional, only for method calls */
05136       if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
05137         {
05138           _dbus_verbose ("No interface field provided\n");
05139           return FALSE;
05140         }
05141       if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
05142         {
05143           _dbus_verbose ("No member field provided\n");
05144           return FALSE;
05145         }
05146       break;
05147     case DBUS_MESSAGE_TYPE_ERROR:
05148       if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
05149         {
05150           _dbus_verbose ("No error-name field provided\n");
05151           return FALSE;
05152         }
05153       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05154         {
05155           _dbus_verbose ("No reply serial field provided in error\n");
05156           return FALSE;
05157         }
05158       break;
05159     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
05160       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05161         {
05162           _dbus_verbose ("No reply serial field provided in method return\n");
05163           return FALSE;
05164         }
05165       break;
05166     default:
05167       /* An unknown type, spec requires us to ignore it */
05168       break;
05169     }
05170   
05171   if (message_padding)
05172     *message_padding = header_len - pos;  
05173   
05174   return TRUE;
05175 }
05176 
05187 void
05188 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
05189                                     DBusString         *buffer,
05190                                     int                 bytes_read)
05191 {
05192   _dbus_assert (loader->buffer_outstanding);
05193   _dbus_assert (buffer == &loader->data);
05194 
05195   loader->buffer_outstanding = FALSE;
05196 }
05197 
05198 static dbus_bool_t
05199 load_one_message (DBusMessageLoader *loader,
05200                   int                byte_order,
05201                   int                message_type,
05202                   int                header_len,
05203                   int                body_len)
05204 {
05205   DBusMessage *message;
05206   HeaderField fields[DBUS_HEADER_FIELD_LAST + 1];
05207   int i;
05208   int next_arg;
05209   dbus_bool_t oom;
05210   int header_padding;
05211   
05212   message = NULL;
05213   oom = FALSE;
05214   
05215 #if 0
05216   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
05217 #endif    
05218 
05219   if (!decode_header_data (&loader->data,
05220                            header_len, byte_order,
05221                            message_type,
05222                            fields, &header_padding))
05223     {
05224       _dbus_verbose ("Header was invalid\n");
05225       loader->corrupted = TRUE;
05226       goto failed;
05227     }
05228           
05229   next_arg = header_len;
05230   while (next_arg < (header_len + body_len))
05231     {
05232       int type;
05233       int prev = next_arg;
05234 
05235       if (!_dbus_marshal_validate_type (&loader->data, next_arg,
05236                                         &type, &next_arg))
05237         {
05238           _dbus_verbose ("invalid typecode at offset %d\n", prev);
05239           loader->corrupted = TRUE;
05240           goto failed;
05241         }
05242       
05243       if (!_dbus_marshal_validate_arg (&loader->data,
05244                                        byte_order,
05245                                        0,
05246                                        type, -1,
05247                                        next_arg,
05248                                        &next_arg))
05249         {
05250           _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
05251           loader->corrupted = TRUE;
05252           goto failed;
05253         }
05254 
05255       _dbus_assert (next_arg > prev);
05256     }
05257           
05258   if (next_arg > (header_len + body_len))
05259     {
05260       _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
05261                      next_arg, header_len, body_len,
05262                      header_len + body_len);
05263       loader->corrupted = TRUE;
05264       goto failed;
05265     }
05266 
05267   message = dbus_message_new_empty_header ();
05268   if (message == NULL)
05269     {
05270       _dbus_verbose ("Failed to allocate empty message\n");
05271       oom = TRUE;
05272       goto failed;
05273     }
05274 
05275   message->byte_order = byte_order;
05276   message->header_padding = header_padding;
05277           
05278   /* Copy in the offsets we found */
05279   i = 0;
05280   while (i <= DBUS_HEADER_FIELD_LAST)
05281     {
05282       message->header_fields[i] = fields[i];
05283       ++i;
05284     }
05285           
05286   if (!_dbus_list_append (&loader->messages, message))
05287     {
05288       _dbus_verbose ("Failed to append new message to loader queue\n");
05289       oom = TRUE;
05290       goto failed;
05291     }
05292 
05293   _dbus_assert (_dbus_string_get_length (&message->header) == 0);
05294   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
05295 
05296   _dbus_assert (_dbus_string_get_length (&loader->data) >=
05297                 (header_len + body_len));
05298           
05299   if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
05300     {
05301       _dbus_verbose ("Failed to move header into new message\n");
05302       oom = TRUE;
05303       goto failed;
05304     }
05305           
05306   if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
05307     {
05308       _dbus_verbose ("Failed to move body into new message\n");
05309       
05310       oom = TRUE;
05311       goto failed;
05312     }
05313 
05314   _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
05315   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
05316 
05317   /* Fill in caches (we checked the types of these fields
05318    * earlier)
05319    */
05320   message->reply_serial = get_uint_field (message,
05321                                           DBUS_HEADER_FIELD_REPLY_SERIAL);
05322   
05323   message->client_serial = _dbus_demarshal_uint32 (&message->header,
05324                                                    message->byte_order,
05325                                                    CLIENT_SERIAL_OFFSET,
05326                                                    NULL);
05327   if (message->client_serial == 0 ||
05328       (message->header_fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset >= 0 && message->reply_serial == 0))
05329     {
05330       _dbus_verbose ("client_serial = %d reply_serial = %d, one of these no good\n",
05331                      message->client_serial,
05332                      message->reply_serial);
05333       
05334       loader->corrupted = TRUE;
05335       goto failed;
05336     }
05337           
05338   /* Fill in signature (FIXME should do this during validation,
05339    * but I didn't want to spend time on it since we want to change
05340    * the wire format to contain the signature anyway)
05341    */
05342   {
05343     DBusMessageIter iter;
05344 
05345     dbus_message_iter_init (message, &iter);
05346 
05347     do
05348       {
05349         int t;
05350 
05351         t = dbus_message_iter_get_arg_type (&iter);
05352         if (t == DBUS_TYPE_INVALID)
05353           break;
05354 
05355         if (!_dbus_string_append_byte (&message->signature,
05356                                        t))
05357           {
05358             _dbus_verbose ("failed to append type byte to signature\n");
05359             oom = TRUE;
05360             goto failed;
05361           }
05362 
05363         if (t == DBUS_TYPE_ARRAY)
05364           {
05365             DBusMessageIter child_iter;
05366             int array_type = t;
05367 
05368             child_iter = iter;
05369                     
05370             while (array_type == DBUS_TYPE_ARRAY)
05371               {
05372                 DBusMessageIter parent_iter = child_iter;
05373                 dbus_message_iter_init_array_iterator (&parent_iter,
05374                                                        &child_iter,
05375                                                        &array_type);
05376                                             
05377                 if (!_dbus_string_append_byte (&message->signature,
05378                                                array_type))
05379                   {
05380                     _dbus_verbose ("failed to append array type byte to signature\n");
05381 
05382                     oom = TRUE;
05383                     goto failed;
05384                   }
05385               }
05386           }
05387       }
05388     while (dbus_message_iter_next (&iter));
05389   }
05390           
05391   _dbus_verbose ("Loaded message %p\n", message);
05392 
05393   _dbus_assert (!oom);
05394   _dbus_assert (!loader->corrupted);
05395 
05396   return TRUE;
05397 
05398  failed:
05399   
05400   /* Clean up */
05401   
05402   if (message != NULL)
05403     {
05404       /* Put the data back so we can try again later if it was an OOM issue */
05405       if (_dbus_string_get_length (&message->body) > 0)
05406         {
05407           dbus_bool_t result;
05408           
05409           result = _dbus_string_copy_len (&message->body, 0, body_len,
05410                                           &loader->data, 0);
05411           
05412           _dbus_assert (result); /* because DBusString never reallocs smaller */
05413         }
05414       
05415       if (_dbus_string_get_length (&message->header) > 0)
05416         {
05417           dbus_bool_t result;
05418           
05419           result = _dbus_string_copy_len (&message->header, 0, header_len,
05420                                           &loader->data, 0);
05421           
05422           _dbus_assert (result); /* because DBusString never reallocs smaller */
05423         }
05424 
05425       /* does nothing if the message isn't in the list */
05426       _dbus_list_remove_last (&loader->messages, message);
05427 
05428       dbus_message_unref (message);
05429     }
05430 
05431   
05432   return !oom;
05433 }
05434 
05448 dbus_bool_t
05449 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
05450 {
05451   while (!loader->corrupted && _dbus_string_get_length (&loader->data) >= 16)
05452     {
05453       const char *header_data;
05454       int byte_order, message_type, header_len, body_len;
05455       dbus_uint32_t header_len_unsigned, body_len_unsigned;
05456       
05457       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
05458 
05459       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
05460 
05461       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
05462         {
05463           _dbus_verbose ("Message has protocol version %d ours is %d\n",
05464                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
05465           loader->corrupted = TRUE;
05466           return TRUE;
05467         }
05468       
05469       byte_order = header_data[BYTE_ORDER_OFFSET];
05470 
05471       if (byte_order != DBUS_LITTLE_ENDIAN &&
05472           byte_order != DBUS_BIG_ENDIAN)
05473         {
05474           _dbus_verbose ("Message with bad byte order '%c' received\n",
05475                          byte_order);
05476           loader->corrupted = TRUE;
05477           return TRUE;
05478         }
05479 
05480       /* Unknown types are ignored, but INVALID is
05481        * disallowed
05482        */
05483       message_type = header_data[TYPE_OFFSET];
05484       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
05485         {
05486           _dbus_verbose ("Message with bad type '%d' received\n",
05487                          message_type);
05488           loader->corrupted = TRUE;
05489           return TRUE;
05490         }      
05491       
05492       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
05493       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
05494 
05495       if (header_len_unsigned < 16)
05496         {
05497           _dbus_verbose ("Message had broken too-small header length %u\n",
05498                          header_len_unsigned);
05499           loader->corrupted = TRUE;
05500           return TRUE;
05501         }
05502 
05503       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
05504           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
05505         {
05506           _dbus_verbose ("Header or body length too large (%u %u)\n",
05507                          header_len_unsigned,
05508                          body_len_unsigned);
05509           loader->corrupted = TRUE;
05510           return TRUE;
05511         }
05512 
05513       /* Now that we know the values are in signed range, get
05514        * rid of stupid unsigned, just causes bugs
05515        */
05516       header_len = header_len_unsigned;
05517       body_len = body_len_unsigned;
05518 
05519       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
05520         {
05521           
05522           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
05523                          header_len);
05524           loader->corrupted = TRUE;
05525           return TRUE;
05526         }
05527       
05528       if (header_len + body_len > loader->max_message_size)
05529         {
05530           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
05531                          header_len, body_len, loader->max_message_size);
05532           loader->corrupted = TRUE;
05533           return TRUE;
05534         }
05535 
05536       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
05537         {
05538           if (!load_one_message (loader, byte_order, message_type,
05539                                  header_len, body_len))
05540             return FALSE;
05541         }
05542       else
05543         return TRUE;
05544     }
05545 
05546   return TRUE;
05547 }
05548 
05556 DBusMessage*
05557 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
05558 {
05559   if (loader->messages)
05560     return loader->messages->data;
05561   else
05562     return NULL;
05563 }
05564 
05573 DBusMessage*
05574 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
05575 {
05576   return _dbus_list_pop_first (&loader->messages);
05577 }
05578 
05587 DBusList*
05588 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
05589 {
05590   return _dbus_list_pop_first_link (&loader->messages);
05591 }
05592 
05599 void
05600 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
05601                                            DBusList           *link)
05602 {
05603   _dbus_list_prepend_link (&loader->messages, link);
05604 }
05605 
05615 dbus_bool_t
05616 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
05617 {
05618   return loader->corrupted;
05619 }
05620 
05627 void
05628 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
05629                                            long                size)
05630 {
05631   if (size > MAX_SANE_MESSAGE_SIZE)
05632     {
05633       _dbus_verbose ("clamping requested max message size %ld to %d\n",
05634                      size, MAX_SANE_MESSAGE_SIZE);
05635       size = MAX_SANE_MESSAGE_SIZE;
05636     }
05637   loader->max_message_size = size;
05638 }
05639 
05646 long
05647 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
05648 {
05649   return loader->max_message_size;
05650 }
05651 
05652 static DBusDataSlotAllocator slot_allocator;
05653 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
05654 
05669 dbus_bool_t
05670 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
05671 {
05672   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05673                                           _DBUS_LOCK_NAME (message_slots),
05674                                           slot_p);
05675 }
05676 
05688 void
05689 dbus_message_free_data_slot (dbus_int32_t *slot_p)
05690 {
05691   _dbus_return_if_fail (*slot_p >= 0);
05692   
05693   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05694 }
05695 
05709 dbus_bool_t
05710 dbus_message_set_data (DBusMessage     *message,
05711                        dbus_int32_t     slot,
05712                        void            *data,
05713                        DBusFreeFunction free_data_func)
05714 {
05715   DBusFreeFunction old_free_func;
05716   void *old_data;
05717   dbus_bool_t retval;
05718 
05719   _dbus_return_val_if_fail (message != NULL, FALSE);
05720   _dbus_return_val_if_fail (slot >= 0, FALSE);
05721 
05722   retval = _dbus_data_slot_list_set (&slot_allocator,
05723                                      &message->slot_list,
05724                                      slot, data, free_data_func,
05725                                      &old_free_func, &old_data);
05726 
05727   if (retval)
05728     {
05729       /* Do the actual free outside the message lock */
05730       if (old_free_func)
05731         (* old_free_func) (old_data);
05732     }
05733 
05734   return retval;
05735 }
05736 
05745 void*
05746 dbus_message_get_data (DBusMessage   *message,
05747                        dbus_int32_t   slot)
05748 {
05749   void *res;
05750 
05751   _dbus_return_val_if_fail (message != NULL, NULL);
05752   
05753   res = _dbus_data_slot_list_get (&slot_allocator,
05754                                   &message->slot_list,
05755                                   slot);
05756 
05757   return res;
05758 }
05759 
05773 int
05774 dbus_message_type_from_string (const char *type_str)
05775 {
05776   if (strcmp (type_str, "method_call") == 0)
05777     return DBUS_MESSAGE_TYPE_METHOD_CALL;
05778   if (strcmp (type_str, "method_return") == 0)
05779     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
05780   else if (strcmp (type_str, "signal") == 0)
05781     return DBUS_MESSAGE_TYPE_SIGNAL;
05782   else if (strcmp (type_str, "error") == 0)
05783     return DBUS_MESSAGE_TYPE_ERROR;
05784   else
05785     return DBUS_MESSAGE_TYPE_INVALID;
05786 }
05787 
05789 #ifdef DBUS_BUILD_TESTS
05790 #include "dbus-test.h"
05791 #include <stdio.h>
05792 #include <stdlib.h>
05793 
05794 static void
05795 message_iter_test (DBusMessage *message)
05796 {
05797   DBusMessageIter iter, dict, array, array2;
05798   char *str;
05799   unsigned char *data;
05800   dbus_int32_t *our_int_array;
05801   int len;
05802   
05803   dbus_message_iter_init (message, &iter);
05804 
05805   /* String tests */
05806   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
05807     _dbus_assert_not_reached ("Argument type isn't string");
05808 
05809   str = dbus_message_iter_get_string (&iter);
05810   if (strcmp (str, "Test string") != 0)
05811     _dbus_assert_not_reached ("Strings differ");
05812   dbus_free (str);
05813 
05814   if (!dbus_message_iter_next (&iter))
05815     _dbus_assert_not_reached ("Reached end of arguments");
05816 
05817   /* Signed integer tests */
05818   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
05819     _dbus_assert_not_reached ("Argument type isn't int32");
05820 
05821   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
05822     _dbus_assert_not_reached ("Signed integers differ");
05823 
05824   if (!dbus_message_iter_next (&iter))
05825     _dbus_assert_not_reached ("Reached end of fields");
05826   
05827   /* Unsigned integer tests */
05828   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
05829     _dbus_assert_not_reached ("Argument type isn't int32");
05830 
05831   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
05832     _dbus_assert_not_reached ("Unsigned integers differ");
05833 
05834   if (!dbus_message_iter_next (&iter))
05835     _dbus_assert_not_reached ("Reached end of arguments");
05836 
05837   /* Double tests */
05838   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
05839     _dbus_assert_not_reached ("Argument type isn't double");
05840 
05841   if (dbus_message_iter_get_double (&iter) != 3.14159)
05842     _dbus_assert_not_reached ("Doubles differ");
05843 
05844   if (!dbus_message_iter_next (&iter))
05845     _dbus_assert_not_reached ("Reached end of arguments");
05846 
05847   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
05848     _dbus_assert_not_reached ("Argument type not an array");
05849 
05850   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
05851     _dbus_assert_not_reached ("Array type not double");
05852 
05853   
05854   dbus_message_iter_init_array_iterator (&iter, &array, NULL);
05855 
05856   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
05857     _dbus_assert_not_reached ("Argument type isn't double");
05858 
05859   if (dbus_message_iter_get_double (&array) != 1.5)
05860     _dbus_assert_not_reached ("Unsigned integers differ");
05861 
05862   if (!dbus_message_iter_next (&array))
05863     _dbus_assert_not_reached ("Reached end of arguments");
05864 
05865   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
05866     _dbus_assert_not_reached ("Argument type isn't double");
05867 
05868   if (dbus_message_iter_get_double (&array) != 2.5)
05869     _dbus_assert_not_reached ("Unsigned integers differ");
05870 
05871   if (dbus_message_iter_next (&array))
05872     _dbus_assert_not_reached ("Didn't reach end of arguments");
05873   
05874   if (!dbus_message_iter_next (&iter))
05875     _dbus_assert_not_reached ("Reached end of arguments");
05876   
05877 
05878   /* dict */
05879 
05880   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
05881     _dbus_assert_not_reached ("not dict type");
05882      
05883   dbus_message_iter_init_dict_iterator (&iter, &dict);
05884 
05885   str = dbus_message_iter_get_dict_key (&dict);
05886   if (str == NULL || strcmp (str, "test") != 0)
05887     _dbus_assert_not_reached ("wrong dict key");
05888   dbus_free (str);
05889 
05890   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
05891     _dbus_assert_not_reached ("wrong dict entry type");
05892 
05893   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
05894     _dbus_assert_not_reached ("wrong dict entry value");
05895 
05896   if (!dbus_message_iter_next (&dict))
05897     _dbus_assert_not_reached ("reached end of dict");
05898   
05899   /* array of array of int32 (in dict) */
05900 
05901   str = dbus_message_iter_get_dict_key (&dict);
05902   if (str == NULL || strcmp (str, "array") != 0)
05903     _dbus_assert_not_reached ("wrong dict key");
05904   dbus_free (str);
05905   
05906   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
05907     _dbus_assert_not_reached ("Argument type not an array");
05908 
05909   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
05910     _dbus_assert_not_reached ("Array type not array");
05911 
05912   dbus_message_iter_init_array_iterator (&dict, &array, NULL);
05913 
05914   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
05915     _dbus_assert_not_reached ("Argument type isn't array");
05916   
05917   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
05918     _dbus_assert_not_reached ("Array type not int32");
05919   
05920   dbus_message_iter_init_array_iterator (&array, &array2, NULL);
05921 
05922   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
05923     _dbus_assert_not_reached ("Argument type isn't int32");
05924 
05925   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
05926     _dbus_assert_not_reached ("Signed integers differ");
05927 
05928   if (!dbus_message_iter_next (&array2))
05929     _dbus_assert_not_reached ("Reached end of arguments");
05930 
05931   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
05932     _dbus_assert_not_reached ("Signed integers differ");
05933 
05934   if (dbus_message_iter_next (&array2))
05935     _dbus_assert_not_reached ("Didn't reached end of arguments");
05936 
05937   if (!dbus_message_iter_next (&array))
05938     _dbus_assert_not_reached ("Reached end of arguments");
05939 
05940   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
05941     _dbus_assert_not_reached ("Array type not int32");
05942 
05943   if (!dbus_message_iter_get_int32_array (&array,
05944                                           &our_int_array,
05945                                           &len))
05946     _dbus_assert_not_reached ("couldn't get int32 array");
05947 
05948   _dbus_assert (len == 3);
05949   _dbus_assert (our_int_array[0] == 0x34567812 &&
05950                 our_int_array[1] == 0x45678123 &&
05951                 our_int_array[2] == 0x56781234);
05952   dbus_free (our_int_array);
05953   
05954   if (dbus_message_iter_next (&array))
05955     _dbus_assert_not_reached ("Didn't reach end of array");
05956 
05957   if (dbus_message_iter_next (&dict))
05958     _dbus_assert_not_reached ("Didn't reach end of dict");
05959   
05960   if (!dbus_message_iter_next (&iter))
05961     _dbus_assert_not_reached ("Reached end of arguments");
05962   
05963   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
05964     {
05965       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
05966       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
05967     }
05968   
05969   if (dbus_message_iter_get_byte (&iter) != 0xF0)
05970     _dbus_assert_not_reached ("wrong value after dict");
05971 
05972 
05973   if (!dbus_message_iter_next (&iter))
05974     _dbus_assert_not_reached ("Reached end of arguments");
05975   
05976   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
05977     _dbus_assert_not_reached ("not a nil type");
05978   
05979   if (!dbus_message_iter_next (&iter))
05980     _dbus_assert_not_reached ("Reached end of arguments");
05981   
05982   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_CUSTOM)
05983     _dbus_assert_not_reached ("wrong type after dict");
05984 
05985   if (!dbus_message_iter_get_custom (&iter, &str, &data, &len))
05986     _dbus_assert_not_reached ("failed to get custom type");
05987 
05988   _dbus_assert (strcmp (str, "MyTypeName")==0);
05989   _dbus_assert (len == 5);
05990   _dbus_assert (strcmp (data, "data")==0);
05991   dbus_free (str);
05992   dbus_free (data);
05993   
05994   if (dbus_message_iter_next (&iter))
05995     _dbus_assert_not_reached ("Didn't reach end of arguments");
05996 }
05997 
05998 
05999 static dbus_bool_t
06000 check_message_handling_type (DBusMessageIter *iter,
06001                              int type)
06002 {
06003   DBusMessageIter child_iter;
06004   
06005   switch (type)
06006     {
06007     case DBUS_TYPE_NIL:
06008       break;
06009     case DBUS_TYPE_BYTE:
06010       dbus_message_iter_get_byte (iter);
06011       break;
06012     case DBUS_TYPE_BOOLEAN:
06013       dbus_message_iter_get_boolean (iter);
06014       break;
06015     case DBUS_TYPE_INT32:
06016       dbus_message_iter_get_int32 (iter);
06017       break;
06018     case DBUS_TYPE_UINT32:
06019       dbus_message_iter_get_uint32 (iter);
06020       break;
06021     case DBUS_TYPE_INT64:
06022 #ifdef DBUS_HAVE_INT64
06023       dbus_message_iter_get_int64 (iter);
06024 #endif
06025       break;
06026     case DBUS_TYPE_UINT64:
06027 #ifdef DBUS_HAVE_INT64
06028       dbus_message_iter_get_uint64 (iter);
06029 #endif
06030       break;
06031     case DBUS_TYPE_DOUBLE:
06032       dbus_message_iter_get_double (iter);
06033       break;
06034     case DBUS_TYPE_STRING:
06035       {
06036         char *str;
06037         str = dbus_message_iter_get_string (iter);
06038         if (str == NULL)
06039           {
06040             _dbus_warn ("NULL string in message\n");
06041             return FALSE;
06042           }
06043         dbus_free (str);
06044       }
06045       break;
06046     case DBUS_TYPE_CUSTOM:
06047       {
06048         char *name;
06049         unsigned char *data;
06050         int len;
06051         
06052         if (!dbus_message_iter_get_custom (iter, &name, &data, &len))
06053           {
06054             _dbus_warn ("error reading name from custom type\n");
06055             return FALSE;
06056           }
06057         dbus_free (data);
06058         dbus_free (name);
06059       }
06060       break;
06061     case DBUS_TYPE_ARRAY:
06062       {
06063         int array_type;
06064 
06065         dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type);
06066 
06067         while (dbus_message_iter_has_next (&child_iter))
06068           {
06069             if (!check_message_handling_type (&child_iter, array_type))
06070               {
06071                 _dbus_warn ("error in array element\n");
06072                 return FALSE;
06073               }
06074             
06075             if (!dbus_message_iter_next (&child_iter))
06076               break;
06077           }
06078       }
06079       break;
06080     case DBUS_TYPE_DICT:
06081       {
06082         int entry_type;
06083         char *key;
06084         
06085         dbus_message_iter_init_dict_iterator (iter, &child_iter);
06086 
06087         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
06088           {
06089             key = dbus_message_iter_get_dict_key (&child_iter);
06090             if (key == NULL)
06091               {
06092                 _dbus_warn ("error reading dict key\n");
06093                 return FALSE;
06094               }
06095             dbus_free (key);
06096             
06097             if (!check_message_handling_type (&child_iter, entry_type))
06098               {
06099                 _dbus_warn ("error in dict value\n");
06100                 return FALSE;
06101               }
06102             
06103             if (!dbus_message_iter_next (&child_iter))
06104               break;
06105           }
06106       }
06107       break;
06108       
06109     default:
06110       _dbus_warn ("unknown type %d\n", type);
06111       return FALSE;
06112       break;
06113     }
06114   return TRUE;
06115 }
06116   
06117   
06118 static dbus_bool_t
06119 check_message_handling (DBusMessage *message)
06120 {
06121   DBusMessageIter iter;
06122   int type;
06123   dbus_bool_t retval;
06124   dbus_uint32_t client_serial;
06125   
06126   retval = FALSE;
06127   
06128   client_serial = dbus_message_get_serial (message);
06129 
06130   /* can't use set_serial due to the assertions at the start of it */
06131   _dbus_marshal_set_uint32 (&message->header,
06132                             message->byte_order,
06133                             CLIENT_SERIAL_OFFSET,
06134                             client_serial);
06135   
06136   if (client_serial != dbus_message_get_serial (message))
06137     {
06138       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
06139       goto failed;
06140     }
06141   
06142   /* If we implement message_set_arg (message, n, value)
06143    * then we would want to test it here
06144    */
06145 
06146   dbus_message_iter_init (message, &iter);
06147   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
06148     {
06149       if (!check_message_handling_type (&iter, type))
06150         goto failed;
06151 
06152       if (!dbus_message_iter_next (&iter))
06153         break;
06154     }
06155   
06156   retval = TRUE;
06157   
06158  failed:
06159   return retval;
06160 }
06161 
06162 static dbus_bool_t
06163 check_have_valid_message (DBusMessageLoader *loader)
06164 {
06165   DBusMessage *message;
06166   dbus_bool_t retval;
06167 
06168   message = NULL;
06169   retval = FALSE;
06170 
06171   if (!_dbus_message_loader_queue_messages (loader))
06172     _dbus_assert_not_reached ("no memory to queue messages");
06173   
06174   if (_dbus_message_loader_get_is_corrupted (loader))
06175     {
06176       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
06177       goto failed;
06178     }
06179   
06180   message = _dbus_message_loader_pop_message (loader);
06181   if (message == NULL)
06182     {
06183       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
06184       goto failed;
06185     }
06186   
06187   if (_dbus_string_get_length (&loader->data) > 0)
06188     {
06189       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
06190       goto failed;
06191     }
06192 
06193   /* Verify that we're able to properly deal with the message.
06194    * For example, this would detect improper handling of messages
06195    * in nonstandard byte order.
06196    */
06197   if (!check_message_handling (message))
06198     goto failed;  
06199   
06200   retval = TRUE;
06201 
06202  failed:
06203   if (message)
06204     dbus_message_unref (message);
06205 
06206   return retval;
06207 }
06208 
06209 static dbus_bool_t
06210 check_invalid_message (DBusMessageLoader *loader)
06211 {
06212   dbus_bool_t retval;
06213 
06214   retval = FALSE;
06215 
06216   if (!_dbus_message_loader_queue_messages (loader))
06217     _dbus_assert_not_reached ("no memory to queue messages");
06218   
06219   if (!_dbus_message_loader_get_is_corrupted (loader))
06220     {
06221       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
06222       goto failed;
06223     }
06224 
06225   retval = TRUE;
06226 
06227  failed:
06228   return retval;
06229 }
06230 
06231 static dbus_bool_t
06232 check_incomplete_message (DBusMessageLoader *loader)
06233 {
06234   DBusMessage *message;
06235   dbus_bool_t retval;
06236 
06237   message = NULL;
06238   retval = FALSE;
06239 
06240   if (!_dbus_message_loader_queue_messages (loader))
06241     _dbus_assert_not_reached ("no memory to queue messages");
06242   
06243   if (_dbus_message_loader_get_is_corrupted (loader))
06244     {
06245       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
06246       goto failed;
06247     }
06248   
06249   message = _dbus_message_loader_pop_message (loader);
06250   if (message != NULL)
06251     {
06252       _dbus_warn ("loaded message that was expected to be incomplete\n");
06253       goto failed;
06254     }
06255 
06256   retval = TRUE;
06257 
06258  failed:
06259   if (message)
06260     dbus_message_unref (message);
06261   return retval;
06262 }
06263 
06264 static dbus_bool_t
06265 check_loader_results (DBusMessageLoader      *loader,
06266                       DBusMessageValidity     validity)
06267 {
06268   if (!_dbus_message_loader_queue_messages (loader))
06269     _dbus_assert_not_reached ("no memory to queue messages");
06270   
06271   switch (validity)
06272     {
06273     case _DBUS_MESSAGE_VALID:
06274       return check_have_valid_message (loader);
06275     case _DBUS_MESSAGE_INVALID:
06276       return check_invalid_message (loader);
06277     case _DBUS_MESSAGE_INCOMPLETE:
06278       return check_incomplete_message (loader);
06279     case _DBUS_MESSAGE_UNKNOWN:
06280       return TRUE;
06281     }
06282 
06283   _dbus_assert_not_reached ("bad DBusMessageValidity");
06284   return FALSE;
06285 }
06286 
06287 
06296 dbus_bool_t
06297 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
06298                                             dbus_bool_t          is_raw,
06299                                             DBusString          *data)
06300 {
06301   dbus_bool_t retval;
06302 
06303   retval = FALSE;  
06304 
06305   if (is_raw)
06306     {
06307       DBusError error;
06308 
06309       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
06310       dbus_error_init (&error);
06311       if (!_dbus_file_get_contents (data, filename, &error))
06312         {
06313           _dbus_warn ("Could not load message file %s: %s\n",
06314                       _dbus_string_get_const_data (filename),
06315                       error.message);
06316           dbus_error_free (&error);
06317           goto failed;
06318         }
06319     }
06320   else
06321     {
06322       if (!_dbus_message_data_load (data, filename))
06323         {
06324           _dbus_warn ("Could not load message file %s\n",
06325                       _dbus_string_get_const_data (filename));
06326           goto failed;
06327         }
06328     }
06329 
06330   retval = TRUE;
06331   
06332  failed:
06333 
06334   return retval;
06335 }
06336 
06346 dbus_bool_t
06347 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
06348                                            dbus_bool_t          is_raw,
06349                                            DBusMessageValidity  expected_validity)
06350 {
06351   DBusString data;
06352   dbus_bool_t retval;
06353 
06354   retval = FALSE;
06355   
06356   if (!_dbus_string_init (&data))
06357     _dbus_assert_not_reached ("could not allocate string\n");
06358 
06359   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
06360                                                    &data))
06361     goto failed;
06362 
06363   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
06364 
06365  failed:
06366 
06367   if (!retval)
06368     {
06369       if (_dbus_string_get_length (&data) > 0)
06370         _dbus_verbose_bytes_of_string (&data, 0,
06371                                        _dbus_string_get_length (&data));
06372       
06373       _dbus_warn ("Failed message loader test on %s\n",
06374                   _dbus_string_get_const_data (filename));
06375     }
06376   
06377   _dbus_string_free (&data);
06378 
06379   return retval;
06380 }
06381 
06390 dbus_bool_t
06391 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
06392                                            DBusMessageValidity  expected_validity)
06393 {
06394   DBusMessageLoader *loader;
06395   dbus_bool_t retval;
06396   int len;
06397   int i;
06398 
06399   loader = NULL;
06400   retval = FALSE;
06401 
06402   /* Write the data one byte at a time */
06403   
06404   loader = _dbus_message_loader_new ();
06405 
06406   /* check some trivial loader functions */
06407   _dbus_message_loader_ref (loader);
06408   _dbus_message_loader_unref (loader);
06409   _dbus_message_loader_get_max_message_size (loader);
06410   
06411   len = _dbus_string_get_length (data);
06412   for (i = 0; i < len; i++)
06413     {
06414       DBusString *buffer;
06415 
06416       _dbus_message_loader_get_buffer (loader, &buffer);
06417       _dbus_string_append_byte (buffer,
06418                                 _dbus_string_get_byte (data, i));
06419       _dbus_message_loader_return_buffer (loader, buffer, 1);
06420     }
06421   
06422   if (!check_loader_results (loader, expected_validity))
06423     goto failed;
06424 
06425   _dbus_message_loader_unref (loader);
06426   loader = NULL;
06427 
06428   /* Write the data all at once */
06429   
06430   loader = _dbus_message_loader_new ();
06431 
06432   {
06433     DBusString *buffer;
06434     
06435     _dbus_message_loader_get_buffer (loader, &buffer);
06436     _dbus_string_copy (data, 0, buffer,
06437                        _dbus_string_get_length (buffer));
06438     _dbus_message_loader_return_buffer (loader, buffer, 1);
06439   }
06440   
06441   if (!check_loader_results (loader, expected_validity))
06442     goto failed;
06443 
06444   _dbus_message_loader_unref (loader);
06445   loader = NULL;  
06446 
06447   /* Write the data 2 bytes at a time */
06448   
06449   loader = _dbus_message_loader_new ();
06450 
06451   len = _dbus_string_get_length (data);
06452   for (i = 0; i < len; i += 2)
06453     {
06454       DBusString *buffer;
06455 
06456       _dbus_message_loader_get_buffer (loader, &buffer);
06457       _dbus_string_append_byte (buffer,
06458                                 _dbus_string_get_byte (data, i));
06459       if ((i+1) < len)
06460         _dbus_string_append_byte (buffer,
06461                                   _dbus_string_get_byte (data, i+1));
06462       _dbus_message_loader_return_buffer (loader, buffer, 1);
06463     }
06464   
06465   if (!check_loader_results (loader, expected_validity))
06466     goto failed;
06467 
06468   _dbus_message_loader_unref (loader);
06469   loader = NULL;
06470   
06471   retval = TRUE;
06472   
06473  failed:
06474   
06475   if (loader)
06476     _dbus_message_loader_unref (loader);
06477   
06478   return retval;
06479 }
06480 
06481 static dbus_bool_t
06482 process_test_subdir (const DBusString          *test_base_dir,
06483                      const char                *subdir,
06484                      DBusMessageValidity        validity,
06485                      DBusForeachMessageFileFunc function,
06486                      void                      *user_data)
06487 {
06488   DBusString test_directory;
06489   DBusString filename;
06490   DBusDirIter *dir;
06491   dbus_bool_t retval;
06492   DBusError error;
06493 
06494   retval = FALSE;
06495   dir = NULL;
06496   
06497   if (!_dbus_string_init (&test_directory))
06498     _dbus_assert_not_reached ("didn't allocate test_directory\n");
06499 
06500   _dbus_string_init_const (&filename, subdir);
06501   
06502   if (!_dbus_string_copy (test_base_dir, 0,
06503                           &test_directory, 0))
06504     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
06505   
06506   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
06507     _dbus_assert_not_reached ("couldn't allocate full path");
06508 
06509   _dbus_string_free (&filename);
06510   if (!_dbus_string_init (&filename))
06511     _dbus_assert_not_reached ("didn't allocate filename string\n");
06512 
06513   dbus_error_init (&error);
06514   dir = _dbus_directory_open (&test_directory, &error);
06515   if (dir == NULL)
06516     {
06517       _dbus_warn ("Could not open %s: %s\n",
06518                   _dbus_string_get_const_data (&test_directory),
06519                   error.message);
06520       dbus_error_free (&error);
06521       goto failed;
06522     }
06523 
06524   printf ("Testing %s:\n", subdir);
06525   
06526  next:
06527   while (_dbus_directory_get_next_file (dir, &filename, &error))
06528     {
06529       DBusString full_path;
06530       dbus_bool_t is_raw;
06531       
06532       if (!_dbus_string_init (&full_path))
06533         _dbus_assert_not_reached ("couldn't init string");
06534 
06535       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
06536         _dbus_assert_not_reached ("couldn't copy dir to full_path");
06537 
06538       if (!_dbus_concat_dir_and_file (&full_path, &filename))
06539         _dbus_assert_not_reached ("couldn't concat file to dir");
06540 
06541       if (_dbus_string_ends_with_c_str (&filename, ".message"))
06542         is_raw = FALSE;
06543       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
06544         is_raw = TRUE;
06545       else
06546         {
06547           _dbus_verbose ("Skipping non-.message file %s\n",
06548                          _dbus_string_get_const_data (&filename));
06549           _dbus_string_free (&full_path);
06550           goto next;
06551         }
06552 
06553       printf ("    %s\n",
06554               _dbus_string_get_const_data (&filename));
06555       
06556       _dbus_verbose (" expecting %s for %s\n",
06557                      validity == _DBUS_MESSAGE_VALID ? "valid" :
06558                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
06559                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
06560                      _dbus_string_get_const_data (&filename));
06561       
06562       if (! (*function) (&full_path, is_raw, validity, user_data))
06563         {
06564           _dbus_string_free (&full_path);
06565           goto failed;
06566         }
06567       else
06568         _dbus_string_free (&full_path);
06569     }
06570 
06571   if (dbus_error_is_set (&error))
06572     {
06573       _dbus_warn ("Could not get next file in %s: %s\n",
06574                   _dbus_string_get_const_data (&test_directory),
06575                   error.message);
06576       dbus_error_free (&error);
06577       goto failed;
06578     }
06579     
06580   retval = TRUE;
06581   
06582  failed:
06583 
06584   if (dir)
06585     _dbus_directory_close (dir);
06586   _dbus_string_free (&test_directory);
06587   _dbus_string_free (&filename);
06588 
06589   return retval;
06590 }
06591                      
06601 dbus_bool_t
06602 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
06603                                                DBusForeachMessageFileFunc func,
06604                                                void                      *user_data)
06605 {
06606   DBusString test_directory;
06607   dbus_bool_t retval;
06608 
06609   retval = FALSE;
06610   
06611   _dbus_string_init_const (&test_directory, test_data_dir);
06612 
06613   if (!process_test_subdir (&test_directory, "valid-messages",
06614                             _DBUS_MESSAGE_VALID, func, user_data))
06615     goto failed;
06616 
06617   if (!process_test_subdir (&test_directory, "invalid-messages",
06618                             _DBUS_MESSAGE_INVALID, func, user_data))
06619     goto failed;
06620   
06621   if (!process_test_subdir (&test_directory, "incomplete-messages",
06622                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
06623     goto failed;
06624 
06625   retval = TRUE;
06626   
06627  failed:
06628 
06629   _dbus_string_free (&test_directory);
06630   
06631   return retval;
06632 }
06633 
06634 static void
06635 verify_test_message (DBusMessage *message)
06636 {
06637   DBusMessageIter iter, dict;
06638   DBusError error;
06639   dbus_int32_t our_int;
06640   char *our_str;
06641   double our_double;
06642   dbus_bool_t our_bool;
06643   dbus_uint32_t our_uint32;
06644   dbus_int32_t *our_uint32_array;
06645   int our_uint32_array_len;
06646   dbus_int32_t *our_int32_array;
06647   int our_int32_array_len;
06648   char **our_string_array;
06649   int our_string_array_len;
06650 #ifdef DBUS_HAVE_INT64
06651   dbus_int64_t our_int64;
06652   dbus_uint64_t our_uint64;
06653   dbus_int64_t *our_uint64_array;
06654   int our_uint64_array_len;
06655   dbus_int64_t *our_int64_array;
06656   int our_int64_array_len;
06657 #endif
06658   double *our_double_array;
06659   int our_double_array_len;
06660   unsigned char *our_byte_array;
06661   int our_byte_array_len;
06662   unsigned char *our_boolean_array;
06663   int our_boolean_array_len;
06664   
06665   dbus_message_iter_init (message, &iter);
06666 
06667   dbus_error_init (&error);
06668   if (!dbus_message_iter_get_args (&iter, &error,
06669                                    DBUS_TYPE_INT32, &our_int,
06670 #ifdef DBUS_HAVE_INT64
06671                                    DBUS_TYPE_INT64, &our_int64,
06672                                    DBUS_TYPE_UINT64, &our_uint64,
06673 #endif
06674                                    DBUS_TYPE_STRING, &our_str,
06675                                    DBUS_TYPE_DOUBLE, &our_double,
06676                                    DBUS_TYPE_BOOLEAN, &our_bool,
06677                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
06678                                    &our_uint32_array, &our_uint32_array_len,
06679                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
06680                                    &our_int32_array, &our_int32_array_len,
06681 #ifdef DBUS_HAVE_INT64
06682                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
06683                                    &our_uint64_array, &our_uint64_array_len,
06684                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
06685                                    &our_int64_array, &our_int64_array_len,
06686 #endif
06687                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
06688                                    &our_string_array, &our_string_array_len,
06689                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
06690                                    &our_double_array, &our_double_array_len,
06691                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
06692                                    &our_byte_array, &our_byte_array_len,
06693                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
06694                                    &our_boolean_array, &our_boolean_array_len,
06695                                    0))
06696     {
06697       _dbus_warn ("error: %s - %s\n", error.name,
06698                   (error.message != NULL) ? error.message : "no message");
06699       _dbus_assert_not_reached ("Could not get arguments");
06700     }
06701 
06702   if (our_int != -0x12345678)
06703     _dbus_assert_not_reached ("integers differ!");
06704 
06705 #ifdef DBUS_HAVE_INT64
06706   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
06707     _dbus_assert_not_reached ("64-bit integers differ!");
06708   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
06709     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
06710 #endif
06711   
06712   if (our_double != 3.14159)
06713     _dbus_assert_not_reached ("doubles differ!");
06714 
06715   if (strcmp (our_str, "Test string") != 0)
06716     _dbus_assert_not_reached ("strings differ!");
06717   dbus_free (our_str);
06718 
06719   if (!our_bool)
06720     _dbus_assert_not_reached ("booleans differ");
06721 
06722   if (our_uint32_array_len != 4 ||
06723       our_uint32_array[0] != 0x12345678 ||
06724       our_uint32_array[1] != 0x23456781 ||
06725       our_uint32_array[2] != 0x34567812 ||
06726       our_uint32_array[3] != 0x45678123)
06727     _dbus_assert_not_reached ("uint array differs");
06728   dbus_free (our_uint32_array);
06729 
06730   if (our_int32_array_len != 4 ||
06731       our_int32_array[0] != 0x12345678 ||
06732       our_int32_array[1] != -0x23456781 ||
06733       our_int32_array[2] != 0x34567812 ||
06734       our_int32_array[3] != -0x45678123)
06735     _dbus_assert_not_reached ("int array differs");
06736   dbus_free (our_int32_array);
06737 
06738 #ifdef DBUS_HAVE_INT64
06739   if (our_uint64_array_len != 4 ||
06740       our_uint64_array[0] != 0x12345678 ||
06741       our_uint64_array[1] != 0x23456781 ||
06742       our_uint64_array[2] != 0x34567812 ||
06743       our_uint64_array[3] != 0x45678123)
06744     _dbus_assert_not_reached ("uint64 array differs");
06745   dbus_free (our_uint64_array);
06746   
06747   if (our_int64_array_len != 4 ||
06748       our_int64_array[0] != 0x12345678 ||
06749       our_int64_array[1] != -0x23456781 ||
06750       our_int64_array[2] != 0x34567812 ||
06751       our_int64_array[3] != -0x45678123)
06752     _dbus_assert_not_reached ("int64 array differs");
06753   dbus_free (our_int64_array);
06754 #endif /* DBUS_HAVE_INT64 */
06755   
06756   if (our_string_array_len != 4)
06757     _dbus_assert_not_reached ("string array has wrong length");
06758 
06759   if (strcmp (our_string_array[0], "Foo") != 0 ||
06760       strcmp (our_string_array[1], "bar") != 0 ||
06761       strcmp (our_string_array[2], "") != 0 ||
06762       strcmp (our_string_array[3], "woo woo woo woo") != 0)
06763     _dbus_assert_not_reached ("string array differs");
06764 
06765   dbus_free_string_array (our_string_array);
06766 
06767   if (our_double_array_len != 3)
06768     _dbus_assert_not_reached ("double array had wrong length");
06769 
06770   /* On all IEEE machines (i.e. everything sane) exact equality
06771    * should be preserved over the wire
06772    */
06773   if (our_double_array[0] != 0.1234 ||
06774       our_double_array[1] != 9876.54321 ||
06775       our_double_array[2] != -300.0)
06776     _dbus_assert_not_reached ("double array had wrong values");
06777 
06778   dbus_free (our_double_array);
06779 
06780   if (our_byte_array_len != 4)
06781     _dbus_assert_not_reached ("byte array had wrong length");
06782 
06783   if (our_byte_array[0] != 'a' ||
06784       our_byte_array[1] != 'b' ||
06785       our_byte_array[2] != 'c' ||
06786       our_byte_array[3] != 234)
06787     _dbus_assert_not_reached ("byte array had wrong values");
06788 
06789   dbus_free (our_byte_array);
06790 
06791   if (our_boolean_array_len != 5)
06792     _dbus_assert_not_reached ("bool array had wrong length");
06793 
06794   if (our_boolean_array[0] != TRUE ||
06795       our_boolean_array[1] != FALSE ||
06796       our_boolean_array[2] != TRUE ||
06797       our_boolean_array[3] != TRUE ||
06798       our_boolean_array[4] != FALSE)
06799     _dbus_assert_not_reached ("bool array had wrong values");
06800 
06801   dbus_free (our_boolean_array);
06802   
06803   if (!dbus_message_iter_next (&iter))
06804     _dbus_assert_not_reached ("Reached end of arguments");
06805 
06806   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
06807     _dbus_assert_not_reached ("not dict type");
06808      
06809   dbus_message_iter_init_dict_iterator (&iter, &dict);
06810 
06811   our_str = dbus_message_iter_get_dict_key (&dict);
06812   if (our_str == NULL || strcmp (our_str, "test") != 0)
06813     _dbus_assert_not_reached ("wrong dict key");
06814   dbus_free (our_str);
06815 
06816   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
06817     {
06818       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
06819       _dbus_assert_not_reached ("wrong dict entry type");
06820     }
06821 
06822   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
06823     {
06824       _dbus_verbose ("dict entry val: %x\n", our_uint32);
06825       _dbus_assert_not_reached ("wrong dict entry value");
06826     }
06827 
06828   if (dbus_message_iter_next (&dict))
06829     _dbus_assert_not_reached ("Didn't reach end of dict");
06830   
06831   if (!dbus_message_iter_next (&iter))
06832     _dbus_assert_not_reached ("Reached end of arguments");
06833   
06834   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
06835     _dbus_assert_not_reached ("wrong type after dict");
06836   
06837   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
06838     _dbus_assert_not_reached ("wrong value after dict");
06839 
06840   if (dbus_message_iter_next (&iter))
06841     _dbus_assert_not_reached ("Didn't reach end of arguments");
06842 }
06843 
06850 dbus_bool_t
06851 _dbus_message_test (const char *test_data_dir)
06852 {
06853   DBusMessage *message;
06854   DBusMessageLoader *loader;
06855   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
06856   int i;
06857   const char *data;
06858   DBusMessage *copy;
06859   const char *name1;
06860   const char *name2;
06861   const dbus_uint32_t our_uint32_array[] =
06862     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
06863   const dbus_uint32_t our_int32_array[] =
06864     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
06865 #ifdef DBUS_HAVE_INT64
06866   const dbus_uint64_t our_uint64_array[] =
06867     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
06868   const dbus_uint64_t our_int64_array[] =
06869     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
06870 #endif
06871   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
06872   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
06873   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
06874   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
06875   char sig[64];
06876   const char *s;
06877   char *t;
06878   DBusError error;
06879   
06880   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
06881 
06882   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
06883                                           "/org/freedesktop/TestPath",
06884                                           "Foo.TestInterface",
06885                                           "TestMethod");
06886   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
06887   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
06888                                              "TestMethod"));
06889   _dbus_assert (strcmp (dbus_message_get_path (message),
06890                         "/org/freedesktop/TestPath") == 0);
06891   _dbus_message_set_serial (message, 1234);
06892   /* string length including nul byte not a multiple of 4 */
06893   if (!dbus_message_set_sender (message, "org.foo.bar1"))
06894     _dbus_assert_not_reached ("out of memory");
06895   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
06896   dbus_message_set_reply_serial (message, 5678);
06897   if (!dbus_message_set_sender (message, NULL))
06898     _dbus_assert_not_reached ("out of memory");
06899   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
06900   _dbus_assert (dbus_message_get_serial (message) == 1234);
06901   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
06902   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
06903 
06904   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
06905   dbus_message_set_no_reply (message, TRUE);
06906   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
06907   dbus_message_set_no_reply (message, FALSE);
06908   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
06909 
06910   /* Set/get some header fields */
06911   
06912   if (!dbus_message_set_path (message, "/foo"))
06913     _dbus_assert_not_reached ("out of memory");
06914   _dbus_assert (strcmp (dbus_message_get_path (message),
06915                         "/foo") == 0);
06916 
06917   if (!dbus_message_set_interface (message, "org.Foo"))
06918     _dbus_assert_not_reached ("out of memory");
06919   _dbus_assert (strcmp (dbus_message_get_interface (message),
06920                         "org.Foo") == 0);
06921   
06922   if (!dbus_message_set_member (message, "Bar"))
06923     _dbus_assert_not_reached ("out of memory");
06924   _dbus_assert (strcmp (dbus_message_get_member (message),
06925                         "Bar") == 0);
06926 
06927   /* Set/get them with longer values */
06928   if (!dbus_message_set_path (message, "/foo/bar"))
06929     _dbus_assert_not_reached ("out of memory");
06930   _dbus_assert (strcmp (dbus_message_get_path (message),
06931                         "/foo/bar") == 0);
06932 
06933   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
06934     _dbus_assert_not_reached ("out of memory");
06935   _dbus_assert (strcmp (dbus_message_get_interface (message),
06936                         "org.Foo.Bar") == 0);
06937   
06938   if (!dbus_message_set_member (message, "BarFoo"))
06939     _dbus_assert_not_reached ("out of memory");
06940   _dbus_assert (strcmp (dbus_message_get_member (message),
06941                         "BarFoo") == 0);
06942 
06943   /* Realloc shorter again */
06944   
06945   if (!dbus_message_set_path (message, "/foo"))
06946     _dbus_assert_not_reached ("out of memory");
06947   _dbus_assert (strcmp (dbus_message_get_path (message),
06948                         "/foo") == 0);
06949 
06950   if (!dbus_message_set_interface (message, "org.Foo"))
06951     _dbus_assert_not_reached ("out of memory");
06952   _dbus_assert (strcmp (dbus_message_get_interface (message),
06953                         "org.Foo") == 0);
06954   
06955   if (!dbus_message_set_member (message, "Bar"))
06956     _dbus_assert_not_reached ("out of memory");
06957   _dbus_assert (strcmp (dbus_message_get_member (message),
06958                         "Bar") == 0);
06959   
06960   dbus_message_unref (message);
06961   
06962   /* Test the vararg functions */
06963   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
06964                                           "/org/freedesktop/TestPath",
06965                                           "Foo.TestInterface",
06966                                           "TestMethod");
06967   _dbus_message_set_serial (message, 1);
06968   dbus_message_append_args (message,
06969                             DBUS_TYPE_INT32, -0x12345678,
06970 #ifdef DBUS_HAVE_INT64
06971                             DBUS_TYPE_INT64, DBUS_INT64_CONSTANT (-0x123456789abcd),
06972                             DBUS_TYPE_UINT64, DBUS_UINT64_CONSTANT (0x123456789abcd),
06973 #endif
06974                             DBUS_TYPE_STRING, "Test string",
06975                             DBUS_TYPE_DOUBLE, 3.14159,
06976                             DBUS_TYPE_BOOLEAN, TRUE,
06977                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
06978                             _DBUS_N_ELEMENTS (our_uint32_array),
06979                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
06980                             _DBUS_N_ELEMENTS (our_int32_array),
06981 #ifdef DBUS_HAVE_INT64
06982                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
06983                             _DBUS_N_ELEMENTS (our_uint64_array),
06984                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
06985                             _DBUS_N_ELEMENTS (our_int64_array),
06986 #endif
06987                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
06988                             _DBUS_N_ELEMENTS (our_string_array),
06989                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
06990                             _DBUS_N_ELEMENTS (our_double_array),
06991                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
06992                             _DBUS_N_ELEMENTS (our_byte_array),
06993                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
06994                             _DBUS_N_ELEMENTS (our_boolean_array),
06995                             0);
06996   
06997   dbus_message_append_iter_init (message, &iter);
06998   dbus_message_iter_append_dict (&iter, &child_iter);
06999   dbus_message_iter_append_dict_key (&child_iter, "test");
07000   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07001   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
07002 
07003   i = 0;
07004   sig[i++] = DBUS_TYPE_INT32;
07005 #ifdef DBUS_HAVE_INT64
07006   sig[i++] = DBUS_TYPE_INT64;
07007   sig[i++] = DBUS_TYPE_UINT64;
07008 #endif
07009   sig[i++] = DBUS_TYPE_STRING;
07010   sig[i++] = DBUS_TYPE_DOUBLE;
07011   sig[i++] = DBUS_TYPE_BOOLEAN;
07012   sig[i++] = DBUS_TYPE_ARRAY;
07013   sig[i++] = DBUS_TYPE_UINT32;
07014   sig[i++] = DBUS_TYPE_ARRAY;
07015   sig[i++] = DBUS_TYPE_INT32;
07016 #ifdef DBUS_HAVE_INT64
07017   sig[i++] = DBUS_TYPE_ARRAY;
07018   sig[i++] = DBUS_TYPE_UINT64;
07019   sig[i++] = DBUS_TYPE_ARRAY;
07020   sig[i++] = DBUS_TYPE_INT64;
07021 #endif
07022   sig[i++] = DBUS_TYPE_ARRAY;
07023   sig[i++] = DBUS_TYPE_STRING;
07024   sig[i++] = DBUS_TYPE_ARRAY;
07025   sig[i++] = DBUS_TYPE_DOUBLE;
07026   sig[i++] = DBUS_TYPE_ARRAY;
07027   sig[i++] = DBUS_TYPE_BYTE;
07028   sig[i++] = DBUS_TYPE_ARRAY;
07029   sig[i++] = DBUS_TYPE_BOOLEAN;
07030   sig[i++] = DBUS_TYPE_DICT;
07031   sig[i++] = DBUS_TYPE_UINT32;
07032   sig[i++] = DBUS_TYPE_INVALID;
07033 
07034   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
07035   
07036   _dbus_verbose_bytes_of_string (&message->header, 0,
07037                                  _dbus_string_get_length (&message->header));
07038   _dbus_verbose_bytes_of_string (&message->body, 0,
07039                                  _dbus_string_get_length (&message->body));
07040   
07041   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
07042                  sig, dbus_message_get_signature (message));
07043   
07044   s = dbus_message_get_signature (message);
07045   
07046   _dbus_assert (dbus_message_has_signature (message, sig));
07047   _dbus_assert (strcmp (s, sig) == 0);
07048   
07049   verify_test_message (message);
07050 
07051   copy = dbus_message_copy (message);
07052   
07053   _dbus_assert (message->client_serial == copy->client_serial);
07054   _dbus_assert (message->reply_serial == copy->reply_serial);
07055   _dbus_assert (message->header_padding == copy->header_padding);
07056   
07057   _dbus_assert (_dbus_string_get_length (&message->header) ==
07058                 _dbus_string_get_length (&copy->header));
07059 
07060   _dbus_assert (_dbus_string_get_length (&message->body) ==
07061                 _dbus_string_get_length (&copy->body));
07062 
07063   _dbus_assert (_dbus_string_get_length (&message->signature) ==
07064                 _dbus_string_get_length (&copy->signature));
07065   
07066   verify_test_message (copy);
07067 
07068   name1 = dbus_message_get_interface (message);
07069   name2 = dbus_message_get_interface (copy);
07070 
07071   _dbus_assert (strcmp (name1, name2) == 0);
07072 
07073   name1 = dbus_message_get_member (message);
07074   name2 = dbus_message_get_member (copy);
07075 
07076   _dbus_assert (strcmp (name1, name2) == 0);
07077   
07078   dbus_message_unref (message);  
07079   dbus_message_unref (copy);
07080 
07081   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07082                                           "/org/freedesktop/TestPath",
07083                                           "Foo.TestInterface",
07084                                           "TestMethod");
07085 
07086   _dbus_message_set_serial (message, 1);
07087   dbus_message_set_reply_serial (message, 0x12345678);
07088 
07089   dbus_message_append_iter_init (message, &iter);
07090   dbus_message_iter_append_string (&iter, "Test string");
07091   dbus_message_iter_append_int32 (&iter, -0x12345678);
07092   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
07093   dbus_message_iter_append_double (&iter, 3.14159);
07094 
07095   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
07096   dbus_message_iter_append_double (&child_iter, 1.5);
07097   dbus_message_iter_append_double (&child_iter, 2.5);
07098 
07099   /* dict */
07100   dbus_message_iter_append_dict (&iter, &child_iter);
07101   dbus_message_iter_append_dict_key (&child_iter, "test");
07102   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07103 
07104   /* array of array of int32  (in dict) */
07105   dbus_message_iter_append_dict_key (&child_iter, "array");
07106   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
07107   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07108   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
07109   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
07110   _dbus_warn ("next call expected to fail with wrong array type\n");
07111   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
07112   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07113   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
07114   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
07115   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
07116   
07117   dbus_message_iter_append_byte (&iter, 0xF0);
07118 
07119   dbus_message_iter_append_nil (&iter);
07120 
07121   dbus_message_iter_append_custom (&iter, "MyTypeName",
07122                                    "data", 5);
07123   
07124   message_iter_test (message);
07125   
07126   /* Message loader test */
07127   _dbus_message_lock (message);
07128   loader = _dbus_message_loader_new ();
07129 
07130   /* check ref/unref */
07131   _dbus_message_loader_ref (loader);
07132   _dbus_message_loader_unref (loader);
07133   
07134   /* Write the header data one byte at a time */
07135   data = _dbus_string_get_const_data (&message->header);
07136   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
07137     {
07138       DBusString *buffer;
07139 
07140       _dbus_message_loader_get_buffer (loader, &buffer);
07141       _dbus_string_append_byte (buffer, data[i]);
07142       _dbus_message_loader_return_buffer (loader, buffer, 1);
07143     }
07144 
07145   /* Write the body data one byte at a time */
07146   data = _dbus_string_get_const_data (&message->body);
07147   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
07148     {
07149       DBusString *buffer;
07150 
07151       _dbus_message_loader_get_buffer (loader, &buffer);
07152       _dbus_string_append_byte (buffer, data[i]);
07153       _dbus_message_loader_return_buffer (loader, buffer, 1);
07154     }
07155 
07156   copy = dbus_message_copy (message); /* save for tests below */
07157   dbus_message_unref (message);
07158 
07159   /* Now pop back the message */
07160   if (!_dbus_message_loader_queue_messages (loader))
07161     _dbus_assert_not_reached ("no memory to queue messages");
07162   
07163   if (_dbus_message_loader_get_is_corrupted (loader))
07164     _dbus_assert_not_reached ("message loader corrupted");
07165   
07166   message = _dbus_message_loader_pop_message (loader);
07167   if (!message)
07168     _dbus_assert_not_reached ("received a NULL message");
07169 
07170   if (dbus_message_get_reply_serial (message) != 0x12345678)
07171     _dbus_assert_not_reached ("reply serial fields differ");
07172   
07173   message_iter_test (message);
07174   
07175   dbus_message_unref (message);
07176   _dbus_message_loader_unref (loader);
07177 
07178   message = dbus_message_new_method_return (copy);
07179   if (message == NULL)
07180     _dbus_assert_not_reached ("out of memory\n");
07181   dbus_message_unref (copy);
07182 
07183   if (!dbus_message_append_args (message,
07184                                  DBUS_TYPE_STRING, "hello",
07185                                  DBUS_TYPE_INVALID))
07186     _dbus_assert_not_reached ("no memory");
07187 
07188   if (!dbus_message_has_signature (message, "s"))
07189     _dbus_assert_not_reached ("method return has wrong signature");
07190 
07191   dbus_error_init (&error);
07192   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
07193                               &t, DBUS_TYPE_INVALID))
07194     
07195     {
07196       _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
07197       exit (1);
07198     }
07199   dbus_free (t);
07200   
07201   dbus_message_unref (message);
07202   
07203   /* Now load every message in test_data_dir if we have one */
07204   if (test_data_dir == NULL)
07205     return TRUE;
07206 
07207   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
07208                                                         (DBusForeachMessageFileFunc)
07209                                                         dbus_internal_do_not_use_try_message_file,
07210                                                         NULL);
07211 }
07212 
07213 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Feb 10 18:14:06 2004 for D-BUS by doxygen 1.3.5