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 2.0
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 
01510 DBusMessage *
01511 dbus_message_ref (DBusMessage *message)
01512 {
01513   dbus_int32_t old_refcount;
01514 
01515   _dbus_return_val_if_fail (message != NULL, NULL);
01516   
01517   old_refcount = _dbus_atomic_inc (&message->refcount);
01518   _dbus_assert (old_refcount >= 1);
01519 
01520   return message;
01521 }
01522 
01523 static void
01524 free_size_counter (void *element,
01525                    void *data)
01526 {
01527   DBusCounter *counter = element;
01528   DBusMessage *message = data;
01529   
01530   _dbus_counter_adjust (counter, - message->size_counter_delta);
01531 
01532   _dbus_counter_unref (counter);
01533 }
01534 
01541 void
01542 dbus_message_unref (DBusMessage *message)
01543 {
01544  dbus_int32_t old_refcount;
01545 
01546   _dbus_return_if_fail (message != NULL);
01547   
01548   old_refcount = _dbus_atomic_dec (&message->refcount);
01549   
01550   _dbus_assert (old_refcount >= 0);
01551 
01552   if (old_refcount == 1)
01553     {
01554       /* This calls application callbacks! */
01555       _dbus_data_slot_list_free (&message->slot_list);
01556       
01557       _dbus_list_foreach (&message->size_counters,
01558                           free_size_counter, message);
01559       _dbus_list_clear (&message->size_counters);
01560       
01561       _dbus_string_free (&message->header);
01562       _dbus_string_free (&message->body);
01563       _dbus_string_free (&message->signature);
01564       
01565       dbus_free (message);
01566     }
01567 }
01568 
01580 int
01581 dbus_message_get_type (DBusMessage *message)
01582 {
01583   int type;
01584 
01585   type = _dbus_string_get_byte (&message->header, 1);
01586   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
01587 
01588   return type;
01589 }
01590 
01600 dbus_bool_t
01601 dbus_message_set_path (DBusMessage   *message,
01602                        const char    *object_path)
01603 {
01604   _dbus_return_val_if_fail (message != NULL, FALSE);
01605   _dbus_return_val_if_fail (!message->locked, FALSE);
01606 
01607   return set_string_field (message,
01608                            DBUS_HEADER_FIELD_PATH,
01609                            DBUS_TYPE_OBJECT_PATH,
01610                            object_path);
01611 }
01612 
01621 const char*
01622 dbus_message_get_path (DBusMessage   *message)
01623 {
01624   _dbus_return_val_if_fail (message != NULL, NULL);
01625   
01626   return get_string_field (message, DBUS_HEADER_FIELD_PATH, NULL);
01627 }
01628 
01644 dbus_bool_t
01645 dbus_message_get_path_decomposed (DBusMessage   *message,
01646                                   char        ***path)
01647 {
01648   _dbus_return_val_if_fail (message != NULL, FALSE);
01649   _dbus_return_val_if_fail (path != NULL, FALSE);
01650 
01651   return get_path_field_decomposed (message,
01652                                     DBUS_HEADER_FIELD_PATH,
01653                                     path);
01654 }
01655 
01666 dbus_bool_t
01667 dbus_message_set_interface (DBusMessage  *message,
01668                             const char   *interface)
01669 {
01670   _dbus_return_val_if_fail (message != NULL, FALSE);
01671   _dbus_return_val_if_fail (!message->locked, FALSE);
01672 
01673   return set_string_field (message,
01674                            DBUS_HEADER_FIELD_INTERFACE,
01675                            DBUS_TYPE_STRING,
01676                            interface);
01677 }
01678 
01688 const char*
01689 dbus_message_get_interface (DBusMessage *message)
01690 {
01691   _dbus_return_val_if_fail (message != NULL, NULL);
01692   
01693   return get_string_field (message, DBUS_HEADER_FIELD_INTERFACE, NULL);
01694 }
01695 
01706 dbus_bool_t
01707 dbus_message_set_member (DBusMessage  *message,
01708                        const char   *member)
01709 {
01710   _dbus_return_val_if_fail (message != NULL, FALSE);
01711   _dbus_return_val_if_fail (!message->locked, FALSE);
01712 
01713   return set_string_field (message,
01714                            DBUS_HEADER_FIELD_MEMBER,
01715                            DBUS_TYPE_STRING,
01716                            member);
01717 }
01718 
01727 const char*
01728 dbus_message_get_member (DBusMessage *message)
01729 {
01730   _dbus_return_val_if_fail (message != NULL, NULL);
01731   
01732   return get_string_field (message,
01733                            DBUS_HEADER_FIELD_MEMBER,
01734                            NULL);
01735 }
01736 
01745 dbus_bool_t
01746 dbus_message_set_error_name (DBusMessage  *message,
01747                              const char   *error_name)
01748 {
01749   _dbus_return_val_if_fail (message != NULL, FALSE);
01750   _dbus_return_val_if_fail (!message->locked, FALSE);
01751 
01752   return set_string_field (message,
01753                            DBUS_HEADER_FIELD_ERROR_NAME,
01754                            DBUS_TYPE_STRING,
01755                            error_name);
01756 }
01757 
01764 const char*
01765 dbus_message_get_error_name (DBusMessage *message)
01766 {
01767   _dbus_return_val_if_fail (message != NULL, NULL);
01768   
01769   return get_string_field (message,
01770                            DBUS_HEADER_FIELD_ERROR_NAME,
01771                            NULL);
01772 }
01773 
01781 dbus_bool_t
01782 dbus_message_set_destination (DBusMessage  *message,
01783                               const char   *destination)
01784 {
01785   _dbus_return_val_if_fail (message != NULL, FALSE);
01786   _dbus_return_val_if_fail (!message->locked, FALSE);
01787 
01788   return set_string_field (message,
01789                            DBUS_HEADER_FIELD_SERVICE,
01790                            DBUS_TYPE_STRING,
01791                            destination);
01792 }
01793 
01800 const char*
01801 dbus_message_get_destination (DBusMessage *message)
01802 {
01803   _dbus_return_val_if_fail (message != NULL, NULL);
01804   
01805   return get_string_field (message,
01806                            DBUS_HEADER_FIELD_SERVICE,
01807                            NULL);
01808 }
01809 
01828 dbus_bool_t
01829 dbus_message_append_args (DBusMessage *message,
01830                           int first_arg_type,
01831                           ...)
01832 {
01833   dbus_bool_t retval;
01834   va_list var_args;
01835 
01836   _dbus_return_val_if_fail (message != NULL, FALSE);
01837   
01838   va_start (var_args, first_arg_type);
01839   retval = dbus_message_append_args_valist (message,
01840                                             first_arg_type,
01841                                             var_args);
01842   va_end (var_args);
01843 
01844   return retval;
01845 }
01846 
01860 dbus_bool_t
01861 dbus_message_append_args_valist (DBusMessage *message,
01862                                  int          first_arg_type,
01863                                  va_list      var_args)
01864 {
01865   int type, old_len;
01866   DBusMessageIter iter;
01867 
01868   _dbus_return_val_if_fail (message != NULL, FALSE);
01869   
01870   old_len = _dbus_string_get_length (&message->body);
01871   
01872   type = first_arg_type;
01873 
01874   dbus_message_append_iter_init (message, &iter);
01875   
01876   while (type != DBUS_TYPE_INVALID)
01877     {
01878       switch (type)
01879         {
01880         case DBUS_TYPE_NIL:
01881           if (!dbus_message_iter_append_nil (&iter))
01882             goto errorout;
01883           break;
01884         case DBUS_TYPE_BYTE:
01885           if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, unsigned char)))
01886             goto errorout;
01887           break;
01888         case DBUS_TYPE_BOOLEAN:
01889           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
01890             goto errorout;
01891           break;
01892         case DBUS_TYPE_INT32:
01893           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
01894             goto errorout;
01895           break;
01896         case DBUS_TYPE_UINT32:
01897           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
01898             goto errorout;          
01899           break;
01900 #ifdef DBUS_HAVE_INT64
01901         case DBUS_TYPE_INT64:
01902           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
01903             goto errorout;
01904           break;
01905         case DBUS_TYPE_UINT64:
01906           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
01907             goto errorout;          
01908           break;
01909 #endif /* DBUS_HAVE_INT64 */
01910         case DBUS_TYPE_DOUBLE:
01911           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
01912             goto errorout;
01913           break;
01914         case DBUS_TYPE_STRING:
01915           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
01916             goto errorout;
01917           break;
01918         case DBUS_TYPE_OBJECT_PATH:
01919 
01920           break;
01921         case DBUS_TYPE_CUSTOM:
01922           {
01923             const char *name;
01924             unsigned char *data;
01925             int len;
01926  
01927             name = va_arg (var_args, const char *);
01928             data = va_arg (var_args, unsigned char *);
01929             len = va_arg (var_args, int);
01930 
01931             if (!dbus_message_iter_append_custom (&iter, name, data, len))
01932               goto errorout;
01933             break;
01934           }
01935         case DBUS_TYPE_ARRAY:
01936           {
01937             void *data;
01938             int len, type;
01939  
01940             type = va_arg (var_args, int);
01941             data = va_arg (var_args, void *);
01942             len = va_arg (var_args, int);
01943 
01944             switch (type)
01945               {
01946               case DBUS_TYPE_BYTE:
01947                 if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
01948                   goto errorout;
01949                 break;
01950               case DBUS_TYPE_BOOLEAN:
01951                 if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
01952                   goto errorout;
01953                 break;
01954               case DBUS_TYPE_INT32:
01955                 if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
01956                   goto errorout;
01957                 break;
01958               case DBUS_TYPE_UINT32:
01959                 if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
01960                   goto errorout;
01961                 break;
01962 #ifdef DBUS_HAVE_INT64
01963               case DBUS_TYPE_INT64:
01964                 if (!dbus_message_iter_append_int64_array (&iter, (dbus_int64_t *)data, len))
01965                   goto errorout;
01966                 break;
01967               case DBUS_TYPE_UINT64:
01968                 if (!dbus_message_iter_append_uint64_array (&iter, (dbus_uint64_t *)data, len))
01969                   goto errorout;
01970                 break;
01971 #endif /* DBUS_HAVE_INT64 */
01972               case DBUS_TYPE_DOUBLE:
01973                 if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
01974                   goto errorout;
01975                 break;
01976               case DBUS_TYPE_STRING:
01977                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
01978                   goto errorout;
01979                 break;
01980               case DBUS_TYPE_NIL:
01981               case DBUS_TYPE_ARRAY:
01982               case DBUS_TYPE_CUSTOM:
01983               case DBUS_TYPE_DICT:
01984                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
01985                 goto errorout;
01986               default:
01987                 _dbus_warn ("Unknown field type %d\n", type);
01988                 goto errorout;
01989               }
01990           }
01991           break;
01992           
01993         case DBUS_TYPE_DICT:
01994           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
01995           goto errorout;
01996         default:
01997           _dbus_warn ("Unknown field type %d\n", type);
01998           goto errorout;
01999         }
02000 
02001       type = va_arg (var_args, int);
02002     }
02003 
02004   return TRUE;
02005 
02006  errorout:
02007   return FALSE;
02008 }
02009 
02010 
02023 dbus_bool_t
02024 dbus_message_get_args (DBusMessage     *message,
02025                        DBusError       *error,
02026                        int              first_arg_type,
02027                        ...)
02028 {
02029   dbus_bool_t retval;
02030   va_list var_args;
02031 
02032   _dbus_return_val_if_fail (message != NULL, FALSE);
02033   _dbus_return_val_if_error_is_set (error, FALSE);
02034   
02035   va_start (var_args, first_arg_type);
02036   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
02037   va_end (var_args);
02038 
02039   return retval;
02040 }
02041 
02054 dbus_bool_t
02055 dbus_message_get_args_valist (DBusMessage     *message,
02056                               DBusError       *error,
02057                               int              first_arg_type,
02058                               va_list          var_args)
02059 {
02060   DBusMessageIter iter;
02061 
02062   _dbus_return_val_if_fail (message != NULL, FALSE);
02063   _dbus_return_val_if_error_is_set (error, FALSE);
02064   
02065   dbus_message_iter_init (message, &iter);
02066   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
02067 }
02068 
02081 dbus_bool_t
02082 dbus_message_iter_get_args (DBusMessageIter *iter,
02083                             DBusError       *error,
02084                             int              first_arg_type,
02085                             ...)
02086 {
02087   dbus_bool_t retval;
02088   va_list var_args;
02089 
02090   _dbus_return_val_if_fail (iter != NULL, FALSE);
02091   _dbus_return_val_if_error_is_set (error, FALSE);
02092   
02093   va_start (var_args, first_arg_type);
02094   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
02095   va_end (var_args);
02096 
02097   return retval;
02098 }
02099 
02122 dbus_bool_t
02123 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
02124                                    DBusError       *error,
02125                                    int              first_arg_type,
02126                                    va_list          var_args)
02127 {
02128   int spec_type, msg_type, i;
02129   dbus_bool_t retval;
02130 
02131   _dbus_return_val_if_fail (iter != NULL, FALSE);
02132   _dbus_return_val_if_error_is_set (error, FALSE);
02133 
02134   retval = FALSE;
02135   
02136   spec_type = first_arg_type;
02137   i = 0;
02138   
02139   while (spec_type != 0)
02140     {
02141       msg_type = dbus_message_iter_get_arg_type (iter);      
02142       
02143       if (msg_type != spec_type)
02144         {
02145           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02146                           "Argument %d is specified to be of type \"%s\", but "
02147                           "is actually of type \"%s\"\n", i,
02148                           _dbus_type_to_string (spec_type),
02149                           _dbus_type_to_string (msg_type));
02150 
02151           goto out;
02152         }
02153 
02154       switch (spec_type)
02155         {
02156         case DBUS_TYPE_NIL:
02157           break;
02158         case DBUS_TYPE_BYTE:
02159           {
02160             unsigned char *ptr;
02161 
02162             ptr = va_arg (var_args, unsigned char *);
02163 
02164             *ptr = dbus_message_iter_get_byte (iter);
02165             break;
02166           }
02167         case DBUS_TYPE_BOOLEAN:
02168           {
02169             dbus_bool_t *ptr;
02170 
02171             ptr = va_arg (var_args, dbus_bool_t *);
02172 
02173             *ptr = dbus_message_iter_get_boolean (iter);
02174             break;
02175           }
02176         case DBUS_TYPE_INT32:
02177           {
02178             dbus_int32_t *ptr;
02179 
02180             ptr = va_arg (var_args, dbus_int32_t *);
02181 
02182             *ptr = dbus_message_iter_get_int32 (iter);
02183             break;
02184           }
02185         case DBUS_TYPE_UINT32:
02186           {
02187             dbus_uint32_t *ptr;
02188 
02189             ptr = va_arg (var_args, dbus_uint32_t *);
02190 
02191             *ptr = dbus_message_iter_get_uint32 (iter);
02192             break;
02193           }
02194 #ifdef DBUS_HAVE_INT64
02195         case DBUS_TYPE_INT64:
02196           {
02197             dbus_int64_t *ptr;
02198 
02199             ptr = va_arg (var_args, dbus_int64_t *);
02200 
02201             *ptr = dbus_message_iter_get_int64 (iter);
02202             break;
02203           }
02204         case DBUS_TYPE_UINT64:
02205           {
02206             dbus_uint64_t *ptr;
02207 
02208             ptr = va_arg (var_args, dbus_uint64_t *);
02209 
02210             *ptr = dbus_message_iter_get_uint64 (iter);
02211             break;
02212           }
02213 #endif /* DBUS_HAVE_INT64 */
02214           
02215         case DBUS_TYPE_DOUBLE:
02216           {
02217             double *ptr;
02218 
02219             ptr = va_arg (var_args, double *);
02220 
02221             *ptr = dbus_message_iter_get_double (iter);
02222             break;
02223           }
02224 
02225         case DBUS_TYPE_STRING:
02226           {
02227             char **ptr;
02228 
02229             ptr = va_arg (var_args, char **);
02230 
02231             *ptr = dbus_message_iter_get_string (iter);
02232 
02233             if (!*ptr)
02234               {
02235                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02236                 goto out;
02237               }
02238             
02239             break;
02240           }
02241 
02242         case DBUS_TYPE_CUSTOM:
02243           {
02244             char **name;
02245             unsigned char **data;
02246             int *len;
02247  
02248             name = va_arg (var_args, char **);
02249             data = va_arg (var_args, unsigned char **);
02250             len = va_arg (var_args, int *);
02251 
02252             if (!dbus_message_iter_get_custom (iter, name, data, len))
02253               {
02254                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02255                 goto out;
02256               }
02257           }
02258           break;
02259         case DBUS_TYPE_ARRAY:
02260           {
02261             void **data;
02262             int *len, type;
02263             dbus_bool_t err = FALSE;
02264  
02265             type = va_arg (var_args, int);
02266             data = va_arg (var_args, void *);
02267             len = va_arg (var_args, int *);
02268 
02269             _dbus_return_val_if_fail (data != NULL, FALSE);
02270             _dbus_return_val_if_fail (len != NULL, FALSE);
02271             
02272             if (dbus_message_iter_get_array_type (iter) != type)
02273               {
02274                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02275                                 "Argument %d is specified to be of type \"array of %s\", but "
02276                                 "is actually of type \"array of %s\"\n", i,
02277                                 _dbus_type_to_string (type),
02278                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
02279                 goto out;
02280               }
02281             
02282             switch (type)
02283               {
02284               case DBUS_TYPE_BYTE:
02285                 err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
02286                 break;
02287               case DBUS_TYPE_BOOLEAN:
02288                 err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
02289                 break;
02290               case DBUS_TYPE_INT32:
02291                 err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
02292                 break;
02293               case DBUS_TYPE_UINT32:
02294                 err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
02295                 break;
02296 #ifdef DBUS_HAVE_INT64
02297               case DBUS_TYPE_INT64:
02298                 err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
02299                 break;
02300               case DBUS_TYPE_UINT64:
02301                 err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
02302                 break;
02303 #endif /* DBUS_HAVE_INT64 */
02304               case DBUS_TYPE_DOUBLE:
02305                 err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
02306                 break;
02307               case DBUS_TYPE_STRING:
02308                 err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
02309                 break;
02310               case DBUS_TYPE_NIL:
02311               case DBUS_TYPE_ARRAY:
02312               case DBUS_TYPE_CUSTOM:
02313               case DBUS_TYPE_DICT:
02314                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
02315                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02316                 goto out;
02317               default:
02318                 _dbus_warn ("Unknown field type %d\n", type);
02319                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02320                 goto out;
02321               }
02322             if (err)
02323               {
02324                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02325                 goto out;
02326               }
02327           }
02328           break;
02329         case DBUS_TYPE_DICT:
02330           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
02331           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02332           goto out;
02333         default:          
02334           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02335           _dbus_warn ("Unknown field type %d\n", spec_type);
02336           goto out;
02337         }
02338       
02339       spec_type = va_arg (var_args, int);
02340       if (spec_type != 0 && !dbus_message_iter_next (iter))
02341         {
02342           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02343                           "Message has only %d arguments, but more were expected", i);
02344           goto out;
02345         }
02346 
02347       i++;
02348     }
02349   
02350   retval = TRUE;
02351   
02352  out:
02353   
02354   return retval;
02355 }
02356 
02357 
02365 void
02366 dbus_message_iter_init (DBusMessage     *message,
02367                         DBusMessageIter *iter)
02368 {
02369   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02370 
02371   _dbus_return_if_fail (message != NULL);
02372   _dbus_return_if_fail (iter != NULL);
02373   
02374   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
02375   
02376   real->message = message;
02377   real->parent_iter = NULL;
02378   real->changed_stamp = message->changed_stamp;
02379   
02380   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
02381   real->pos = 0;
02382   real->end = _dbus_string_get_length (&message->body);
02383   
02384   real->container_start = 0;
02385   real->container_length_pos = 0;
02386   real->wrote_dict_key = 0;
02387   real->array_type_pos = 0;
02388 }
02389 
02390 #ifndef DBUS_DISABLE_CHECKS
02391 static dbus_bool_t
02392 dbus_message_iter_check (DBusMessageRealIter *iter)
02393 {
02394   if (iter == NULL)
02395     {
02396       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
02397       return FALSE;
02398     }
02399   
02400   if (iter->changed_stamp != iter->message->changed_stamp)
02401     {
02402       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
02403       return FALSE;
02404     }
02405   
02406   if (iter->pos < 0 || iter->pos > iter->end)
02407     {
02408       _dbus_warn ("dbus iterator check failed: invalid position\n");
02409       return FALSE;
02410     }
02411 
02412   return TRUE;
02413 }
02414 #endif /* DBUS_DISABLE_CHECKS */
02415 
02416 static int
02417 skip_array_type (DBusMessageRealIter *iter, int pos)
02418 {
02419   const char *data;
02420 
02421   do
02422     {
02423       data = _dbus_string_get_const_data_len (&iter->message->body,
02424                                               pos++, 1);
02425     }
02426   while (*data == DBUS_TYPE_ARRAY);
02427   
02428   return pos;
02429 }
02430 
02431 /* FIXME what are these _dbus_type_is_valid() checks for?
02432  * haven't we validated the message?
02433  */
02434 static int
02435 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
02436 {
02437   const char *data;
02438   int pos, len;
02439   
02440   switch (iter->type)
02441     {
02442     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02443       data = _dbus_string_get_const_data_len (&iter->message->body,
02444                                               iter->pos, 1);
02445       if (_dbus_type_is_valid (*data))
02446         *type = *data;
02447       else
02448         *type = DBUS_TYPE_INVALID;
02449       
02450       return skip_array_type (iter, iter->pos);
02451       
02452     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02453       data = _dbus_string_get_const_data_len (&iter->message->body,
02454                                               iter->array_type_pos, 1);
02455       if (_dbus_type_is_valid (*data))
02456         *type = *data;
02457       else
02458         *type = DBUS_TYPE_INVALID;
02459       
02460       return iter->pos;
02461       
02462     case DBUS_MESSAGE_ITER_TYPE_DICT:
02463       /* Get the length of the string */
02464       len = _dbus_demarshal_uint32 (&iter->message->body,
02465                                     iter->message->byte_order,
02466                                     iter->pos, &pos);
02467       pos = pos + len + 1;
02468 
02469       data = _dbus_string_get_const_data_len (&iter->message->body,
02470                                               pos, 1);
02471       if (_dbus_type_is_valid (*data))
02472         *type = *data;
02473       else
02474         *type = DBUS_TYPE_INVALID;
02475 
02476       return skip_array_type (iter, pos);
02477       
02478     default:
02479       _dbus_assert_not_reached ("Invalid iter type");
02480       break;
02481     }
02482   *type = DBUS_TYPE_INVALID;
02483   return iter->pos;
02484 }
02485 
02486 
02494 dbus_bool_t
02495 dbus_message_iter_has_next (DBusMessageIter *iter)
02496 {
02497   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02498   int end_pos;
02499   int type, pos;
02500 
02501   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02502 
02503   if (real->pos >= real->end)
02504     return FALSE;
02505   
02506   pos = dbus_message_iter_get_data_start (real, &type);
02507   
02508   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02509                                       real->message->byte_order,
02510                                       type, pos, &end_pos))
02511     return FALSE;
02512   
02513   if (end_pos >= real->end)
02514     return FALSE;
02515 
02516   return TRUE;  
02517 }
02518 
02525 dbus_bool_t
02526 dbus_message_iter_next (DBusMessageIter *iter)
02527 {
02528   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02529   int end_pos;
02530   int type, pos;
02531 
02532   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02533 
02534   pos = dbus_message_iter_get_data_start (real, &type);
02535   
02536   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02537                                       real->message->byte_order,
02538                                       type, pos, &end_pos))
02539     return FALSE;
02540 
02541   if (end_pos >= real->end)
02542     return FALSE;
02543 
02544   real->pos = end_pos;
02545 
02546   return TRUE;
02547 }
02548 
02556 int
02557 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02558 {
02559   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02560   int type, pos;
02561 
02562   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02563 
02564   if (real->pos >= real->end)
02565     {
02566       _dbus_verbose ("  iterator at or beyond end of message\n");
02567       return DBUS_TYPE_INVALID;
02568     }
02569 
02570   pos = dbus_message_iter_get_data_start (real, &type);
02571   
02572   return type;
02573 }
02574 
02575 /* FIXME why do we validate the typecode in here, hasn't the message
02576  * already been verified?
02577  */
02578 static int
02579 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
02580 {
02581   const char *data;
02582   int _array_type_pos;
02583   int len, pos;
02584   
02585   switch (iter->type)
02586     {
02587     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02588       _array_type_pos = iter->pos + 1;
02589       break;
02590     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02591       _array_type_pos = iter->array_type_pos + 1;
02592       break;
02593     case DBUS_MESSAGE_ITER_TYPE_DICT:
02594       /* Get the length of the string */
02595       len = _dbus_demarshal_uint32 (&iter->message->body,
02596                                     iter->message->byte_order,
02597                                     iter->pos, &pos);
02598       pos = pos + len + 1;
02599       data = _dbus_string_get_const_data_len (&iter->message->body,
02600                                               pos + 1, 1);
02601       _array_type_pos = pos + 1;
02602       break;
02603     default:
02604       _dbus_assert_not_reached ("wrong iter type");
02605       return DBUS_TYPE_INVALID;
02606     }
02607 
02608   if (array_type_pos != NULL)
02609     *array_type_pos = _array_type_pos;
02610   
02611   data = _dbus_string_get_const_data_len (&iter->message->body,
02612                                           _array_type_pos, 1);
02613   if (_dbus_type_is_valid (*data))
02614     return  *data;
02615   
02616   return DBUS_TYPE_INVALID;
02617 }
02618 
02619 
02629 int
02630 dbus_message_iter_get_array_type (DBusMessageIter *iter)
02631 {
02632   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02633   int type, pos;
02634 
02635   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02636 
02637   if (real->pos >= real->end)
02638     return DBUS_TYPE_INVALID;
02639 
02640   pos = dbus_message_iter_get_data_start (real, &type);
02641 
02642   _dbus_assert (type == DBUS_TYPE_ARRAY);
02643 
02644   return iter_get_array_type (real, NULL);
02645 }
02646 
02647 
02657 char *
02658 dbus_message_iter_get_string (DBusMessageIter *iter)
02659 {
02660   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02661   int type, pos;
02662 
02663   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02664 
02665   pos = dbus_message_iter_get_data_start (real, &type);
02666   
02667   _dbus_assert (type == DBUS_TYPE_STRING);
02668 
02669   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02670                                  pos, NULL);
02671 }
02672 
02673 #if 0
02674 
02686 char *
02687 dbus_message_iter_get_object_path (DBusMessageIter  *iter)
02688 {
02689   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02690   int type, pos;
02691 
02692   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02693 
02694   pos = dbus_message_iter_get_data_start (real, &type);
02695   
02696   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
02697 
02698   return _dbus_demarshal_object_path (&real->message->body, real->message->byte_order,
02699                                       pos, NULL);
02700 }
02701 #endif
02702 
02716 dbus_bool_t
02717 dbus_message_iter_get_custom (DBusMessageIter   *iter,
02718                               char             **name,
02719                               unsigned char    **value,
02720                               int               *len)
02721 {
02722   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02723   int type, pos;
02724   char *_name;
02725 
02726   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02727 
02728   pos = dbus_message_iter_get_data_start (real, &type);
02729   
02730   _dbus_assert (type == DBUS_TYPE_CUSTOM);
02731   
02732   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02733                                   pos, &pos);
02734 
02735   if (_name == NULL)
02736     return FALSE;
02737   
02738   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
02739                                    pos, NULL, value, len))
02740     {
02741       dbus_free (_name);
02742       return FALSE;
02743     }
02744 
02745   *name = _name;
02746   
02747   return TRUE;
02748 }
02749 
02759 unsigned char
02760 dbus_message_iter_get_byte (DBusMessageIter *iter)
02761 {
02762   unsigned char value;
02763   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02764   int type, pos;
02765 
02766   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02767 
02768   pos = dbus_message_iter_get_data_start (real, &type);
02769   
02770   _dbus_assert (type == DBUS_TYPE_BYTE);
02771 
02772   value = _dbus_string_get_byte (&real->message->body, pos);
02773   
02774   return value;
02775 }
02776 
02777 
02787 dbus_bool_t
02788 dbus_message_iter_get_boolean (DBusMessageIter *iter)
02789 {
02790   unsigned char value;
02791   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02792   int type, pos;
02793 
02794   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02795 
02796   pos = dbus_message_iter_get_data_start (real, &type);
02797   
02798   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
02799 
02800   value = _dbus_string_get_byte (&real->message->body, pos);
02801   
02802   return value;
02803 }
02804 
02814 dbus_int32_t
02815 dbus_message_iter_get_int32 (DBusMessageIter *iter)
02816 {
02817   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02818   int type, pos;
02819 
02820   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02821 
02822   pos = dbus_message_iter_get_data_start (real, &type);
02823   
02824   _dbus_assert (type == DBUS_TYPE_INT32);
02825   
02826   return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
02827                                 pos, NULL);
02828 }
02829 
02839 dbus_uint32_t
02840 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
02841 {
02842   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02843   int type, pos;
02844 
02845   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02846 
02847   pos = dbus_message_iter_get_data_start (real, &type);
02848   
02849   _dbus_assert (type == DBUS_TYPE_UINT32);
02850   
02851   return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
02852                                  pos, NULL);
02853 }
02854 
02855 #ifdef DBUS_HAVE_INT64
02856 
02868 dbus_int64_t
02869 dbus_message_iter_get_int64 (DBusMessageIter *iter)
02870 {
02871   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02872   int type, pos;
02873 
02874   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02875 
02876   pos = dbus_message_iter_get_data_start (real, &type);
02877   
02878   _dbus_assert (type == DBUS_TYPE_INT64);
02879   
02880   return _dbus_demarshal_int64 (&real->message->body, real->message->byte_order,
02881                                 pos, NULL);
02882 }
02883 
02895 dbus_uint64_t
02896 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
02897 {
02898   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02899   int type, pos;
02900 
02901   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
02902 
02903   pos = dbus_message_iter_get_data_start (real, &type);
02904   
02905   _dbus_assert (type == DBUS_TYPE_UINT64);
02906   
02907   return _dbus_demarshal_uint64 (&real->message->body, real->message->byte_order,
02908                                  pos, NULL);
02909 }
02910 
02911 #endif /* DBUS_HAVE_INT64 */
02912 
02922 double
02923 dbus_message_iter_get_double (DBusMessageIter *iter)
02924 {
02925   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02926   int type, pos;
02927 
02928   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0.0);
02929 
02930   pos = dbus_message_iter_get_data_start (real, &type);
02931   
02932   _dbus_assert (type == DBUS_TYPE_DOUBLE);
02933   
02934   return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
02935                                  pos, NULL);
02936 }
02937 
02950 void
02951 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
02952                                        DBusMessageIter *array_iter,
02953                                        int             *array_type)
02954 {
02955   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02956   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
02957   int type, pos, len_pos, len, array_type_pos;
02958   int _array_type;
02959 
02960   _dbus_return_if_fail (dbus_message_iter_check (real));
02961 
02962   pos = dbus_message_iter_get_data_start (real, &type);
02963   
02964   _dbus_assert (type == DBUS_TYPE_ARRAY);
02965 
02966   _array_type = iter_get_array_type (real, &array_type_pos);
02967   
02968   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
02969   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
02970                                 pos, &pos);
02971   
02972   array_real->parent_iter = real;
02973   array_real->message = real->message;
02974   array_real->changed_stamp = real->message->changed_stamp;
02975   
02976   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
02977   array_real->pos = pos;
02978   array_real->end = pos + len;
02979   
02980   array_real->container_start = pos;
02981   array_real->container_length_pos = len_pos;
02982   array_real->wrote_dict_key = 0;
02983   array_real->array_type_pos = array_type_pos;
02984   array_real->array_type_done = TRUE;
02985   
02986   if (array_type != NULL)
02987     *array_type = _array_type;
02988 }
02989 
02990 
02999 void
03000 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
03001                                       DBusMessageIter *dict_iter)
03002 {
03003   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03004   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
03005   int type, pos, len_pos, len;
03006 
03007   _dbus_return_if_fail (dbus_message_iter_check (real));
03008 
03009   pos = dbus_message_iter_get_data_start (real, &type);
03010   
03011   _dbus_assert (type == DBUS_TYPE_DICT);
03012 
03013   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
03014   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
03015                                 pos, &pos);
03016   
03017   dict_real->parent_iter = real;
03018   dict_real->message = real->message;
03019   dict_real->changed_stamp = real->message->changed_stamp;
03020   
03021   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
03022   dict_real->pos = pos;
03023   dict_real->end = pos + len;
03024   
03025   dict_real->container_start = pos;
03026   dict_real->container_length_pos = len_pos;
03027   dict_real->wrote_dict_key = 0;
03028 }
03029 
03040 dbus_bool_t
03041 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
03042                                   unsigned char   **value,
03043                                   int              *len)
03044 {
03045   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03046   int type, pos;
03047 
03048   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03049 
03050   pos = dbus_message_iter_get_data_start (real, &type);
03051   
03052   _dbus_assert (type == DBUS_TYPE_ARRAY);
03053 
03054   type = iter_get_array_type (real, NULL);
03055 
03056   _dbus_assert (type == DBUS_TYPE_BYTE);
03057 
03058   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
03059                                    pos, NULL, value, len))
03060     return FALSE;
03061   else
03062     return TRUE;
03063 }
03064 
03075 dbus_bool_t
03076 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
03077                                      unsigned char    **value,
03078                                      int               *len)
03079 {
03080   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03081   int type, pos;
03082 
03083   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03084 
03085   pos = dbus_message_iter_get_data_start (real, &type);
03086   
03087   _dbus_assert (type == DBUS_TYPE_ARRAY);
03088 
03089   type = iter_get_array_type (real, NULL);
03090 
03091   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
03092 
03093   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
03094                                    pos, NULL, value, len))
03095     return FALSE;
03096   else
03097     return TRUE;
03098 }
03099 
03110 dbus_bool_t
03111 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
03112                                     dbus_int32_t   **value,
03113                                     int             *len)
03114 {
03115   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03116   int type, pos;
03117 
03118   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03119 
03120   pos = dbus_message_iter_get_data_start (real, &type);
03121   
03122   _dbus_assert (type == DBUS_TYPE_ARRAY);
03123 
03124   type = iter_get_array_type (real, NULL);
03125   
03126   _dbus_assert (type == DBUS_TYPE_INT32);
03127 
03128   if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
03129                                     pos, NULL, value, len))
03130     return FALSE;
03131   else
03132     return TRUE;
03133 }
03134 
03145 dbus_bool_t
03146 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
03147                                      dbus_uint32_t  **value,
03148                                      int             *len)
03149 {
03150   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03151   int type, pos;
03152 
03153   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03154 
03155   pos = dbus_message_iter_get_data_start (real, &type);
03156   
03157   _dbus_assert (type == DBUS_TYPE_ARRAY);
03158 
03159   type = iter_get_array_type (real, NULL);
03160   _dbus_assert (type == DBUS_TYPE_UINT32);
03161 
03162   if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
03163                                     pos, NULL, value, len))
03164     return FALSE;
03165   else
03166     return TRUE;
03167 }
03168 
03169 #ifdef DBUS_HAVE_INT64
03170 
03183 dbus_bool_t
03184 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
03185                                     dbus_int64_t   **value,
03186                                     int             *len)
03187 {
03188   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03189   int type, pos;
03190 
03191   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03192 
03193   pos = dbus_message_iter_get_data_start (real, &type);
03194   
03195   _dbus_assert (type == DBUS_TYPE_ARRAY);
03196 
03197   type = iter_get_array_type (real, NULL);
03198   
03199   _dbus_assert (type == DBUS_TYPE_INT64);
03200 
03201   if (!_dbus_demarshal_int64_array (&real->message->body, real->message->byte_order,
03202                                     pos, NULL, value, len))
03203     return FALSE;
03204   else
03205     return TRUE;
03206 }
03207 
03220 dbus_bool_t
03221 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
03222                                      dbus_uint64_t  **value,
03223                                      int             *len)
03224 {
03225   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03226   int type, pos;
03227 
03228   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03229 
03230   pos = dbus_message_iter_get_data_start (real, &type);
03231   
03232   _dbus_assert (type == DBUS_TYPE_ARRAY);
03233 
03234   type = iter_get_array_type (real, NULL);
03235   _dbus_assert (type == DBUS_TYPE_UINT64);
03236 
03237   if (!_dbus_demarshal_uint64_array (&real->message->body, real->message->byte_order,
03238                                     pos, NULL, value, len))
03239     return FALSE;
03240   else
03241     return TRUE;
03242 }
03243 
03244 #endif /* DBUS_HAVE_INT64 */
03245 
03256 dbus_bool_t
03257 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
03258                                      double         **value,
03259                                      int             *len)
03260 {
03261   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03262   int type, pos;
03263 
03264   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03265 
03266   pos = dbus_message_iter_get_data_start (real, &type);
03267   
03268   _dbus_assert (type == DBUS_TYPE_ARRAY);
03269 
03270   type = iter_get_array_type (real, NULL);
03271   _dbus_assert (type == DBUS_TYPE_DOUBLE);
03272 
03273   if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
03274                                      pos, NULL, value, len))
03275     return FALSE;
03276   else
03277     return TRUE;
03278 }
03279 
03295 dbus_bool_t
03296 dbus_message_iter_get_string_array (DBusMessageIter *iter,
03297                                     char          ***value,
03298                                     int             *len)
03299 {
03300   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03301   int type, pos;
03302 
03303   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03304 
03305   pos = dbus_message_iter_get_data_start (real, &type);
03306   
03307   _dbus_assert (type == DBUS_TYPE_ARRAY);
03308 
03309   type = iter_get_array_type (real, NULL);
03310   _dbus_assert (type == DBUS_TYPE_STRING);
03311 
03312   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
03313                                      pos, NULL, value, len))
03314     return FALSE;
03315   else
03316     return TRUE;
03317 }
03318 
03319 #if 0
03320 
03338 dbus_bool_t
03339 dbus_message_iter_get_object_path_array (DBusMessageIter *iter,
03340                                          char          ***value,
03341                                          int             *len)
03342 {
03343   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03344   int type, pos;
03345 
03346   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03347 
03348   pos = dbus_message_iter_get_data_start (real, &type);
03349   
03350   _dbus_assert (type == DBUS_TYPE_ARRAY);
03351 
03352   type = iter_get_array_type (real, NULL);
03353   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
03354 
03355   if (!_dbus_demarshal_object_path_array (&real->message->body, real->message->byte_order,
03356                                           pos, NULL, value, len))
03357     return FALSE;
03358   else
03359     return TRUE;
03360 }
03361 #endif
03362 
03372 char *
03373 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
03374 {
03375   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03376 
03377   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
03378 
03379   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03380 
03381   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
03382                                  real->pos, NULL);
03383 }
03384 
03393 void
03394 dbus_message_append_iter_init (DBusMessage     *message,
03395                                DBusMessageIter *iter)
03396 {
03397   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03398 
03399   _dbus_return_if_fail (message != NULL);
03400   _dbus_return_if_fail (iter != NULL);
03401   
03402   real->message = message;
03403   real->parent_iter = NULL;
03404   real->changed_stamp = message->changed_stamp;
03405   
03406   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
03407   real->end = _dbus_string_get_length (&real->message->body);
03408   real->pos = real->end;
03409   
03410   real->container_length_pos = 0;
03411   real->wrote_dict_key = 0;
03412 }
03413 
03414 #ifndef DBUS_DISABLE_CHECKS
03415 static dbus_bool_t
03416 dbus_message_iter_append_check (DBusMessageRealIter *iter)
03417 {
03418   if (iter == NULL)
03419     {
03420       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
03421       return FALSE;
03422     }
03423   
03424   if (iter->message->locked)
03425     {
03426       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
03427       return FALSE;
03428     }
03429       
03430   if (iter->changed_stamp != iter->message->changed_stamp)
03431     {
03432       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
03433       return FALSE;
03434     }
03435   
03436   if (iter->pos != iter->end)
03437     {
03438       _dbus_warn ("dbus iterator check failed: can only append at end of message");
03439       return FALSE;
03440     }
03441   
03442   if (iter->pos != _dbus_string_get_length (&iter->message->body))
03443     {
03444       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
03445       return FALSE;
03446     }
03447 
03448   return TRUE;
03449 }
03450 #endif /* DBUS_DISABLE_CHECKS */
03451 
03452 static dbus_bool_t
03453 dbus_message_iter_append_type (DBusMessageRealIter *iter,
03454                                int                  type)
03455 {
03456   const char *data;
03457   switch (iter->type)
03458     {
03459     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
03460       if (!_dbus_string_append_byte (&iter->message->signature, type))
03461         return FALSE;
03462       
03463       if (!_dbus_string_append_byte (&iter->message->body, type))
03464         {
03465           _dbus_string_shorten (&iter->message->signature, 1);
03466           return FALSE;
03467         }
03468       break;
03469       
03470     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
03471       data = _dbus_string_get_const_data_len (&iter->message->body,
03472                                               iter->array_type_pos, 1);
03473       if (type != *data)
03474         {
03475           _dbus_warn ("Appended element of wrong type for array\n");
03476           return FALSE;
03477         }
03478       break;
03479       
03480     case DBUS_MESSAGE_ITER_TYPE_DICT:
03481       if (!iter->wrote_dict_key)
03482         {
03483           _dbus_warn ("Appending dict data before key name\n");
03484           return FALSE;
03485         }
03486       
03487       if (!_dbus_string_append_byte (&iter->message->body, type))
03488         return FALSE;
03489       
03490       break;
03491       
03492     default:
03493       _dbus_assert_not_reached ("Invalid iter type");
03494       break;
03495     }
03496   
03497   return TRUE;
03498 }
03499 
03500 static void
03501 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
03502 {
03503   iter->changed_stamp = iter->message->changed_stamp;
03504   
03505   /* Set new end of iter */
03506   iter->end = _dbus_string_get_length (&iter->message->body);
03507   iter->pos = iter->end;
03508 
03509   /* Set container length */
03510   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
03511       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
03512     _dbus_marshal_set_uint32 (&iter->message->body,
03513                               iter->message->byte_order,
03514                               iter->container_length_pos,
03515                               iter->end - iter->container_start);
03516   
03517   if (iter->parent_iter)
03518     dbus_message_iter_update_after_change (iter->parent_iter);
03519 }
03520 
03521 static void
03522 dbus_message_iter_append_done (DBusMessageRealIter *iter)
03523 {
03524   iter->message->changed_stamp++;
03525   dbus_message_iter_update_after_change (iter);
03526   iter->wrote_dict_key = FALSE;
03527 }
03528 
03535 dbus_bool_t
03536 dbus_message_iter_append_nil (DBusMessageIter *iter)
03537 {
03538   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03539 
03540   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03541 
03542   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
03543     return FALSE;
03544   
03545   dbus_message_iter_append_done (real);
03546   
03547   return TRUE;
03548 }
03549 
03557 dbus_bool_t
03558 dbus_message_iter_append_boolean (DBusMessageIter *iter,
03559                                   dbus_bool_t     value)
03560 {
03561   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03562 
03563   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03564 
03565   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
03566     return FALSE;
03567   
03568   if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
03569     {
03570       _dbus_string_set_length (&real->message->body, real->pos);
03571       return FALSE;
03572     }
03573 
03574   dbus_message_iter_append_done (real);
03575   
03576   return TRUE;
03577 }
03578 
03586 dbus_bool_t
03587 dbus_message_iter_append_byte (DBusMessageIter *iter,
03588                                unsigned char    value)
03589 {
03590   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03591 
03592   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03593 
03594   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
03595     return FALSE;
03596   
03597   if (!_dbus_string_append_byte (&real->message->body, value))
03598     {
03599       _dbus_string_set_length (&real->message->body, real->pos);
03600       return FALSE;
03601     }
03602 
03603   dbus_message_iter_append_done (real);
03604   
03605   return TRUE;
03606 }
03607 
03608 
03616 dbus_bool_t
03617 dbus_message_iter_append_int32   (DBusMessageIter *iter,
03618                                   dbus_int32_t  value)
03619 {
03620   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03621 
03622   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03623 
03624   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
03625     return FALSE;
03626   
03627   if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
03628     {
03629       _dbus_string_set_length (&real->message->body, real->pos);
03630       return FALSE;
03631     }
03632 
03633   dbus_message_iter_append_done (real);
03634   
03635   return TRUE;
03636 }
03637 
03645 dbus_bool_t
03646 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
03647                                  dbus_uint32_t    value)
03648 {
03649   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03650 
03651   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03652 
03653   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
03654     return FALSE;
03655   
03656   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
03657     {
03658       _dbus_string_set_length (&real->message->body, real->pos);
03659       return FALSE;
03660     }
03661 
03662   dbus_message_iter_append_done (real);
03663   
03664   return TRUE;
03665 }
03666 
03667 #ifdef DBUS_HAVE_INT64
03668 
03678 dbus_bool_t
03679 dbus_message_iter_append_int64   (DBusMessageIter *iter,
03680                                   dbus_int64_t  value)
03681 {
03682   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03683 
03684   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03685 
03686   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT64))
03687     return FALSE;
03688   
03689   if (!_dbus_marshal_int64 (&real->message->body, real->message->byte_order, value))
03690     {
03691       _dbus_string_set_length (&real->message->body, real->pos);
03692       return FALSE;
03693     }
03694 
03695   dbus_message_iter_append_done (real);
03696   
03697   return TRUE;
03698 }
03699 
03709 dbus_bool_t
03710 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
03711                                  dbus_uint64_t    value)
03712 {
03713   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03714 
03715   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03716 
03717   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT64))
03718     return FALSE;
03719   
03720   if (!_dbus_marshal_uint64 (&real->message->body, real->message->byte_order, value))
03721     {
03722       _dbus_string_set_length (&real->message->body, real->pos);
03723       return FALSE;
03724     }
03725 
03726   dbus_message_iter_append_done (real);
03727   
03728   return TRUE;
03729 }
03730 
03731 #endif /* DBUS_HAVE_INT64 */
03732 
03740 dbus_bool_t
03741 dbus_message_iter_append_double (DBusMessageIter *iter,
03742                                  double           value)
03743 {
03744   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03745 
03746   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03747 
03748   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
03749     return FALSE;
03750   
03751   if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
03752     {
03753       _dbus_string_set_length (&real->message->body, real->pos);
03754       return FALSE;
03755     }
03756 
03757   dbus_message_iter_append_done (real);
03758   
03759   return TRUE;
03760 }
03761 
03771 dbus_bool_t
03772 dbus_message_iter_append_string (DBusMessageIter *iter,
03773                                  const char      *value)
03774 {
03775   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03776 
03777   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03778   
03779   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
03780     return FALSE;
03781   
03782   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03783     {
03784       _dbus_string_set_length (&real->message->body, real->pos);
03785       return FALSE;
03786     }
03787 
03788   dbus_message_iter_append_done (real);
03789   
03790   return TRUE;
03791 }
03792 
03805 dbus_bool_t
03806 dbus_message_iter_append_custom (DBusMessageIter      *iter,
03807                                  const char           *name,
03808                                  const unsigned char  *data,
03809                                  int                   len)
03810 {
03811   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03812 
03813   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03814 
03815   if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
03816     return FALSE;
03817   
03818    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
03819     {
03820       _dbus_string_set_length (&real->message->body, real->pos);
03821       return FALSE;
03822     }
03823    
03824   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
03825     {
03826       _dbus_string_set_length (&real->message->body, real->pos);
03827       return FALSE;
03828     }
03829 
03830   dbus_message_iter_append_done (real);
03831   
03832   return TRUE;
03833 }
03834 
03835 
03844 dbus_bool_t
03845 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
03846                                    const char      *value)
03847 {
03848   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03849 
03850   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03851   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03852   
03853   if (real->wrote_dict_key)
03854     {
03855       _dbus_warn ("Appending multiple dict key names\n");
03856       return FALSE;
03857     }
03858   
03859   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03860     {
03861       return FALSE;
03862     }
03863 
03864   dbus_message_iter_append_done (real);
03865   real->wrote_dict_key = TRUE;
03866   
03867   return TRUE;
03868 }
03869 
03870 static dbus_bool_t
03871 array_iter_type_mark_done (DBusMessageRealIter *iter)
03872 {
03873   int len_pos;
03874   
03875   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
03876     array_iter_type_mark_done (iter->parent_iter);
03877   else
03878     return TRUE;
03879 
03880   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
03881                                sizeof (dbus_uint32_t));
03882 
03883   /* Empty length for now, backfill later */
03884   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
03885     {
03886       _dbus_string_set_length (&iter->message->body, iter->pos);
03887       return FALSE;
03888     }
03889 
03890   iter->container_start = _dbus_string_get_length (&iter->message->body);
03891   iter->container_length_pos = len_pos;
03892   iter->array_type_done = TRUE;
03893 
03894   return TRUE;
03895 }
03896 
03897 static dbus_bool_t
03898 append_array_type (DBusMessageRealIter *real,
03899                    int                  element_type,
03900                    dbus_bool_t         *array_type_done,
03901                    int                 *array_type_pos)
03902 {
03903   int existing_element_type;
03904   
03905   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
03906     return FALSE;
03907   
03908   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
03909       real->array_type_done)
03910     {
03911       existing_element_type = iter_get_array_type (real, array_type_pos);
03912       if (existing_element_type != element_type)
03913         {
03914           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
03915                       _dbus_type_to_string (element_type),
03916                       _dbus_type_to_string (existing_element_type));
03917           _dbus_string_set_length (&real->message->body, real->pos);
03918           return FALSE;
03919         }
03920       if (array_type_done != NULL)
03921           *array_type_done = TRUE;
03922     }
03923   else
03924     {
03925       if (array_type_pos != NULL)
03926         *array_type_pos = _dbus_string_get_length (&real->message->body);
03927 
03928 
03929       if (!_dbus_string_append_byte (&real->message->signature, element_type))
03930         {
03931           _dbus_string_set_length (&real->message->body, real->pos);
03932           return FALSE;
03933         }
03934       
03935       /* Append element type */
03936       if (!_dbus_string_append_byte (&real->message->body, element_type))
03937         {
03938           _dbus_string_shorten (&real->message->signature, 1);
03939           _dbus_string_set_length (&real->message->body, real->pos);
03940           return FALSE;
03941         }
03942 
03943       if (array_type_done != NULL)
03944         *array_type_done = element_type != DBUS_TYPE_ARRAY;
03945       
03946       if (element_type != DBUS_TYPE_ARRAY &&
03947           !array_iter_type_mark_done (real))
03948         {
03949           _dbus_string_shorten (&real->message->signature, 1);
03950           return FALSE;
03951         }        
03952     }
03953 
03954   return TRUE;
03955 }
03956 
03966 dbus_bool_t
03967 dbus_message_iter_append_array (DBusMessageIter      *iter,
03968                                 DBusMessageIter      *array_iter,
03969                                 int                   element_type)
03970 {
03971   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03972   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
03973   int len_pos;
03974   int array_type_pos;
03975   dbus_bool_t array_type_done;
03976 
03977   if (element_type == DBUS_TYPE_NIL)
03978     {
03979       _dbus_warn ("Can't create NIL arrays\n");
03980       return FALSE;
03981     }
03982   
03983   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03984 
03985   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
03986     return FALSE;
03987 
03988   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
03989 
03990   if (array_type_done)
03991     {
03992       /* Empty length for now, backfill later */
03993       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
03994         {
03995           _dbus_string_set_length (&real->message->body, real->pos);
03996           return FALSE;
03997         }
03998     }
03999   
04000   array_real->parent_iter = real;
04001   array_real->message = real->message;
04002   array_real->changed_stamp = real->message->changed_stamp;
04003   
04004   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
04005   array_real->pos = _dbus_string_get_length (&real->message->body);
04006   array_real->end = array_real->end;
04007   
04008   array_real->container_start = array_real->pos;
04009   array_real->container_length_pos = len_pos;
04010   array_real->wrote_dict_key = 0;
04011   array_real->array_type_done = array_type_done;
04012   array_real->array_type_pos = array_type_pos;
04013 
04014   dbus_message_iter_append_done (array_real);
04015   
04016   return TRUE;
04017 }
04018 
04027 dbus_bool_t
04028 dbus_message_iter_append_dict (DBusMessageIter      *iter,
04029                                DBusMessageIter      *dict_iter)
04030 {
04031   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04032   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
04033   int len_pos;
04034 
04035   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04036   
04037   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
04038     return FALSE;  
04039   
04040   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
04041 
04042   /* Empty length for now, backfill later */
04043   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
04044     {
04045       _dbus_string_set_length (&real->message->body, real->pos);
04046       return FALSE;
04047     }
04048   
04049   dict_real->parent_iter = real;
04050   dict_real->message = real->message;
04051   dict_real->changed_stamp = real->message->changed_stamp;
04052   
04053   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
04054   dict_real->pos = _dbus_string_get_length (&real->message->body);
04055   dict_real->end = dict_real->end;
04056   
04057   dict_real->container_start = dict_real->pos;
04058   dict_real->container_length_pos = len_pos;
04059   dict_real->wrote_dict_key = 0;
04060 
04061   dbus_message_iter_append_done (dict_real);
04062   
04063   real->wrote_dict_key = FALSE;
04064   
04065   return TRUE;
04066 }
04067 
04068 
04077 dbus_bool_t
04078 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
04079                                         unsigned const char *value,
04080                                         int                  len)
04081 {
04082   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04083 
04084   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04085 
04086   if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
04087     return FALSE;
04088   
04089   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
04090     {
04091       _dbus_string_set_length (&real->message->body, real->pos);
04092       return FALSE;
04093     }
04094 
04095   dbus_message_iter_append_done (real);
04096   
04097   return TRUE;
04098 }
04099 
04108 dbus_bool_t
04109 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
04110                                       const dbus_int32_t *value,
04111                                       int                 len)
04112 {
04113   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04114 
04115   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04116 
04117   if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
04118     return FALSE;
04119   
04120   if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
04121     {
04122       _dbus_string_set_length (&real->message->body, real->pos);
04123       return FALSE;
04124     }
04125 
04126   dbus_message_iter_append_done (real);
04127   
04128   return TRUE;
04129 }
04130 
04139 dbus_bool_t
04140 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
04141                                        const dbus_uint32_t *value,
04142                                        int                  len)
04143 {
04144   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04145 
04146   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04147 
04148   if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
04149     return FALSE;
04150   
04151   if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
04152     {
04153       _dbus_string_set_length (&real->message->body, real->pos);
04154       return FALSE;
04155     }
04156 
04157   dbus_message_iter_append_done (real);
04158   
04159   return TRUE;
04160 }
04161 
04162 #ifdef DBUS_HAVE_INT64
04163 
04174 dbus_bool_t
04175 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
04176                                       const dbus_int64_t *value,
04177                                       int                 len)
04178 {
04179   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04180 
04181   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04182 
04183   if (!append_array_type (real, DBUS_TYPE_INT64, NULL, NULL))
04184     return FALSE;
04185   
04186   if (!_dbus_marshal_int64_array (&real->message->body, real->message->byte_order, value, len))
04187     {
04188       _dbus_string_set_length (&real->message->body, real->pos);
04189       return FALSE;
04190     }
04191 
04192   dbus_message_iter_append_done (real);
04193   
04194   return TRUE;
04195 }
04196 
04207 dbus_bool_t
04208 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
04209                                        const dbus_uint64_t *value,
04210                                        int                  len)
04211 {
04212   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04213 
04214   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04215 
04216   if (!append_array_type (real, DBUS_TYPE_UINT64, NULL, NULL))
04217     return FALSE;
04218   
04219   if (!_dbus_marshal_uint64_array (&real->message->body, real->message->byte_order, value, len))
04220     {
04221       _dbus_string_set_length (&real->message->body, real->pos);
04222       return FALSE;
04223     }
04224 
04225   dbus_message_iter_append_done (real);
04226   
04227   return TRUE;
04228 }
04229 #endif /* DBUS_HAVE_INT64 */
04230 
04239 dbus_bool_t
04240 dbus_message_iter_append_double_array (DBusMessageIter *iter,
04241                                        const double    *value,
04242                                        int              len)
04243 {
04244   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04245 
04246   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04247 
04248   if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
04249     return FALSE;
04250   
04251   if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
04252     {
04253       _dbus_string_set_length (&real->message->body, real->pos);
04254       return FALSE;
04255     }
04256 
04257   dbus_message_iter_append_done (real);
04258   
04259   return TRUE;
04260 }
04261 
04270 dbus_bool_t
04271 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
04272                                      unsigned const char *value,
04273                                      int                  len)
04274 {
04275   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04276 
04277   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04278 
04279   if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
04280     return FALSE;
04281   
04282   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
04283     {
04284       _dbus_string_set_length (&real->message->body, real->pos);
04285       return FALSE;
04286     }
04287 
04288   dbus_message_iter_append_done (real);
04289   
04290   return TRUE;
04291 }
04292 
04301 dbus_bool_t
04302 dbus_message_iter_append_string_array (DBusMessageIter *iter,
04303                                        const char     **value,
04304                                        int              len)
04305 {
04306   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04307 
04308   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04309 
04310   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
04311     return FALSE;
04312   
04313   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04314     {
04315       _dbus_string_set_length (&real->message->body, real->pos);
04316       return FALSE;
04317     }
04318 
04319   dbus_message_iter_append_done (real);
04320   
04321   return TRUE;
04322 }
04323 
04331 dbus_bool_t
04332 dbus_message_set_sender (DBusMessage  *message,
04333                          const char   *sender)
04334 {
04335   _dbus_return_val_if_fail (message != NULL, FALSE);
04336   _dbus_return_val_if_fail (!message->locked, FALSE);
04337 
04338   return set_string_field (message,
04339                            DBUS_HEADER_FIELD_SENDER_SERVICE,
04340                            DBUS_TYPE_STRING,
04341                            sender);
04342 }
04343 
04354 void
04355 dbus_message_set_no_reply (DBusMessage *message,
04356                            dbus_bool_t  no_reply)
04357 {
04358   char *header;
04359 
04360   _dbus_return_if_fail (message != NULL);
04361   _dbus_return_if_fail (!message->locked);
04362   
04363   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04364   
04365   if (no_reply)
04366     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
04367   else
04368     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
04369 }
04370 
04378 dbus_bool_t
04379 dbus_message_get_no_reply (DBusMessage *message)
04380 {
04381   const char *header;
04382 
04383   _dbus_return_val_if_fail (message != NULL, FALSE);
04384   
04385   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04386 
04387   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
04388 }
04389 
04390 
04400 void
04401 dbus_message_set_auto_activation (DBusMessage *message,
04402                                   dbus_bool_t  auto_activation)
04403 {
04404   char *header;
04405 
04406   _dbus_return_if_fail (message != NULL);
04407   _dbus_return_if_fail (!message->locked);
04408   
04409   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04410   
04411   if (auto_activation)
04412     *header |= DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04413   else
04414     *header &= ~DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04415 }
04416 
04424 dbus_bool_t
04425 dbus_message_get_auto_activation (DBusMessage *message)
04426 {
04427   const char *header;
04428 
04429   _dbus_return_val_if_fail (message != NULL, FALSE);
04430   
04431   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04432 
04433   return (*header & DBUS_HEADER_FLAG_AUTO_ACTIVATION) != 0;
04434 }
04435 
04443 const char*
04444 dbus_message_get_sender (DBusMessage *message)
04445 {
04446   _dbus_return_val_if_fail (message != NULL, NULL);
04447   
04448   return get_string_field (message, 
04449                            DBUS_HEADER_FIELD_SENDER_SERVICE,
04450                            NULL);
04451 }
04452 
04468 const char*
04469 dbus_message_get_signature (DBusMessage *message)
04470 {
04471   _dbus_return_val_if_fail (message != NULL, NULL);
04472   
04473   return _dbus_string_get_const_data (&message->signature);
04474 }
04475 
04476 static dbus_bool_t
04477 _dbus_message_has_type_interface_member (DBusMessage *message,
04478                                          int          type,
04479                                          const char  *interface,
04480                                          const char  *method)
04481 {
04482   const char *n;
04483 
04484   _dbus_assert (message != NULL);
04485   _dbus_assert (interface != NULL);
04486   _dbus_assert (method != NULL);
04487 
04488   if (dbus_message_get_type (message) != type)
04489     return FALSE;
04490 
04491   /* Optimize by checking the short method name first
04492    * instead of the longer interface name
04493    */  
04494 
04495   n = dbus_message_get_member (message);
04496 
04497   if (n && strcmp (n, method) == 0)
04498     {
04499       n = dbus_message_get_interface (message);
04500       
04501       if (n && strcmp (n, interface) == 0)
04502         return TRUE;
04503     }
04504 
04505   return FALSE;
04506 }
04507 
04520 dbus_bool_t
04521 dbus_message_is_method_call (DBusMessage *message,
04522                              const char  *interface,
04523                              const char  *method)
04524 {
04525   _dbus_return_val_if_fail (message != NULL, FALSE);
04526   _dbus_return_val_if_fail (interface != NULL, FALSE);
04527   _dbus_return_val_if_fail (method != NULL, FALSE);
04528 
04529   return _dbus_message_has_type_interface_member (message,
04530                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
04531                                                   interface, method);
04532 }
04533 
04546 dbus_bool_t
04547 dbus_message_is_signal (DBusMessage *message,
04548                         const char  *interface,
04549                         const char  *signal_name)
04550 {
04551   _dbus_return_val_if_fail (message != NULL, FALSE);
04552   _dbus_return_val_if_fail (interface != NULL, FALSE);
04553   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
04554 
04555   return _dbus_message_has_type_interface_member (message,
04556                                                   DBUS_MESSAGE_TYPE_SIGNAL,
04557                                                   interface, signal_name);
04558 }
04559 
04570 dbus_bool_t
04571 dbus_message_is_error (DBusMessage *message,
04572                         const char  *error_name)
04573 {
04574   const char *n;
04575   
04576   _dbus_return_val_if_fail (message != NULL, FALSE);
04577   _dbus_return_val_if_fail (error_name != NULL, FALSE);
04578 
04579   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04580     return FALSE;
04581 
04582   n = dbus_message_get_error_name (message);
04583 
04584   if (n && strcmp (n, error_name) == 0)
04585     return TRUE;
04586   else
04587     return FALSE;
04588 }
04589 
04600 dbus_bool_t
04601 dbus_message_has_destination (DBusMessage  *message,
04602                               const char   *service)
04603 {
04604   const char *s;
04605 
04606   _dbus_return_val_if_fail (message != NULL, FALSE);
04607   _dbus_return_val_if_fail (service != NULL, FALSE);
04608   
04609   s = dbus_message_get_destination (message);
04610 
04611   if (s && strcmp (s, service) == 0)
04612     return TRUE;
04613   else
04614     return FALSE;
04615 }
04616 
04631 dbus_bool_t
04632 dbus_message_has_sender (DBusMessage  *message,
04633                          const char   *service)
04634 {
04635   const char *s;
04636 
04637   _dbus_return_val_if_fail (message != NULL, FALSE);
04638   _dbus_return_val_if_fail (service != NULL, FALSE);
04639   
04640   s = dbus_message_get_sender (message);
04641 
04642   if (s && strcmp (s, service) == 0)
04643     return TRUE;
04644   else
04645     return FALSE;
04646 }
04647 
04657 dbus_bool_t
04658 dbus_message_has_signature (DBusMessage   *message,
04659                             const char    *signature)
04660 {
04661   _dbus_return_val_if_fail (message != NULL, FALSE);
04662   _dbus_return_val_if_fail (signature != NULL, FALSE);
04663 
04664   return _dbus_string_equal_c_str (&message->signature, signature);
04665 }
04666 
04684 dbus_bool_t
04685 dbus_set_error_from_message (DBusError   *error,
04686                              DBusMessage *message)
04687 {
04688   char *str;
04689 
04690   _dbus_return_val_if_fail (message != NULL, FALSE);
04691   _dbus_return_val_if_error_is_set (error, FALSE);
04692   
04693   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04694     return FALSE;
04695 
04696   str = NULL;
04697   dbus_message_get_args (message, NULL,
04698                          DBUS_TYPE_STRING, &str,
04699                          DBUS_TYPE_INVALID);
04700 
04701   dbus_set_error (error, dbus_message_get_error_name (message),
04702                   str ? "%s" : NULL, str);
04703 
04704   dbus_free (str);
04705   
04706   return TRUE;
04707 }
04708 
04733 /* we definitely use signed ints for sizes, so don't exceed
04734  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
04735  * over 128M is pretty nuts anyhow.
04736  */
04737 
04741 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
04742 
04747 struct DBusMessageLoader
04748 {
04749   int refcount;        
04751   DBusString data;     
04753   DBusList *messages;  
04755   long max_message_size; 
04757   unsigned int buffer_outstanding : 1; 
04759   unsigned int corrupted : 1; 
04760 };
04761 
04772 #define INITIAL_LOADER_DATA_LEN 32
04773 
04780 DBusMessageLoader*
04781 _dbus_message_loader_new (void)
04782 {
04783   DBusMessageLoader *loader;
04784 
04785   loader = dbus_new0 (DBusMessageLoader, 1);
04786   if (loader == NULL)
04787     return NULL;
04788   
04789   loader->refcount = 1;
04790 
04791   /* Try to cap message size at something that won't *totally* hose
04792    * the system if we have a couple of them.
04793    */
04794   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
04795   
04796   if (!_dbus_string_init (&loader->data))
04797     {
04798       dbus_free (loader);
04799       return NULL;
04800     }
04801 
04802   /* preallocate the buffer for speed, ignore failure */
04803   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
04804   _dbus_string_set_length (&loader->data, 0);
04805   
04806   return loader;
04807 }
04808 
04815 DBusMessageLoader *
04816 _dbus_message_loader_ref (DBusMessageLoader *loader)
04817 {
04818   loader->refcount += 1;
04819 
04820   return loader;
04821 }
04822 
04829 void
04830 _dbus_message_loader_unref (DBusMessageLoader *loader)
04831 {
04832   loader->refcount -= 1;
04833   if (loader->refcount == 0)
04834     {
04835       _dbus_list_foreach (&loader->messages,
04836                           (DBusForeachFunction) dbus_message_unref,
04837                           NULL);
04838       _dbus_list_clear (&loader->messages);
04839       _dbus_string_free (&loader->data);
04840       dbus_free (loader);
04841     }
04842 }
04843 
04862 void
04863 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
04864                                  DBusString        **buffer)
04865 {
04866   _dbus_assert (!loader->buffer_outstanding);
04867 
04868   *buffer = &loader->data;
04869   
04870   loader->buffer_outstanding = TRUE;
04871 }
04872 
04877 #define DBUS_MINIMUM_HEADER_SIZE 16
04878 
04879 static dbus_bool_t
04880 decode_string_field (const DBusString   *data,
04881                      int                 field,
04882                      HeaderField        *header_field,
04883                      DBusString         *field_data,
04884                      int                 pos,
04885                      int                 type)
04886 {
04887   int string_data_pos;
04888 
04889   _dbus_assert (header_field != NULL);
04890   _dbus_assert (field_data != NULL);
04891   
04892   if (header_field->name_offset >= 0)
04893     {
04894       _dbus_verbose ("%s field provided twice\n",
04895                      _dbus_header_field_to_string (field));
04896       return FALSE;
04897     }
04898 
04899   if (type != DBUS_TYPE_STRING)
04900     {
04901       _dbus_verbose ("%s field has wrong type %s\n",
04902                      _dbus_header_field_to_string (field),
04903                      _dbus_type_to_string (type));
04904       return FALSE;
04905     }
04906 
04907   /* skip padding after typecode, skip string length;
04908    * we assume that the string arg has already been validated
04909    * for sanity and UTF-8
04910    */
04911   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
04912   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
04913   
04914   _dbus_string_init_const (field_data,
04915                            _dbus_string_get_const_data (data) + string_data_pos);
04916 
04917   header_field->name_offset  = pos;
04918   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
04919   
04920 #if 0
04921   _dbus_verbose ("Found field %s at offset %d\n",
04922                  _dbus_header_field_to_string (field),
04923                  header_field->value_offset);
04924 #endif
04925 
04926   return TRUE;
04927 }
04928 
04929 /* FIXME because the service/interface/member/error names are already
04930  * validated to be in the particular ASCII subset, UTF-8 validating
04931  * them could be skipped as a probably-interesting optimization.
04932  * The UTF-8 validation definitely shows up in profiles.
04933  */
04934 static dbus_bool_t
04935 decode_header_data (const DBusString   *data,
04936                     int                 header_len,
04937                     int                 byte_order,
04938                     int                 message_type,
04939                     HeaderField         fields[DBUS_HEADER_FIELD_LAST + 1],
04940                     int                *message_padding)
04941 {
04942   DBusString field_data;
04943   int pos, new_pos;
04944   int i;
04945   int field;
04946   int type;
04947   
04948   if (header_len < 16)
04949     {
04950       _dbus_verbose ("Header length %d is too short\n", header_len);
04951       return FALSE;
04952     }
04953   
04954   i = 0;
04955   while (i <= DBUS_HEADER_FIELD_LAST)
04956     {
04957       fields[i].name_offset  = -1;
04958       fields[i].value_offset = -1;
04959       ++i;
04960     }
04961   
04962   pos = 16;
04963   while (pos < header_len)
04964     {
04965       field = _dbus_string_get_byte (data, pos);
04966       if (field == DBUS_HEADER_FIELD_INVALID)
04967         break; /* Must be padding */
04968       pos++;
04969 
04970       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
04971         {
04972           _dbus_verbose ("Failed to validate type of named header field pos = %d\n",
04973                          pos);
04974           return FALSE;
04975         }
04976       
04977       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
04978         {
04979           _dbus_verbose ("Failed to validate argument to named header field pos = %d\n",
04980                          pos);
04981           return FALSE;
04982         }
04983 
04984       if (new_pos > header_len)
04985         {
04986           _dbus_verbose ("Named header field tries to extend beyond header length\n");
04987           return FALSE;
04988         }
04989       
04990       switch (field)
04991         {
04992         case DBUS_HEADER_FIELD_SERVICE:
04993           if (!decode_string_field (data, field, &fields[field],
04994                                     &field_data, pos, type))
04995             return FALSE;
04996 
04997           if (!_dbus_string_validate_service (&field_data, 0,
04998                                               _dbus_string_get_length (&field_data)))
04999             {
05000               _dbus_verbose ("service field has invalid content \"%s\"\n",
05001                              _dbus_string_get_const_data (&field_data));
05002               return FALSE;
05003             }
05004           break;
05005 
05006         case DBUS_HEADER_FIELD_INTERFACE:
05007           if (!decode_string_field (data, field, &fields[field],
05008                                     &field_data, pos, type))
05009             return FALSE;
05010 
05011           if (!_dbus_string_validate_interface (&field_data, 0,
05012                                                 _dbus_string_get_length (&field_data)))
05013             {
05014               _dbus_verbose ("interface field has invalid content \"%s\"\n",
05015                              _dbus_string_get_const_data (&field_data));
05016               return FALSE;
05017             }
05018       
05019           if (_dbus_string_equal_c_str (&field_data,
05020                                         DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
05021             {
05022               _dbus_verbose ("Message is on the local interface\n");
05023               return FALSE;
05024             }
05025           break;
05026 
05027         case DBUS_HEADER_FIELD_MEMBER:
05028           if (!decode_string_field (data, field, &fields[field],
05029                                     &field_data, pos, type))
05030             return FALSE;
05031           
05032           if (!_dbus_string_validate_member (&field_data, 0,
05033                                              _dbus_string_get_length (&field_data)))
05034             {
05035               _dbus_verbose ("member field has invalid content \"%s\"\n",
05036                              _dbus_string_get_const_data (&field_data));
05037               return FALSE;
05038             }
05039           break;
05040 
05041         case DBUS_HEADER_FIELD_ERROR_NAME:
05042           if (!decode_string_field (data, field, &fields[field],
05043                                     &field_data, pos, type))
05044             return FALSE;
05045           
05046           if (!_dbus_string_validate_error_name (&field_data, 0,
05047                                                  _dbus_string_get_length (&field_data)))
05048             {
05049               _dbus_verbose ("error-name field has invalid content \"%s\"\n",
05050                              _dbus_string_get_const_data (&field_data));
05051               return FALSE;
05052             }
05053           break;
05054           
05055         case DBUS_HEADER_FIELD_SENDER_SERVICE:
05056           if (!decode_string_field (data, field, &fields[field],
05057                                     &field_data, pos, type))
05058             return FALSE;
05059           
05060           if (!_dbus_string_validate_service (&field_data, 0,
05061                                               _dbus_string_get_length (&field_data)))
05062             {
05063               _dbus_verbose ("sender-service field has invalid content \"%s\"\n",
05064                              _dbus_string_get_const_data (&field_data));
05065               return FALSE;
05066             }
05067           break;
05068 
05069         case DBUS_HEADER_FIELD_PATH:
05070 
05071           /* Path was already validated as part of standard
05072            * type validation, since there's an OBJECT_PATH
05073            * type.
05074            */
05075           
05076           if (fields[field].name_offset >= 0)
05077             {
05078               _dbus_verbose ("path field provided twice\n");
05079               return FALSE;
05080             }
05081           if (type != DBUS_TYPE_OBJECT_PATH)
05082             {
05083               _dbus_verbose ("path field has wrong type\n");
05084               return FALSE;
05085             }
05086 
05087           fields[field].name_offset  = pos;
05088           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05089 
05090           /* No forging signals from the local path */
05091           {
05092             const char *s;
05093             s = _dbus_string_get_const_data_len (data,
05094                                                  fields[field].value_offset,
05095                                                  _dbus_string_get_length (data) -
05096                                                  fields[field].value_offset);
05097             if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
05098               {
05099                 _dbus_verbose ("Message is on the local path\n");
05100                 return FALSE;
05101               }
05102           }
05103           
05104           _dbus_verbose ("Found path at offset %d\n",
05105                          fields[field].value_offset);
05106           break;
05107           
05108         case DBUS_HEADER_FIELD_REPLY_SERIAL:
05109           if (fields[field].name_offset >= 0)
05110             {
05111               _dbus_verbose ("reply field provided twice\n");
05112               return FALSE;
05113             }
05114 
05115           if (type != DBUS_TYPE_UINT32)
05116             {
05117               _dbus_verbose ("reply field has wrong type\n");
05118               return FALSE;
05119             }
05120           
05121           fields[field].name_offset  = pos;
05122           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05123 
05124           _dbus_verbose ("Found reply serial %u at offset %d\n",
05125                          _dbus_demarshal_uint32 (data,
05126                                                  byte_order,
05127                                                  fields[field].value_offset,
05128                                                  NULL),
05129                          fields[field].value_offset);
05130           break;
05131 
05132         default:
05133           _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
05134                          field, pos);
05135         }
05136       
05137       pos = new_pos;
05138     }
05139 
05140   if (pos < header_len)
05141     {
05142       /* Alignment padding, verify that it's nul */
05143       if ((header_len - pos) >= 8)
05144         {
05145           _dbus_verbose ("too much header alignment padding\n");
05146           return FALSE;
05147         }
05148 
05149       if (!_dbus_string_validate_nul (data,
05150                                       pos, (header_len - pos)))
05151         {
05152           _dbus_verbose ("header alignment padding is not nul\n");
05153           return FALSE;
05154         }
05155     }
05156 
05157   /* Depending on message type, enforce presence of certain fields. */
05158   switch (message_type)
05159     {
05160     case DBUS_MESSAGE_TYPE_SIGNAL:
05161     case DBUS_MESSAGE_TYPE_METHOD_CALL:
05162       if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
05163         {
05164           _dbus_verbose ("No path field provided\n");
05165           return FALSE;
05166         }
05167       /* FIXME make this optional, only for method calls */
05168       if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
05169         {
05170           _dbus_verbose ("No interface field provided\n");
05171           return FALSE;
05172         }
05173       if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
05174         {
05175           _dbus_verbose ("No member field provided\n");
05176           return FALSE;
05177         }
05178       break;
05179     case DBUS_MESSAGE_TYPE_ERROR:
05180       if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
05181         {
05182           _dbus_verbose ("No error-name field provided\n");
05183           return FALSE;
05184         }
05185       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05186         {
05187           _dbus_verbose ("No reply serial field provided in error\n");
05188           return FALSE;
05189         }
05190       break;
05191     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
05192       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05193         {
05194           _dbus_verbose ("No reply serial field provided in method return\n");
05195           return FALSE;
05196         }
05197       break;
05198     default:
05199       /* An unknown type, spec requires us to ignore it */
05200       break;
05201     }
05202   
05203   if (message_padding)
05204     *message_padding = header_len - pos;  
05205   
05206   return TRUE;
05207 }
05208 
05219 void
05220 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
05221                                     DBusString         *buffer,
05222                                     int                 bytes_read)
05223 {
05224   _dbus_assert (loader->buffer_outstanding);
05225   _dbus_assert (buffer == &loader->data);
05226 
05227   loader->buffer_outstanding = FALSE;
05228 }
05229 
05230 static dbus_bool_t
05231 load_one_message (DBusMessageLoader *loader,
05232                   int                byte_order,
05233                   int                message_type,
05234                   int                header_len,
05235                   int                body_len)
05236 {
05237   DBusMessage *message;
05238   HeaderField fields[DBUS_HEADER_FIELD_LAST + 1];
05239   int i;
05240   int next_arg;
05241   dbus_bool_t oom;
05242   int header_padding;
05243   
05244   message = NULL;
05245   oom = FALSE;
05246   
05247 #if 0
05248   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
05249 #endif    
05250 
05251   if (!decode_header_data (&loader->data,
05252                            header_len, byte_order,
05253                            message_type,
05254                            fields, &header_padding))
05255     {
05256       _dbus_verbose ("Header was invalid\n");
05257       loader->corrupted = TRUE;
05258       goto failed;
05259     }
05260           
05261   next_arg = header_len;
05262   while (next_arg < (header_len + body_len))
05263     {
05264       int type;
05265       int prev = next_arg;
05266 
05267       if (!_dbus_marshal_validate_type (&loader->data, next_arg,
05268                                         &type, &next_arg))
05269         {
05270           _dbus_verbose ("invalid typecode at offset %d\n", prev);
05271           loader->corrupted = TRUE;
05272           goto failed;
05273         }
05274       
05275       if (!_dbus_marshal_validate_arg (&loader->data,
05276                                        byte_order,
05277                                        0,
05278                                        type, -1,
05279                                        next_arg,
05280                                        &next_arg))
05281         {
05282           _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
05283           loader->corrupted = TRUE;
05284           goto failed;
05285         }
05286 
05287       _dbus_assert (next_arg > prev);
05288     }
05289           
05290   if (next_arg > (header_len + body_len))
05291     {
05292       _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
05293                      next_arg, header_len, body_len,
05294                      header_len + body_len);
05295       loader->corrupted = TRUE;
05296       goto failed;
05297     }
05298 
05299   message = dbus_message_new_empty_header ();
05300   if (message == NULL)
05301     {
05302       _dbus_verbose ("Failed to allocate empty message\n");
05303       oom = TRUE;
05304       goto failed;
05305     }
05306 
05307   message->byte_order = byte_order;
05308   message->header_padding = header_padding;
05309           
05310   /* Copy in the offsets we found */
05311   i = 0;
05312   while (i <= DBUS_HEADER_FIELD_LAST)
05313     {
05314       message->header_fields[i] = fields[i];
05315       ++i;
05316     }
05317           
05318   if (!_dbus_list_append (&loader->messages, message))
05319     {
05320       _dbus_verbose ("Failed to append new message to loader queue\n");
05321       oom = TRUE;
05322       goto failed;
05323     }
05324 
05325   _dbus_assert (_dbus_string_get_length (&message->header) == 0);
05326   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
05327 
05328   _dbus_assert (_dbus_string_get_length (&loader->data) >=
05329                 (header_len + body_len));
05330           
05331   if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
05332     {
05333       _dbus_verbose ("Failed to move header into new message\n");
05334       oom = TRUE;
05335       goto failed;
05336     }
05337           
05338   if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
05339     {
05340       _dbus_verbose ("Failed to move body into new message\n");
05341       
05342       oom = TRUE;
05343       goto failed;
05344     }
05345 
05346   _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
05347   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
05348 
05349   /* Fill in caches (we checked the types of these fields
05350    * earlier)
05351    */
05352   message->reply_serial = get_uint_field (message,
05353                                           DBUS_HEADER_FIELD_REPLY_SERIAL);
05354   
05355   message->client_serial = _dbus_demarshal_uint32 (&message->header,
05356                                                    message->byte_order,
05357                                                    CLIENT_SERIAL_OFFSET,
05358                                                    NULL);
05359   if (message->client_serial == 0 ||
05360       (message->header_fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset >= 0 && message->reply_serial == 0))
05361     {
05362       _dbus_verbose ("client_serial = %d reply_serial = %d, one of these no good\n",
05363                      message->client_serial,
05364                      message->reply_serial);
05365       
05366       loader->corrupted = TRUE;
05367       goto failed;
05368     }
05369           
05370   /* Fill in signature (FIXME should do this during validation,
05371    * but I didn't want to spend time on it since we want to change
05372    * the wire format to contain the signature anyway)
05373    */
05374   {
05375     DBusMessageIter iter;
05376 
05377     dbus_message_iter_init (message, &iter);
05378 
05379     do
05380       {
05381         int t;
05382 
05383         t = dbus_message_iter_get_arg_type (&iter);
05384         if (t == DBUS_TYPE_INVALID)
05385           break;
05386 
05387         if (!_dbus_string_append_byte (&message->signature,
05388                                        t))
05389           {
05390             _dbus_verbose ("failed to append type byte to signature\n");
05391             oom = TRUE;
05392             goto failed;
05393           }
05394 
05395         if (t == DBUS_TYPE_ARRAY)
05396           {
05397             DBusMessageIter child_iter;
05398             int array_type = t;
05399 
05400             child_iter = iter;
05401                     
05402             while (array_type == DBUS_TYPE_ARRAY)
05403               {
05404                 DBusMessageIter parent_iter = child_iter;
05405                 dbus_message_iter_init_array_iterator (&parent_iter,
05406                                                        &child_iter,
05407                                                        &array_type);
05408                                             
05409                 if (!_dbus_string_append_byte (&message->signature,
05410                                                array_type))
05411                   {
05412                     _dbus_verbose ("failed to append array type byte to signature\n");
05413 
05414                     oom = TRUE;
05415                     goto failed;
05416                   }
05417               }
05418           }
05419       }
05420     while (dbus_message_iter_next (&iter));
05421   }
05422           
05423   _dbus_verbose ("Loaded message %p\n", message);
05424 
05425   _dbus_assert (!oom);
05426   _dbus_assert (!loader->corrupted);
05427 
05428   return TRUE;
05429 
05430  failed:
05431   
05432   /* Clean up */
05433   
05434   if (message != NULL)
05435     {
05436       /* Put the data back so we can try again later if it was an OOM issue */
05437       if (_dbus_string_get_length (&message->body) > 0)
05438         {
05439           dbus_bool_t result;
05440           
05441           result = _dbus_string_copy_len (&message->body, 0, body_len,
05442                                           &loader->data, 0);
05443           
05444           _dbus_assert (result); /* because DBusString never reallocs smaller */
05445         }
05446       
05447       if (_dbus_string_get_length (&message->header) > 0)
05448         {
05449           dbus_bool_t result;
05450           
05451           result = _dbus_string_copy_len (&message->header, 0, header_len,
05452                                           &loader->data, 0);
05453           
05454           _dbus_assert (result); /* because DBusString never reallocs smaller */
05455         }
05456 
05457       /* does nothing if the message isn't in the list */
05458       _dbus_list_remove_last (&loader->messages, message);
05459 
05460       dbus_message_unref (message);
05461     }
05462 
05463   
05464   return !oom;
05465 }
05466 
05480 dbus_bool_t
05481 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
05482 {
05483   while (!loader->corrupted && _dbus_string_get_length (&loader->data) >= 16)
05484     {
05485       const char *header_data;
05486       int byte_order, message_type, header_len, body_len;
05487       dbus_uint32_t header_len_unsigned, body_len_unsigned;
05488       
05489       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
05490 
05491       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
05492 
05493       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
05494         {
05495           _dbus_verbose ("Message has protocol version %d ours is %d\n",
05496                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
05497           loader->corrupted = TRUE;
05498           return TRUE;
05499         }
05500       
05501       byte_order = header_data[BYTE_ORDER_OFFSET];
05502 
05503       if (byte_order != DBUS_LITTLE_ENDIAN &&
05504           byte_order != DBUS_BIG_ENDIAN)
05505         {
05506           _dbus_verbose ("Message with bad byte order '%c' received\n",
05507                          byte_order);
05508           loader->corrupted = TRUE;
05509           return TRUE;
05510         }
05511 
05512       /* Unknown types are ignored, but INVALID is
05513        * disallowed
05514        */
05515       message_type = header_data[TYPE_OFFSET];
05516       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
05517         {
05518           _dbus_verbose ("Message with bad type '%d' received\n",
05519                          message_type);
05520           loader->corrupted = TRUE;
05521           return TRUE;
05522         }      
05523       
05524       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
05525       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
05526 
05527       if (header_len_unsigned < 16)
05528         {
05529           _dbus_verbose ("Message had broken too-small header length %u\n",
05530                          header_len_unsigned);
05531           loader->corrupted = TRUE;
05532           return TRUE;
05533         }
05534 
05535       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
05536           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
05537         {
05538           _dbus_verbose ("Header or body length too large (%u %u)\n",
05539                          header_len_unsigned,
05540                          body_len_unsigned);
05541           loader->corrupted = TRUE;
05542           return TRUE;
05543         }
05544 
05545       /* Now that we know the values are in signed range, get
05546        * rid of stupid unsigned, just causes bugs
05547        */
05548       header_len = header_len_unsigned;
05549       body_len = body_len_unsigned;
05550 
05551       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
05552         {
05553           
05554           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
05555                          header_len);
05556           loader->corrupted = TRUE;
05557           return TRUE;
05558         }
05559       
05560       if (header_len + body_len > loader->max_message_size)
05561         {
05562           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
05563                          header_len, body_len, loader->max_message_size);
05564           loader->corrupted = TRUE;
05565           return TRUE;
05566         }
05567 
05568       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
05569         {
05570           if (!load_one_message (loader, byte_order, message_type,
05571                                  header_len, body_len))
05572             return FALSE;
05573         }
05574       else
05575         return TRUE;
05576     }
05577 
05578   return TRUE;
05579 }
05580 
05588 DBusMessage*
05589 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
05590 {
05591   if (loader->messages)
05592     return loader->messages->data;
05593   else
05594     return NULL;
05595 }
05596 
05605 DBusMessage*
05606 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
05607 {
05608   return _dbus_list_pop_first (&loader->messages);
05609 }
05610 
05619 DBusList*
05620 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
05621 {
05622   return _dbus_list_pop_first_link (&loader->messages);
05623 }
05624 
05631 void
05632 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
05633                                            DBusList           *link)
05634 {
05635   _dbus_list_prepend_link (&loader->messages, link);
05636 }
05637 
05647 dbus_bool_t
05648 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
05649 {
05650   return loader->corrupted;
05651 }
05652 
05659 void
05660 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
05661                                            long                size)
05662 {
05663   if (size > MAX_SANE_MESSAGE_SIZE)
05664     {
05665       _dbus_verbose ("clamping requested max message size %ld to %d\n",
05666                      size, MAX_SANE_MESSAGE_SIZE);
05667       size = MAX_SANE_MESSAGE_SIZE;
05668     }
05669   loader->max_message_size = size;
05670 }
05671 
05678 long
05679 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
05680 {
05681   return loader->max_message_size;
05682 }
05683 
05684 static DBusDataSlotAllocator slot_allocator;
05685 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
05686 
05701 dbus_bool_t
05702 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
05703 {
05704   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05705                                           _DBUS_LOCK_NAME (message_slots),
05706                                           slot_p);
05707 }
05708 
05720 void
05721 dbus_message_free_data_slot (dbus_int32_t *slot_p)
05722 {
05723   _dbus_return_if_fail (*slot_p >= 0);
05724   
05725   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05726 }
05727 
05741 dbus_bool_t
05742 dbus_message_set_data (DBusMessage     *message,
05743                        dbus_int32_t     slot,
05744                        void            *data,
05745                        DBusFreeFunction free_data_func)
05746 {
05747   DBusFreeFunction old_free_func;
05748   void *old_data;
05749   dbus_bool_t retval;
05750 
05751   _dbus_return_val_if_fail (message != NULL, FALSE);
05752   _dbus_return_val_if_fail (slot >= 0, FALSE);
05753 
05754   retval = _dbus_data_slot_list_set (&slot_allocator,
05755                                      &message->slot_list,
05756                                      slot, data, free_data_func,
05757                                      &old_free_func, &old_data);
05758 
05759   if (retval)
05760     {
05761       /* Do the actual free outside the message lock */
05762       if (old_free_func)
05763         (* old_free_func) (old_data);
05764     }
05765 
05766   return retval;
05767 }
05768 
05777 void*
05778 dbus_message_get_data (DBusMessage   *message,
05779                        dbus_int32_t   slot)
05780 {
05781   void *res;
05782 
05783   _dbus_return_val_if_fail (message != NULL, NULL);
05784   
05785   res = _dbus_data_slot_list_get (&slot_allocator,
05786                                   &message->slot_list,
05787                                   slot);
05788 
05789   return res;
05790 }
05791 
05805 int
05806 dbus_message_type_from_string (const char *type_str)
05807 {
05808   if (strcmp (type_str, "method_call") == 0)
05809     return DBUS_MESSAGE_TYPE_METHOD_CALL;
05810   if (strcmp (type_str, "method_return") == 0)
05811     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
05812   else if (strcmp (type_str, "signal") == 0)
05813     return DBUS_MESSAGE_TYPE_SIGNAL;
05814   else if (strcmp (type_str, "error") == 0)
05815     return DBUS_MESSAGE_TYPE_ERROR;
05816   else
05817     return DBUS_MESSAGE_TYPE_INVALID;
05818 }
05819 
05821 #ifdef DBUS_BUILD_TESTS
05822 #include "dbus-test.h"
05823 #include <stdio.h>
05824 #include <stdlib.h>
05825 
05826 static void
05827 message_iter_test (DBusMessage *message)
05828 {
05829   DBusMessageIter iter, dict, dict2, array, array2;
05830   char *str;
05831   unsigned char *data;
05832   dbus_int32_t *our_int_array;
05833   int len;
05834   
05835   dbus_message_iter_init (message, &iter);
05836 
05837   /* String tests */
05838   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
05839     _dbus_assert_not_reached ("Argument type isn't string");
05840 
05841   str = dbus_message_iter_get_string (&iter);
05842   if (strcmp (str, "Test string") != 0)
05843     _dbus_assert_not_reached ("Strings differ");
05844   dbus_free (str);
05845 
05846   if (!dbus_message_iter_next (&iter))
05847     _dbus_assert_not_reached ("Reached end of arguments");
05848 
05849   /* Signed integer tests */
05850   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
05851     _dbus_assert_not_reached ("Argument type isn't int32");
05852 
05853   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
05854     _dbus_assert_not_reached ("Signed integers differ");
05855 
05856   if (!dbus_message_iter_next (&iter))
05857     _dbus_assert_not_reached ("Reached end of fields");
05858   
05859   /* Unsigned integer tests */
05860   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
05861     _dbus_assert_not_reached ("Argument type isn't int32");
05862 
05863   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
05864     _dbus_assert_not_reached ("Unsigned integers differ");
05865 
05866   if (!dbus_message_iter_next (&iter))
05867     _dbus_assert_not_reached ("Reached end of arguments");
05868 
05869   /* Double tests */
05870   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
05871     _dbus_assert_not_reached ("Argument type isn't double");
05872 
05873   if (dbus_message_iter_get_double (&iter) != 3.14159)
05874     _dbus_assert_not_reached ("Doubles differ");
05875 
05876   if (!dbus_message_iter_next (&iter))
05877     _dbus_assert_not_reached ("Reached end of arguments");
05878 
05879   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
05880     _dbus_assert_not_reached ("Argument type not an array");
05881 
05882   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
05883     _dbus_assert_not_reached ("Array type not double");
05884 
05885   
05886   dbus_message_iter_init_array_iterator (&iter, &array, NULL);
05887 
05888   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
05889     _dbus_assert_not_reached ("Argument type isn't double");
05890 
05891   if (dbus_message_iter_get_double (&array) != 1.5)
05892     _dbus_assert_not_reached ("Unsigned integers differ");
05893 
05894   if (!dbus_message_iter_next (&array))
05895     _dbus_assert_not_reached ("Reached end of arguments");
05896 
05897   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
05898     _dbus_assert_not_reached ("Argument type isn't double");
05899 
05900   if (dbus_message_iter_get_double (&array) != 2.5)
05901     _dbus_assert_not_reached ("Unsigned integers differ");
05902 
05903   if (dbus_message_iter_next (&array))
05904     _dbus_assert_not_reached ("Didn't reach end of arguments");
05905   
05906   if (!dbus_message_iter_next (&iter))
05907     _dbus_assert_not_reached ("Reached end of arguments");
05908   
05909 
05910   /* dict */
05911 
05912   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
05913     _dbus_assert_not_reached ("not dict type");
05914      
05915   dbus_message_iter_init_dict_iterator (&iter, &dict);
05916 
05917   str = dbus_message_iter_get_dict_key (&dict);
05918   if (str == NULL || strcmp (str, "test") != 0)
05919     _dbus_assert_not_reached ("wrong dict key");
05920   dbus_free (str);
05921 
05922   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
05923     _dbus_assert_not_reached ("wrong dict entry type");
05924 
05925   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
05926     _dbus_assert_not_reached ("wrong dict entry value");
05927 
05928   /* dict (in dict) */
05929 
05930   if (!dbus_message_iter_next (&dict))
05931     _dbus_assert_not_reached ("reached end of dict");
05932   
05933   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_DICT)
05934     _dbus_assert_not_reached ("not dict type");
05935     
05936   dbus_message_iter_init_dict_iterator (&dict, &dict2);
05937   
05938   str = dbus_message_iter_get_dict_key (&dict2);
05939   if (str == NULL || strcmp (str, "dictkey") != 0)
05940     _dbus_assert_not_reached ("wrong dict key");
05941   dbus_free (str);
05942   
05943   if (dbus_message_iter_get_arg_type (&dict2) != DBUS_TYPE_STRING)
05944     _dbus_assert_not_reached ("wrong dict entry type");
05945   
05946   str = dbus_message_iter_get_string (&dict2);
05947   if (str == NULL || strcmp (str, "dictvalue") != 0)
05948     _dbus_assert_not_reached ("wrong dict entry value");
05949   dbus_free (str);
05950   
05951   if (dbus_message_iter_next (&dict2))
05952     _dbus_assert_not_reached ("didn't reach end of dict");
05953 
05954   if (!dbus_message_iter_next (&dict))
05955     _dbus_assert_not_reached ("reached end of dict");
05956   
05957   /* array of array of int32 (in dict) */
05958 
05959   str = dbus_message_iter_get_dict_key (&dict);
05960   if (str == NULL || strcmp (str, "array") != 0)
05961     _dbus_assert_not_reached ("wrong dict key");
05962   dbus_free (str);
05963   
05964   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
05965     _dbus_assert_not_reached ("Argument type not an array");
05966 
05967   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
05968     _dbus_assert_not_reached ("Array type not array");
05969 
05970   dbus_message_iter_init_array_iterator (&dict, &array, NULL);
05971 
05972   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
05973     _dbus_assert_not_reached ("Argument type isn't array");
05974   
05975   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
05976     _dbus_assert_not_reached ("Array type not int32");
05977   
05978   dbus_message_iter_init_array_iterator (&array, &array2, NULL);
05979 
05980   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
05981     _dbus_assert_not_reached ("Argument type isn't int32");
05982 
05983   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
05984     _dbus_assert_not_reached ("Signed integers differ");
05985 
05986   if (!dbus_message_iter_next (&array2))
05987     _dbus_assert_not_reached ("Reached end of arguments");
05988 
05989   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
05990     _dbus_assert_not_reached ("Signed integers differ");
05991 
05992   if (dbus_message_iter_next (&array2))
05993     _dbus_assert_not_reached ("Didn't reached end of arguments");
05994 
05995   if (!dbus_message_iter_next (&array))
05996     _dbus_assert_not_reached ("Reached end of arguments");
05997 
05998   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
05999     _dbus_assert_not_reached ("Array type not int32");
06000 
06001   if (!dbus_message_iter_get_int32_array (&array,
06002                                           &our_int_array,
06003                                           &len))
06004     _dbus_assert_not_reached ("couldn't get int32 array");
06005 
06006   _dbus_assert (len == 3);
06007   _dbus_assert (our_int_array[0] == 0x34567812 &&
06008                 our_int_array[1] == 0x45678123 &&
06009                 our_int_array[2] == 0x56781234);
06010   dbus_free (our_int_array);
06011   
06012   if (dbus_message_iter_next (&array))
06013     _dbus_assert_not_reached ("Didn't reach end of array");
06014 
06015   if (dbus_message_iter_next (&dict))
06016     _dbus_assert_not_reached ("Didn't reach end of dict");
06017   
06018   if (!dbus_message_iter_next (&iter))
06019     _dbus_assert_not_reached ("Reached end of arguments");
06020   
06021   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
06022     {
06023       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
06024       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
06025     }
06026   
06027   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06028     _dbus_assert_not_reached ("wrong value after dict");
06029 
06030 
06031   if (!dbus_message_iter_next (&iter))
06032     _dbus_assert_not_reached ("Reached end of arguments");
06033   
06034   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
06035     _dbus_assert_not_reached ("not a nil type");
06036   
06037   if (!dbus_message_iter_next (&iter))
06038     _dbus_assert_not_reached ("Reached end of arguments");
06039   
06040   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_CUSTOM)
06041     _dbus_assert_not_reached ("wrong type after dict");
06042 
06043   if (!dbus_message_iter_get_custom (&iter, &str, &data, &len))
06044     _dbus_assert_not_reached ("failed to get custom type");
06045 
06046   _dbus_assert (strcmp (str, "MyTypeName")==0);
06047   _dbus_assert (len == 5);
06048   _dbus_assert (strcmp (data, "data")==0);
06049   dbus_free (str);
06050   dbus_free (data);
06051   
06052   if (!dbus_message_iter_next (&iter))
06053     _dbus_assert_not_reached ("Reached end of arguments");
06054 
06055   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06056     _dbus_assert_not_reached ("wrong value after custom");
06057 
06058   if (dbus_message_iter_next (&iter))
06059     _dbus_assert_not_reached ("Didn't reach end of arguments");
06060 }
06061 
06062 
06063 static dbus_bool_t
06064 check_message_handling_type (DBusMessageIter *iter,
06065                              int type)
06066 {
06067   DBusMessageIter child_iter;
06068   
06069   switch (type)
06070     {
06071     case DBUS_TYPE_NIL:
06072       break;
06073     case DBUS_TYPE_BYTE:
06074       dbus_message_iter_get_byte (iter);
06075       break;
06076     case DBUS_TYPE_BOOLEAN:
06077       dbus_message_iter_get_boolean (iter);
06078       break;
06079     case DBUS_TYPE_INT32:
06080       dbus_message_iter_get_int32 (iter);
06081       break;
06082     case DBUS_TYPE_UINT32:
06083       dbus_message_iter_get_uint32 (iter);
06084       break;
06085     case DBUS_TYPE_INT64:
06086 #ifdef DBUS_HAVE_INT64
06087       dbus_message_iter_get_int64 (iter);
06088 #endif
06089       break;
06090     case DBUS_TYPE_UINT64:
06091 #ifdef DBUS_HAVE_INT64
06092       dbus_message_iter_get_uint64 (iter);
06093 #endif
06094       break;
06095     case DBUS_TYPE_DOUBLE:
06096       dbus_message_iter_get_double (iter);
06097       break;
06098     case DBUS_TYPE_STRING:
06099       {
06100         char *str;
06101         str = dbus_message_iter_get_string (iter);
06102         if (str == NULL)
06103           {
06104             _dbus_warn ("NULL string in message\n");
06105             return FALSE;
06106           }
06107         dbus_free (str);
06108       }
06109       break;
06110     case DBUS_TYPE_CUSTOM:
06111       {
06112         char *name;
06113         unsigned char *data;
06114         int len;
06115         
06116         if (!dbus_message_iter_get_custom (iter, &name, &data, &len))
06117           {
06118             _dbus_warn ("error reading name from custom type\n");
06119             return FALSE;
06120           }
06121         dbus_free (data);
06122         dbus_free (name);
06123       }
06124       break;
06125     case DBUS_TYPE_ARRAY:
06126       {
06127         int array_type;
06128 
06129         dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type);
06130 
06131         while (dbus_message_iter_has_next (&child_iter))
06132           {
06133             if (!check_message_handling_type (&child_iter, array_type))
06134               {
06135                 _dbus_warn ("error in array element\n");
06136                 return FALSE;
06137               }
06138             
06139             if (!dbus_message_iter_next (&child_iter))
06140               break;
06141           }
06142       }
06143       break;
06144     case DBUS_TYPE_DICT:
06145       {
06146         int entry_type;
06147         char *key;
06148         
06149         dbus_message_iter_init_dict_iterator (iter, &child_iter);
06150 
06151         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
06152           {
06153             key = dbus_message_iter_get_dict_key (&child_iter);
06154             if (key == NULL)
06155               {
06156                 _dbus_warn ("error reading dict key\n");
06157                 return FALSE;
06158               }
06159             dbus_free (key);
06160             
06161             if (!check_message_handling_type (&child_iter, entry_type))
06162               {
06163                 _dbus_warn ("error in dict value\n");
06164                 return FALSE;
06165               }
06166             
06167             if (!dbus_message_iter_next (&child_iter))
06168               break;
06169           }
06170       }
06171       break;
06172       
06173     default:
06174       _dbus_warn ("unknown type %d\n", type);
06175       return FALSE;
06176       break;
06177     }
06178   return TRUE;
06179 }
06180   
06181   
06182 static dbus_bool_t
06183 check_message_handling (DBusMessage *message)
06184 {
06185   DBusMessageIter iter;
06186   int type;
06187   dbus_bool_t retval;
06188   dbus_uint32_t client_serial;
06189   
06190   retval = FALSE;
06191   
06192   client_serial = dbus_message_get_serial (message);
06193 
06194   /* can't use set_serial due to the assertions at the start of it */
06195   _dbus_marshal_set_uint32 (&message->header,
06196                             message->byte_order,
06197                             CLIENT_SERIAL_OFFSET,
06198                             client_serial);
06199   
06200   if (client_serial != dbus_message_get_serial (message))
06201     {
06202       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
06203       goto failed;
06204     }
06205   
06206   /* If we implement message_set_arg (message, n, value)
06207    * then we would want to test it here
06208    */
06209 
06210   dbus_message_iter_init (message, &iter);
06211   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
06212     {
06213       if (!check_message_handling_type (&iter, type))
06214         goto failed;
06215 
06216       if (!dbus_message_iter_next (&iter))
06217         break;
06218     }
06219   
06220   retval = TRUE;
06221   
06222  failed:
06223   return retval;
06224 }
06225 
06226 static dbus_bool_t
06227 check_have_valid_message (DBusMessageLoader *loader)
06228 {
06229   DBusMessage *message;
06230   dbus_bool_t retval;
06231 
06232   message = NULL;
06233   retval = FALSE;
06234 
06235   if (!_dbus_message_loader_queue_messages (loader))
06236     _dbus_assert_not_reached ("no memory to queue messages");
06237   
06238   if (_dbus_message_loader_get_is_corrupted (loader))
06239     {
06240       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
06241       goto failed;
06242     }
06243   
06244   message = _dbus_message_loader_pop_message (loader);
06245   if (message == NULL)
06246     {
06247       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
06248       goto failed;
06249     }
06250   
06251   if (_dbus_string_get_length (&loader->data) > 0)
06252     {
06253       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
06254       goto failed;
06255     }
06256 
06257   /* Verify that we're able to properly deal with the message.
06258    * For example, this would detect improper handling of messages
06259    * in nonstandard byte order.
06260    */
06261   if (!check_message_handling (message))
06262     goto failed;  
06263   
06264   retval = TRUE;
06265 
06266  failed:
06267   if (message)
06268     dbus_message_unref (message);
06269 
06270   return retval;
06271 }
06272 
06273 static dbus_bool_t
06274 check_invalid_message (DBusMessageLoader *loader)
06275 {
06276   dbus_bool_t retval;
06277 
06278   retval = FALSE;
06279 
06280   if (!_dbus_message_loader_queue_messages (loader))
06281     _dbus_assert_not_reached ("no memory to queue messages");
06282   
06283   if (!_dbus_message_loader_get_is_corrupted (loader))
06284     {
06285       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
06286       goto failed;
06287     }
06288 
06289   retval = TRUE;
06290 
06291  failed:
06292   return retval;
06293 }
06294 
06295 static dbus_bool_t
06296 check_incomplete_message (DBusMessageLoader *loader)
06297 {
06298   DBusMessage *message;
06299   dbus_bool_t retval;
06300 
06301   message = NULL;
06302   retval = FALSE;
06303 
06304   if (!_dbus_message_loader_queue_messages (loader))
06305     _dbus_assert_not_reached ("no memory to queue messages");
06306   
06307   if (_dbus_message_loader_get_is_corrupted (loader))
06308     {
06309       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
06310       goto failed;
06311     }
06312   
06313   message = _dbus_message_loader_pop_message (loader);
06314   if (message != NULL)
06315     {
06316       _dbus_warn ("loaded message that was expected to be incomplete\n");
06317       goto failed;
06318     }
06319 
06320   retval = TRUE;
06321 
06322  failed:
06323   if (message)
06324     dbus_message_unref (message);
06325   return retval;
06326 }
06327 
06328 static dbus_bool_t
06329 check_loader_results (DBusMessageLoader      *loader,
06330                       DBusMessageValidity     validity)
06331 {
06332   if (!_dbus_message_loader_queue_messages (loader))
06333     _dbus_assert_not_reached ("no memory to queue messages");
06334   
06335   switch (validity)
06336     {
06337     case _DBUS_MESSAGE_VALID:
06338       return check_have_valid_message (loader);
06339     case _DBUS_MESSAGE_INVALID:
06340       return check_invalid_message (loader);
06341     case _DBUS_MESSAGE_INCOMPLETE:
06342       return check_incomplete_message (loader);
06343     case _DBUS_MESSAGE_UNKNOWN:
06344       return TRUE;
06345     }
06346 
06347   _dbus_assert_not_reached ("bad DBusMessageValidity");
06348   return FALSE;
06349 }
06350 
06351 
06360 dbus_bool_t
06361 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
06362                                             dbus_bool_t          is_raw,
06363                                             DBusString          *data)
06364 {
06365   dbus_bool_t retval;
06366 
06367   retval = FALSE;  
06368 
06369   if (is_raw)
06370     {
06371       DBusError error;
06372 
06373       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
06374       dbus_error_init (&error);
06375       if (!_dbus_file_get_contents (data, filename, &error))
06376         {
06377           _dbus_warn ("Could not load message file %s: %s\n",
06378                       _dbus_string_get_const_data (filename),
06379                       error.message);
06380           dbus_error_free (&error);
06381           goto failed;
06382         }
06383     }
06384   else
06385     {
06386       if (!_dbus_message_data_load (data, filename))
06387         {
06388           _dbus_warn ("Could not load message file %s\n",
06389                       _dbus_string_get_const_data (filename));
06390           goto failed;
06391         }
06392     }
06393 
06394   retval = TRUE;
06395   
06396  failed:
06397 
06398   return retval;
06399 }
06400 
06410 dbus_bool_t
06411 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
06412                                            dbus_bool_t          is_raw,
06413                                            DBusMessageValidity  expected_validity)
06414 {
06415   DBusString data;
06416   dbus_bool_t retval;
06417 
06418   retval = FALSE;
06419   
06420   if (!_dbus_string_init (&data))
06421     _dbus_assert_not_reached ("could not allocate string\n");
06422 
06423   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
06424                                                    &data))
06425     goto failed;
06426 
06427   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
06428 
06429  failed:
06430 
06431   if (!retval)
06432     {
06433       if (_dbus_string_get_length (&data) > 0)
06434         _dbus_verbose_bytes_of_string (&data, 0,
06435                                        _dbus_string_get_length (&data));
06436       
06437       _dbus_warn ("Failed message loader test on %s\n",
06438                   _dbus_string_get_const_data (filename));
06439     }
06440   
06441   _dbus_string_free (&data);
06442 
06443   return retval;
06444 }
06445 
06454 dbus_bool_t
06455 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
06456                                            DBusMessageValidity  expected_validity)
06457 {
06458   DBusMessageLoader *loader;
06459   dbus_bool_t retval;
06460   int len;
06461   int i;
06462 
06463   loader = NULL;
06464   retval = FALSE;
06465 
06466   /* Write the data one byte at a time */
06467   
06468   loader = _dbus_message_loader_new ();
06469 
06470   /* check some trivial loader functions */
06471   _dbus_message_loader_ref (loader);
06472   _dbus_message_loader_unref (loader);
06473   _dbus_message_loader_get_max_message_size (loader);
06474   
06475   len = _dbus_string_get_length (data);
06476   for (i = 0; i < len; i++)
06477     {
06478       DBusString *buffer;
06479 
06480       _dbus_message_loader_get_buffer (loader, &buffer);
06481       _dbus_string_append_byte (buffer,
06482                                 _dbus_string_get_byte (data, i));
06483       _dbus_message_loader_return_buffer (loader, buffer, 1);
06484     }
06485   
06486   if (!check_loader_results (loader, expected_validity))
06487     goto failed;
06488 
06489   _dbus_message_loader_unref (loader);
06490   loader = NULL;
06491 
06492   /* Write the data all at once */
06493   
06494   loader = _dbus_message_loader_new ();
06495 
06496   {
06497     DBusString *buffer;
06498     
06499     _dbus_message_loader_get_buffer (loader, &buffer);
06500     _dbus_string_copy (data, 0, buffer,
06501                        _dbus_string_get_length (buffer));
06502     _dbus_message_loader_return_buffer (loader, buffer, 1);
06503   }
06504   
06505   if (!check_loader_results (loader, expected_validity))
06506     goto failed;
06507 
06508   _dbus_message_loader_unref (loader);
06509   loader = NULL;  
06510 
06511   /* Write the data 2 bytes at a time */
06512   
06513   loader = _dbus_message_loader_new ();
06514 
06515   len = _dbus_string_get_length (data);
06516   for (i = 0; i < len; i += 2)
06517     {
06518       DBusString *buffer;
06519 
06520       _dbus_message_loader_get_buffer (loader, &buffer);
06521       _dbus_string_append_byte (buffer,
06522                                 _dbus_string_get_byte (data, i));
06523       if ((i+1) < len)
06524         _dbus_string_append_byte (buffer,
06525                                   _dbus_string_get_byte (data, i+1));
06526       _dbus_message_loader_return_buffer (loader, buffer, 1);
06527     }
06528   
06529   if (!check_loader_results (loader, expected_validity))
06530     goto failed;
06531 
06532   _dbus_message_loader_unref (loader);
06533   loader = NULL;
06534   
06535   retval = TRUE;
06536   
06537  failed:
06538   
06539   if (loader)
06540     _dbus_message_loader_unref (loader);
06541   
06542   return retval;
06543 }
06544 
06545 static dbus_bool_t
06546 process_test_subdir (const DBusString          *test_base_dir,
06547                      const char                *subdir,
06548                      DBusMessageValidity        validity,
06549                      DBusForeachMessageFileFunc function,
06550                      void                      *user_data)
06551 {
06552   DBusString test_directory;
06553   DBusString filename;
06554   DBusDirIter *dir;
06555   dbus_bool_t retval;
06556   DBusError error;
06557 
06558   retval = FALSE;
06559   dir = NULL;
06560   
06561   if (!_dbus_string_init (&test_directory))
06562     _dbus_assert_not_reached ("didn't allocate test_directory\n");
06563 
06564   _dbus_string_init_const (&filename, subdir);
06565   
06566   if (!_dbus_string_copy (test_base_dir, 0,
06567                           &test_directory, 0))
06568     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
06569   
06570   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
06571     _dbus_assert_not_reached ("couldn't allocate full path");
06572 
06573   _dbus_string_free (&filename);
06574   if (!_dbus_string_init (&filename))
06575     _dbus_assert_not_reached ("didn't allocate filename string\n");
06576 
06577   dbus_error_init (&error);
06578   dir = _dbus_directory_open (&test_directory, &error);
06579   if (dir == NULL)
06580     {
06581       _dbus_warn ("Could not open %s: %s\n",
06582                   _dbus_string_get_const_data (&test_directory),
06583                   error.message);
06584       dbus_error_free (&error);
06585       goto failed;
06586     }
06587 
06588   printf ("Testing %s:\n", subdir);
06589   
06590  next:
06591   while (_dbus_directory_get_next_file (dir, &filename, &error))
06592     {
06593       DBusString full_path;
06594       dbus_bool_t is_raw;
06595       
06596       if (!_dbus_string_init (&full_path))
06597         _dbus_assert_not_reached ("couldn't init string");
06598 
06599       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
06600         _dbus_assert_not_reached ("couldn't copy dir to full_path");
06601 
06602       if (!_dbus_concat_dir_and_file (&full_path, &filename))
06603         _dbus_assert_not_reached ("couldn't concat file to dir");
06604 
06605       if (_dbus_string_ends_with_c_str (&filename, ".message"))
06606         is_raw = FALSE;
06607       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
06608         is_raw = TRUE;
06609       else
06610         {
06611           _dbus_verbose ("Skipping non-.message file %s\n",
06612                          _dbus_string_get_const_data (&filename));
06613           _dbus_string_free (&full_path);
06614           goto next;
06615         }
06616 
06617       printf ("    %s\n",
06618               _dbus_string_get_const_data (&filename));
06619       
06620       _dbus_verbose (" expecting %s for %s\n",
06621                      validity == _DBUS_MESSAGE_VALID ? "valid" :
06622                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
06623                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
06624                      _dbus_string_get_const_data (&filename));
06625       
06626       if (! (*function) (&full_path, is_raw, validity, user_data))
06627         {
06628           _dbus_string_free (&full_path);
06629           goto failed;
06630         }
06631       else
06632         _dbus_string_free (&full_path);
06633     }
06634 
06635   if (dbus_error_is_set (&error))
06636     {
06637       _dbus_warn ("Could not get next file in %s: %s\n",
06638                   _dbus_string_get_const_data (&test_directory),
06639                   error.message);
06640       dbus_error_free (&error);
06641       goto failed;
06642     }
06643     
06644   retval = TRUE;
06645   
06646  failed:
06647 
06648   if (dir)
06649     _dbus_directory_close (dir);
06650   _dbus_string_free (&test_directory);
06651   _dbus_string_free (&filename);
06652 
06653   return retval;
06654 }
06655                      
06665 dbus_bool_t
06666 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
06667                                                DBusForeachMessageFileFunc func,
06668                                                void                      *user_data)
06669 {
06670   DBusString test_directory;
06671   dbus_bool_t retval;
06672 
06673   retval = FALSE;
06674   
06675   _dbus_string_init_const (&test_directory, test_data_dir);
06676 
06677   if (!process_test_subdir (&test_directory, "valid-messages",
06678                             _DBUS_MESSAGE_VALID, func, user_data))
06679     goto failed;
06680 
06681   if (!process_test_subdir (&test_directory, "invalid-messages",
06682                             _DBUS_MESSAGE_INVALID, func, user_data))
06683     goto failed;
06684   
06685   if (!process_test_subdir (&test_directory, "incomplete-messages",
06686                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
06687     goto failed;
06688 
06689   retval = TRUE;
06690   
06691  failed:
06692 
06693   _dbus_string_free (&test_directory);
06694   
06695   return retval;
06696 }
06697 
06698 static void
06699 verify_test_message (DBusMessage *message)
06700 {
06701   DBusMessageIter iter, dict;
06702   DBusError error;
06703   dbus_int32_t our_int;
06704   char *our_str;
06705   double our_double;
06706   dbus_bool_t our_bool;
06707   dbus_uint32_t our_uint32;
06708   dbus_int32_t *our_uint32_array;
06709   int our_uint32_array_len;
06710   dbus_int32_t *our_int32_array;
06711   int our_int32_array_len;
06712   char **our_string_array;
06713   int our_string_array_len;
06714 #ifdef DBUS_HAVE_INT64
06715   dbus_int64_t our_int64;
06716   dbus_uint64_t our_uint64;
06717   dbus_int64_t *our_uint64_array;
06718   int our_uint64_array_len;
06719   dbus_int64_t *our_int64_array;
06720   int our_int64_array_len;
06721 #endif
06722   double *our_double_array;
06723   int our_double_array_len;
06724   unsigned char *our_byte_array;
06725   int our_byte_array_len;
06726   unsigned char *our_boolean_array;
06727   int our_boolean_array_len;
06728   
06729   dbus_message_iter_init (message, &iter);
06730 
06731   dbus_error_init (&error);
06732   if (!dbus_message_iter_get_args (&iter, &error,
06733                                    DBUS_TYPE_INT32, &our_int,
06734 #ifdef DBUS_HAVE_INT64
06735                                    DBUS_TYPE_INT64, &our_int64,
06736                                    DBUS_TYPE_UINT64, &our_uint64,
06737 #endif
06738                                    DBUS_TYPE_STRING, &our_str,
06739                                    DBUS_TYPE_DOUBLE, &our_double,
06740                                    DBUS_TYPE_BOOLEAN, &our_bool,
06741                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
06742                                    &our_uint32_array, &our_uint32_array_len,
06743                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
06744                                    &our_int32_array, &our_int32_array_len,
06745 #ifdef DBUS_HAVE_INT64
06746                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
06747                                    &our_uint64_array, &our_uint64_array_len,
06748                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
06749                                    &our_int64_array, &our_int64_array_len,
06750 #endif
06751                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
06752                                    &our_string_array, &our_string_array_len,
06753                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
06754                                    &our_double_array, &our_double_array_len,
06755                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
06756                                    &our_byte_array, &our_byte_array_len,
06757                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
06758                                    &our_boolean_array, &our_boolean_array_len,
06759                                    0))
06760     {
06761       _dbus_warn ("error: %s - %s\n", error.name,
06762                   (error.message != NULL) ? error.message : "no message");
06763       _dbus_assert_not_reached ("Could not get arguments");
06764     }
06765 
06766   if (our_int != -0x12345678)
06767     _dbus_assert_not_reached ("integers differ!");
06768 
06769 #ifdef DBUS_HAVE_INT64
06770   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
06771     _dbus_assert_not_reached ("64-bit integers differ!");
06772   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
06773     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
06774 #endif
06775   
06776   if (our_double != 3.14159)
06777     _dbus_assert_not_reached ("doubles differ!");
06778 
06779   if (strcmp (our_str, "Test string") != 0)
06780     _dbus_assert_not_reached ("strings differ!");
06781   dbus_free (our_str);
06782 
06783   if (!our_bool)
06784     _dbus_assert_not_reached ("booleans differ");
06785 
06786   if (our_uint32_array_len != 4 ||
06787       our_uint32_array[0] != 0x12345678 ||
06788       our_uint32_array[1] != 0x23456781 ||
06789       our_uint32_array[2] != 0x34567812 ||
06790       our_uint32_array[3] != 0x45678123)
06791     _dbus_assert_not_reached ("uint array differs");
06792   dbus_free (our_uint32_array);
06793 
06794   if (our_int32_array_len != 4 ||
06795       our_int32_array[0] != 0x12345678 ||
06796       our_int32_array[1] != -0x23456781 ||
06797       our_int32_array[2] != 0x34567812 ||
06798       our_int32_array[3] != -0x45678123)
06799     _dbus_assert_not_reached ("int array differs");
06800   dbus_free (our_int32_array);
06801 
06802 #ifdef DBUS_HAVE_INT64
06803   if (our_uint64_array_len != 4 ||
06804       our_uint64_array[0] != 0x12345678 ||
06805       our_uint64_array[1] != 0x23456781 ||
06806       our_uint64_array[2] != 0x34567812 ||
06807       our_uint64_array[3] != 0x45678123)
06808     _dbus_assert_not_reached ("uint64 array differs");
06809   dbus_free (our_uint64_array);
06810   
06811   if (our_int64_array_len != 4 ||
06812       our_int64_array[0] != 0x12345678 ||
06813       our_int64_array[1] != -0x23456781 ||
06814       our_int64_array[2] != 0x34567812 ||
06815       our_int64_array[3] != -0x45678123)
06816     _dbus_assert_not_reached ("int64 array differs");
06817   dbus_free (our_int64_array);
06818 #endif /* DBUS_HAVE_INT64 */
06819   
06820   if (our_string_array_len != 4)
06821     _dbus_assert_not_reached ("string array has wrong length");
06822 
06823   if (strcmp (our_string_array[0], "Foo") != 0 ||
06824       strcmp (our_string_array[1], "bar") != 0 ||
06825       strcmp (our_string_array[2], "") != 0 ||
06826       strcmp (our_string_array[3], "woo woo woo woo") != 0)
06827     _dbus_assert_not_reached ("string array differs");
06828 
06829   dbus_free_string_array (our_string_array);
06830 
06831   if (our_double_array_len != 3)
06832     _dbus_assert_not_reached ("double array had wrong length");
06833 
06834   /* On all IEEE machines (i.e. everything sane) exact equality
06835    * should be preserved over the wire
06836    */
06837   if (our_double_array[0] != 0.1234 ||
06838       our_double_array[1] != 9876.54321 ||
06839       our_double_array[2] != -300.0)
06840     _dbus_assert_not_reached ("double array had wrong values");
06841 
06842   dbus_free (our_double_array);
06843 
06844   if (our_byte_array_len != 4)
06845     _dbus_assert_not_reached ("byte array had wrong length");
06846 
06847   if (our_byte_array[0] != 'a' ||
06848       our_byte_array[1] != 'b' ||
06849       our_byte_array[2] != 'c' ||
06850       our_byte_array[3] != 234)
06851     _dbus_assert_not_reached ("byte array had wrong values");
06852 
06853   dbus_free (our_byte_array);
06854 
06855   if (our_boolean_array_len != 5)
06856     _dbus_assert_not_reached ("bool array had wrong length");
06857 
06858   if (our_boolean_array[0] != TRUE ||
06859       our_boolean_array[1] != FALSE ||
06860       our_boolean_array[2] != TRUE ||
06861       our_boolean_array[3] != TRUE ||
06862       our_boolean_array[4] != FALSE)
06863     _dbus_assert_not_reached ("bool array had wrong values");
06864 
06865   dbus_free (our_boolean_array);
06866   
06867   if (!dbus_message_iter_next (&iter))
06868     _dbus_assert_not_reached ("Reached end of arguments");
06869 
06870   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
06871     _dbus_assert_not_reached ("not dict type");
06872      
06873   dbus_message_iter_init_dict_iterator (&iter, &dict);
06874 
06875   our_str = dbus_message_iter_get_dict_key (&dict);
06876   if (our_str == NULL || strcmp (our_str, "test") != 0)
06877     _dbus_assert_not_reached ("wrong dict key");
06878   dbus_free (our_str);
06879 
06880   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
06881     {
06882       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
06883       _dbus_assert_not_reached ("wrong dict entry type");
06884     }
06885 
06886   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
06887     {
06888       _dbus_verbose ("dict entry val: %x\n", our_uint32);
06889       _dbus_assert_not_reached ("wrong dict entry value");
06890     }
06891 
06892   if (dbus_message_iter_next (&dict))
06893     _dbus_assert_not_reached ("Didn't reach end of dict");
06894   
06895   if (!dbus_message_iter_next (&iter))
06896     _dbus_assert_not_reached ("Reached end of arguments");
06897   
06898   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
06899     _dbus_assert_not_reached ("wrong type after dict");
06900   
06901   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
06902     _dbus_assert_not_reached ("wrong value after dict");
06903 
06904   if (dbus_message_iter_next (&iter))
06905     _dbus_assert_not_reached ("Didn't reach end of arguments");
06906 }
06907 
06914 dbus_bool_t
06915 _dbus_message_test (const char *test_data_dir)
06916 {
06917   DBusMessage *message;
06918   DBusMessageLoader *loader;
06919   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
06920   int i;
06921   const char *data;
06922   DBusMessage *copy;
06923   const char *name1;
06924   const char *name2;
06925   const dbus_uint32_t our_uint32_array[] =
06926     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
06927   const dbus_uint32_t our_int32_array[] =
06928     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
06929 #ifdef DBUS_HAVE_INT64
06930   const dbus_uint64_t our_uint64_array[] =
06931     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
06932   const dbus_uint64_t our_int64_array[] =
06933     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
06934 #endif
06935   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
06936   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
06937   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
06938   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
06939   char sig[64];
06940   const char *s;
06941   char *t;
06942   DBusError error;
06943   
06944   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
06945 
06946   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
06947                                           "/org/freedesktop/TestPath",
06948                                           "Foo.TestInterface",
06949                                           "TestMethod");
06950   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
06951   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
06952                                              "TestMethod"));
06953   _dbus_assert (strcmp (dbus_message_get_path (message),
06954                         "/org/freedesktop/TestPath") == 0);
06955   _dbus_message_set_serial (message, 1234);
06956   /* string length including nul byte not a multiple of 4 */
06957   if (!dbus_message_set_sender (message, "org.foo.bar1"))
06958     _dbus_assert_not_reached ("out of memory");
06959   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
06960   dbus_message_set_reply_serial (message, 5678);
06961   if (!dbus_message_set_sender (message, NULL))
06962     _dbus_assert_not_reached ("out of memory");
06963   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
06964   _dbus_assert (dbus_message_get_serial (message) == 1234);
06965   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
06966   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
06967 
06968   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
06969   dbus_message_set_no_reply (message, TRUE);
06970   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
06971   dbus_message_set_no_reply (message, FALSE);
06972   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
06973 
06974   /* Set/get some header fields */
06975   
06976   if (!dbus_message_set_path (message, "/foo"))
06977     _dbus_assert_not_reached ("out of memory");
06978   _dbus_assert (strcmp (dbus_message_get_path (message),
06979                         "/foo") == 0);
06980 
06981   if (!dbus_message_set_interface (message, "org.Foo"))
06982     _dbus_assert_not_reached ("out of memory");
06983   _dbus_assert (strcmp (dbus_message_get_interface (message),
06984                         "org.Foo") == 0);
06985   
06986   if (!dbus_message_set_member (message, "Bar"))
06987     _dbus_assert_not_reached ("out of memory");
06988   _dbus_assert (strcmp (dbus_message_get_member (message),
06989                         "Bar") == 0);
06990 
06991   /* Set/get them with longer values */
06992   if (!dbus_message_set_path (message, "/foo/bar"))
06993     _dbus_assert_not_reached ("out of memory");
06994   _dbus_assert (strcmp (dbus_message_get_path (message),
06995                         "/foo/bar") == 0);
06996 
06997   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
06998     _dbus_assert_not_reached ("out of memory");
06999   _dbus_assert (strcmp (dbus_message_get_interface (message),
07000                         "org.Foo.Bar") == 0);
07001   
07002   if (!dbus_message_set_member (message, "BarFoo"))
07003     _dbus_assert_not_reached ("out of memory");
07004   _dbus_assert (strcmp (dbus_message_get_member (message),
07005                         "BarFoo") == 0);
07006 
07007   /* Realloc shorter again */
07008   
07009   if (!dbus_message_set_path (message, "/foo"))
07010     _dbus_assert_not_reached ("out of memory");
07011   _dbus_assert (strcmp (dbus_message_get_path (message),
07012                         "/foo") == 0);
07013 
07014   if (!dbus_message_set_interface (message, "org.Foo"))
07015     _dbus_assert_not_reached ("out of memory");
07016   _dbus_assert (strcmp (dbus_message_get_interface (message),
07017                         "org.Foo") == 0);
07018   
07019   if (!dbus_message_set_member (message, "Bar"))
07020     _dbus_assert_not_reached ("out of memory");
07021   _dbus_assert (strcmp (dbus_message_get_member (message),
07022                         "Bar") == 0);
07023   
07024   dbus_message_unref (message);
07025   
07026   /* Test the vararg functions */
07027   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07028                                           "/org/freedesktop/TestPath",
07029                                           "Foo.TestInterface",
07030                                           "TestMethod");
07031   _dbus_message_set_serial (message, 1);
07032   dbus_message_append_args (message,
07033                             DBUS_TYPE_INT32, -0x12345678,
07034 #ifdef DBUS_HAVE_INT64
07035                             DBUS_TYPE_INT64, DBUS_INT64_CONSTANT (-0x123456789abcd),
07036                             DBUS_TYPE_UINT64, DBUS_UINT64_CONSTANT (0x123456789abcd),
07037 #endif
07038                             DBUS_TYPE_STRING, "Test string",
07039                             DBUS_TYPE_DOUBLE, 3.14159,
07040                             DBUS_TYPE_BOOLEAN, TRUE,
07041                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
07042                             _DBUS_N_ELEMENTS (our_uint32_array),
07043                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
07044                             _DBUS_N_ELEMENTS (our_int32_array),
07045 #ifdef DBUS_HAVE_INT64
07046                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
07047                             _DBUS_N_ELEMENTS (our_uint64_array),
07048                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
07049                             _DBUS_N_ELEMENTS (our_int64_array),
07050 #endif
07051                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
07052                             _DBUS_N_ELEMENTS (our_string_array),
07053                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
07054                             _DBUS_N_ELEMENTS (our_double_array),
07055                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
07056                             _DBUS_N_ELEMENTS (our_byte_array),
07057                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
07058                             _DBUS_N_ELEMENTS (our_boolean_array),
07059                             0);
07060   
07061   dbus_message_append_iter_init (message, &iter);
07062   dbus_message_iter_append_dict (&iter, &child_iter);
07063   dbus_message_iter_append_dict_key (&child_iter, "test");
07064   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07065   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
07066 
07067   i = 0;
07068   sig[i++] = DBUS_TYPE_INT32;
07069 #ifdef DBUS_HAVE_INT64
07070   sig[i++] = DBUS_TYPE_INT64;
07071   sig[i++] = DBUS_TYPE_UINT64;
07072 #endif
07073   sig[i++] = DBUS_TYPE_STRING;
07074   sig[i++] = DBUS_TYPE_DOUBLE;
07075   sig[i++] = DBUS_TYPE_BOOLEAN;
07076   sig[i++] = DBUS_TYPE_ARRAY;
07077   sig[i++] = DBUS_TYPE_UINT32;
07078   sig[i++] = DBUS_TYPE_ARRAY;
07079   sig[i++] = DBUS_TYPE_INT32;
07080 #ifdef DBUS_HAVE_INT64
07081   sig[i++] = DBUS_TYPE_ARRAY;
07082   sig[i++] = DBUS_TYPE_UINT64;
07083   sig[i++] = DBUS_TYPE_ARRAY;
07084   sig[i++] = DBUS_TYPE_INT64;
07085 #endif
07086   sig[i++] = DBUS_TYPE_ARRAY;
07087   sig[i++] = DBUS_TYPE_STRING;
07088   sig[i++] = DBUS_TYPE_ARRAY;
07089   sig[i++] = DBUS_TYPE_DOUBLE;
07090   sig[i++] = DBUS_TYPE_ARRAY;
07091   sig[i++] = DBUS_TYPE_BYTE;
07092   sig[i++] = DBUS_TYPE_ARRAY;
07093   sig[i++] = DBUS_TYPE_BOOLEAN;
07094   sig[i++] = DBUS_TYPE_DICT;
07095   sig[i++] = DBUS_TYPE_UINT32;
07096   sig[i++] = DBUS_TYPE_INVALID;
07097 
07098   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
07099   
07100   _dbus_verbose_bytes_of_string (&message->header, 0,
07101                                  _dbus_string_get_length (&message->header));
07102   _dbus_verbose_bytes_of_string (&message->body, 0,
07103                                  _dbus_string_get_length (&message->body));
07104   
07105   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
07106                  sig, dbus_message_get_signature (message));
07107   
07108   s = dbus_message_get_signature (message);
07109   
07110   _dbus_assert (dbus_message_has_signature (message, sig));
07111   _dbus_assert (strcmp (s, sig) == 0);
07112   
07113   verify_test_message (message);
07114 
07115   copy = dbus_message_copy (message);
07116   
07117   _dbus_assert (message->client_serial == copy->client_serial);
07118   _dbus_assert (message->reply_serial == copy->reply_serial);
07119   _dbus_assert (message->header_padding == copy->header_padding);
07120   
07121   _dbus_assert (_dbus_string_get_length (&message->header) ==
07122                 _dbus_string_get_length (&copy->header));
07123 
07124   _dbus_assert (_dbus_string_get_length (&message->body) ==
07125                 _dbus_string_get_length (&copy->body));
07126 
07127   _dbus_assert (_dbus_string_get_length (&message->signature) ==
07128                 _dbus_string_get_length (&copy->signature));
07129   
07130   verify_test_message (copy);
07131 
07132   name1 = dbus_message_get_interface (message);
07133   name2 = dbus_message_get_interface (copy);
07134 
07135   _dbus_assert (strcmp (name1, name2) == 0);
07136 
07137   name1 = dbus_message_get_member (message);
07138   name2 = dbus_message_get_member (copy);
07139 
07140   _dbus_assert (strcmp (name1, name2) == 0);
07141   
07142   dbus_message_unref (message);  
07143   dbus_message_unref (copy);
07144 
07145   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07146                                           "/org/freedesktop/TestPath",
07147                                           "Foo.TestInterface",
07148                                           "TestMethod");
07149 
07150   _dbus_message_set_serial (message, 1);
07151   dbus_message_set_reply_serial (message, 0x12345678);
07152 
07153   dbus_message_append_iter_init (message, &iter);
07154   dbus_message_iter_append_string (&iter, "Test string");
07155   dbus_message_iter_append_int32 (&iter, -0x12345678);
07156   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
07157   dbus_message_iter_append_double (&iter, 3.14159);
07158 
07159   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
07160   dbus_message_iter_append_double (&child_iter, 1.5);
07161   dbus_message_iter_append_double (&child_iter, 2.5);
07162 
07163   /* dict */
07164   dbus_message_iter_append_dict (&iter, &child_iter);
07165   dbus_message_iter_append_dict_key (&child_iter, "test");
07166   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07167 
07168   /* dict (in dict) */
07169   dbus_message_iter_append_dict_key (&child_iter, "testdict");
07170   dbus_message_iter_append_dict (&child_iter, &child_iter2);
07171 
07172   dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
07173   dbus_message_iter_append_string (&child_iter2, "dictvalue");
07174 
07175   /* array of array of int32  (in dict) */
07176   dbus_message_iter_append_dict_key (&child_iter, "array");
07177   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
07178   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07179   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
07180   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
07181   _dbus_warn ("next call expected to fail with wrong array type\n");
07182   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
07183   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07184   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
07185   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
07186   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
07187   
07188   dbus_message_iter_append_byte (&iter, 0xF0);
07189 
07190   dbus_message_iter_append_nil (&iter);
07191 
07192   dbus_message_iter_append_custom (&iter, "MyTypeName",
07193                                    "data", 5);
07194   
07195   dbus_message_iter_append_byte (&iter, 0xF0);
07196 
07197   message_iter_test (message);
07198   
07199   /* Message loader test */
07200   _dbus_message_lock (message);
07201   loader = _dbus_message_loader_new ();
07202 
07203   /* check ref/unref */
07204   _dbus_message_loader_ref (loader);
07205   _dbus_message_loader_unref (loader);
07206   
07207   /* Write the header data one byte at a time */
07208   data = _dbus_string_get_const_data (&message->header);
07209   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
07210     {
07211       DBusString *buffer;
07212 
07213       _dbus_message_loader_get_buffer (loader, &buffer);
07214       _dbus_string_append_byte (buffer, data[i]);
07215       _dbus_message_loader_return_buffer (loader, buffer, 1);
07216     }
07217 
07218   /* Write the body data one byte at a time */
07219   data = _dbus_string_get_const_data (&message->body);
07220   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
07221     {
07222       DBusString *buffer;
07223 
07224       _dbus_message_loader_get_buffer (loader, &buffer);
07225       _dbus_string_append_byte (buffer, data[i]);
07226       _dbus_message_loader_return_buffer (loader, buffer, 1);
07227     }
07228 
07229   copy = dbus_message_copy (message); /* save for tests below */
07230   dbus_message_unref (message);
07231 
07232   /* Now pop back the message */
07233   if (!_dbus_message_loader_queue_messages (loader))
07234     _dbus_assert_not_reached ("no memory to queue messages");
07235   
07236   if (_dbus_message_loader_get_is_corrupted (loader))
07237     _dbus_assert_not_reached ("message loader corrupted");
07238   
07239   message = _dbus_message_loader_pop_message (loader);
07240   if (!message)
07241     _dbus_assert_not_reached ("received a NULL message");
07242 
07243   if (dbus_message_get_reply_serial (message) != 0x12345678)
07244     _dbus_assert_not_reached ("reply serial fields differ");
07245   
07246   message_iter_test (message);
07247   
07248   dbus_message_unref (message);
07249   _dbus_message_loader_unref (loader);
07250 
07251   message = dbus_message_new_method_return (copy);
07252   if (message == NULL)
07253     _dbus_assert_not_reached ("out of memory\n");
07254   dbus_message_unref (copy);
07255 
07256   if (!dbus_message_append_args (message,
07257                                  DBUS_TYPE_STRING, "hello",
07258                                  DBUS_TYPE_INVALID))
07259     _dbus_assert_not_reached ("no memory");
07260 
07261   if (!dbus_message_has_signature (message, "s"))
07262     _dbus_assert_not_reached ("method return has wrong signature");
07263 
07264   dbus_error_init (&error);
07265   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
07266                               &t, DBUS_TYPE_INVALID))
07267     
07268     {
07269       _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
07270       exit (1);
07271     }
07272   dbus_free (t);
07273   
07274   dbus_message_unref (message);
07275   
07276   /* Now load every message in test_data_dir if we have one */
07277   if (test_data_dir == NULL)
07278     return TRUE;
07279 
07280   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
07281                                                         (DBusForeachMessageFileFunc)
07282                                                         dbus_internal_do_not_use_try_message_file,
07283                                                         NULL);
07284 }
07285 
07286 #endif /* DBUS_BUILD_TESTS */

Generated on Sun Mar 21 03:52:05 2004 for D-BUS by doxygen 1.3.6-20040222