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, 2004  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-marshal.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;   
00107 };
00108 
00109 enum {
00110   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
00111   DBUS_MESSAGE_ITER_TYPE_ARRAY,
00112   DBUS_MESSAGE_ITER_TYPE_DICT
00113 };
00114 
00116 typedef struct DBusMessageRealIter DBusMessageRealIter;
00117 
00123 struct DBusMessageRealIter
00124 {
00125   DBusMessageRealIter *parent_iter; 
00126   DBusMessage *message; 
00127   dbus_uint32_t changed_stamp; 
00129   /* This is an int instead of an enum to get a guaranteed size for the dummy: */
00130   int type; 
00132   int pos; 
00133   int end; 
00134   int container_start; 
00135   int container_length_pos; 
00137   int wrote_dict_key; 
00139   int array_type_pos; 
00140   int array_type_done; 
00141 };
00142 
00153 void
00154 _dbus_message_get_network_data (DBusMessage          *message,
00155                                 const DBusString    **header,
00156                                 const DBusString    **body)
00157 {
00158   _dbus_assert (message->locked);
00159   
00160   *header = &message->header;
00161   *body = &message->body;
00162 }
00163 
00164 static void
00165 clear_header_padding (DBusMessage *message)
00166 {
00167   _dbus_string_shorten (&message->header,
00168                         message->header_padding);
00169   message->header_padding = 0;
00170 }              
00171 
00172 #ifdef DBUS_DISABLE_CHECKS
00173 #define is_valid_error_name(x) TRUE
00174 #else
00175 static dbus_bool_t
00176 is_valid_error_name (const char *error_name)                                          
00177 {
00178   DBusString the_error_name;
00179 
00180   if (error_name == NULL)
00181     return FALSE;
00182   
00183   _dbus_string_init_const (&the_error_name, error_name);
00184   return _dbus_string_validate_error_name (&the_error_name, 0,   
00185                                            _dbus_string_get_length (&the_error_name));
00186 }
00187 #endif
00188 
00189 static dbus_bool_t
00190 append_header_padding (DBusMessage *message)
00191 {
00192   int old_len;
00193   old_len = _dbus_string_get_length (&message->header);
00194   if (!_dbus_string_align_length (&message->header, 8))
00195     return FALSE;
00196 
00197   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
00198 
00199   return TRUE;
00200 }
00201 
00202 #ifdef DBUS_BUILD_TESTS
00203 /* tests-only until it's actually used */
00204 static dbus_int32_t
00205 get_int_field (DBusMessage *message,
00206                int          field)
00207 {
00208   int offset;
00209 
00210   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00211   
00212   offset = message->header_fields[field].value_offset;
00213   
00214   if (offset < 0)
00215     return -1; /* useless if -1 is a valid value of course */
00216   
00217   return _dbus_demarshal_int32 (&message->header,
00218                                 message->byte_order,
00219                                 offset,
00220                                 NULL);
00221 }
00222 #endif
00223 
00224 static dbus_uint32_t
00225 get_uint_field (DBusMessage *message,
00226                 int          field)
00227 {
00228   int offset;
00229   
00230   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00231   
00232   offset = message->header_fields[field].value_offset;
00233   
00234   if (offset < 0)
00235     return 0; /* useless if 0 is a valid value of course */
00236   
00237   return _dbus_demarshal_uint32 (&message->header,
00238                                  message->byte_order,
00239                                  offset,
00240                                  NULL);
00241 }
00242 
00243 static const char*
00244 get_string_field (DBusMessage *message,
00245                   int          field,
00246                   int         *len)
00247 {
00248   int offset;
00249   const char *data;
00250 
00251   offset = message->header_fields[field].value_offset;
00252 
00253   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00254   
00255   if (offset < 0)
00256     return NULL;
00257 
00258   /* offset points to string length, string data follows it */
00259   /* FIXME _dbus_demarshal_const_string() that returned
00260    * a reference to the string plus its len might be nice.
00261    */
00262   
00263   if (len)
00264     *len = _dbus_demarshal_uint32 (&message->header,
00265                                    message->byte_order,
00266                                    offset,
00267                                    NULL);
00268 
00269   data = _dbus_string_get_const_data (&message->header);
00270   
00271   return data + (offset + 4); 
00272 }
00273 
00274 /* returns FALSE if no memory, TRUE with NULL path if no field */
00275 static dbus_bool_t
00276 get_path_field_decomposed (DBusMessage  *message,
00277                            int           field,
00278                            char       ***path)
00279 {
00280   int offset;
00281 
00282   offset = message->header_fields[field].value_offset;
00283 
00284   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00285   
00286   if (offset < 0)
00287     {
00288       *path = NULL;
00289       return TRUE;
00290     }
00291 
00292   return _dbus_demarshal_object_path (&message->header,
00293                                       message->byte_order,
00294                                       offset,
00295                                       NULL,
00296                                       path, NULL);
00297 }
00298 
00299 #ifdef DBUS_BUILD_TESTS
00300 static dbus_bool_t
00301 append_int_field (DBusMessage *message,
00302                   int          field,
00303                   int          value)
00304 {
00305   _dbus_assert (!message->locked);
00306 
00307   clear_header_padding (message);
00308   
00309   message->header_fields[field].name_offset =
00310     _dbus_string_get_length (&message->header);
00311   
00312   if (!_dbus_string_append_byte (&message->header, field))
00313     goto failed;
00314 
00315   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
00316     goto failed;
00317 
00318   if (!_dbus_string_align_length (&message->header, 4))
00319     goto failed;
00320   
00321   message->header_fields[field].value_offset =
00322     _dbus_string_get_length (&message->header);
00323   
00324   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
00325                             value))
00326     goto failed;
00327 
00328   if (!append_header_padding (message))
00329     goto failed;
00330   
00331   return TRUE;
00332   
00333  failed:
00334   _dbus_string_set_length (&message->header,
00335                            message->header_fields[field].name_offset);
00336   message->header_fields[field].name_offset  = -1;
00337   message->header_fields[field].value_offset = -1;
00338 
00339   /* this must succeed because it was allocated on function entry and
00340    * DBusString doesn't ever realloc smaller
00341    */
00342   if (!append_header_padding (message))
00343     _dbus_assert_not_reached ("failed to reappend header padding");
00344   return FALSE;
00345 }
00346 #endif
00347 
00348 static dbus_bool_t
00349 append_uint_field (DBusMessage *message,
00350                    int          field,
00351                    int          value)
00352 {
00353   _dbus_assert (!message->locked);
00354 
00355   clear_header_padding (message);
00356   
00357   message->header_fields[field].name_offset =
00358     _dbus_string_get_length (&message->header);
00359   
00360   if (!_dbus_string_append_byte (&message->header, field))
00361     goto failed;
00362 
00363   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_UINT32))
00364     goto failed;
00365 
00366   if (!_dbus_string_align_length (&message->header, 4))
00367     goto failed;
00368   
00369   message->header_fields[field].value_offset =
00370     _dbus_string_get_length (&message->header);
00371   
00372   if (!_dbus_marshal_uint32 (&message->header, message->byte_order,
00373                              value))
00374     goto failed;
00375 
00376   if (!append_header_padding (message))
00377     goto failed;
00378   
00379   return TRUE;
00380   
00381  failed:
00382   _dbus_string_set_length (&message->header,
00383                            message->header_fields[field].name_offset);
00384   message->header_fields[field].name_offset  = -1;
00385   message->header_fields[field].value_offset = -1;
00386 
00387   /* this must succeed because it was allocated on function entry and
00388    * DBusString doesn't ever realloc smaller
00389    */
00390   if (!append_header_padding (message))
00391     _dbus_assert_not_reached ("failed to reappend header padding");
00392   return FALSE;
00393 }
00394 
00398 #define MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING (1 + 1 + 3 + 4 + 1 + 8)
00399 
00400 static dbus_bool_t
00401 append_string_field_len (DBusMessage *message,
00402                          int          field,
00403                          int          type,
00404                          const char  *value,
00405                          int          value_len)
00406 {
00407   _dbus_assert (!message->locked);
00408 
00409   clear_header_padding (message);
00410   
00411   message->header_fields[field].name_offset =
00412     _dbus_string_get_length (&message->header);
00413   
00414   if (!_dbus_string_append_byte (&message->header, field))
00415     goto failed;
00416   
00417   if (!_dbus_string_append_byte (&message->header, type))
00418     goto failed;
00419 
00420   if (!_dbus_string_align_length (&message->header, 4))
00421     goto failed;
00422   
00423   message->header_fields[field].value_offset =
00424     _dbus_string_get_length (&message->header);
00425   
00426   if (!_dbus_marshal_string_len (&message->header, message->byte_order,
00427                                  value, value_len))
00428     goto failed;
00429 
00430   if (!append_header_padding (message))
00431     goto failed;
00432   
00433   return TRUE;
00434   
00435  failed:
00436   _dbus_string_set_length (&message->header,
00437                            message->header_fields[field].name_offset);
00438   message->header_fields[field].name_offset  = -1;
00439   message->header_fields[field].value_offset = -1;
00440 
00441   /* this must succeed because it was allocated on function entry and
00442    * DBusString doesn't ever realloc smaller
00443    */
00444   if (!append_header_padding (message))
00445     _dbus_assert_not_reached ("failed to reappend header padding");
00446   
00447   return FALSE;
00448 }
00449 
00450 static dbus_bool_t
00451 append_string_field (DBusMessage *message,
00452                      int          field,
00453                      int          type,
00454                      const char  *value)
00455 {
00456   int value_len;
00457 
00458   value_len = strlen (value);
00459 
00460   return append_string_field_len (message, field, type, value, value_len);
00461 }
00462 
00463 static int
00464 get_type_alignment (int type)
00465 {
00466   int alignment;
00467   
00468   switch (type)
00469     {
00470     case DBUS_TYPE_NIL:
00471     case DBUS_TYPE_BYTE:
00472     case DBUS_TYPE_BOOLEAN:
00473       alignment = 0;
00474       break;
00475 
00476     case DBUS_TYPE_INT32:
00477     case DBUS_TYPE_UINT32:
00478     case DBUS_TYPE_STRING:
00479     case DBUS_TYPE_OBJECT_PATH:
00480       /* These are aligned 4 because they have a length as the
00481        * first field;
00482        */
00483     case DBUS_TYPE_CUSTOM:
00484     case DBUS_TYPE_DICT:
00485       alignment = 4;
00486       break;
00487 
00488     case DBUS_TYPE_INT64:
00489     case DBUS_TYPE_UINT64:
00490     case DBUS_TYPE_DOUBLE:
00491       alignment = 8;
00492       break;
00493 
00494     case DBUS_TYPE_ARRAY:
00495       _dbus_assert_not_reached ("passed an ARRAY type to get_type_alignment()");
00496       break;
00497 
00498     case DBUS_TYPE_INVALID:
00499     default:
00500       _dbus_assert_not_reached ("passed an invalid or unknown type to get_type_alignment()");
00501       break;
00502     }
00503 
00504   return alignment;
00505 }
00506 
00507 static dbus_bool_t
00508 iterate_one_field (const DBusString *str,
00509                    int               byte_order,
00510                    int               name_offset,
00511                    int              *next_offset_p,
00512                    int              *field_name_p,
00513                    DBusString       *append_copy_to,
00514                    int              *copy_name_offset_p,
00515                    int              *copy_value_offset_p)
00516 {
00517   int name, type, array_type;
00518   int alignment;
00519   int type_len;
00520   int type_pos;
00521   int value_pos;
00522   int value_len;
00523   int value_end;
00524   int pos;
00525 
00526   _dbus_verbose ("%s: name_offset=%d, append to %p\n",
00527                  _DBUS_FUNCTION_NAME, name_offset, append_copy_to);
00528   
00529   pos = name_offset;
00530   
00531   name = _dbus_string_get_byte (str, name_offset);
00532   pos++;
00533 
00534   type_pos = pos;
00535   type = _dbus_string_get_byte (str, type_pos);
00536   pos++;
00537   type_len = 1;
00538 
00539   array_type = type;
00540   /* find out the type of our array */
00541   while (array_type == DBUS_TYPE_ARRAY)
00542     {
00543       pos++;
00544       type_len++;
00545       array_type = _dbus_string_get_byte (str, pos);
00546     }
00547 
00548   _dbus_verbose ("%s: name %d, type '%c' %d at %d len %d, array type '%c' %d\n",
00549                  _DBUS_FUNCTION_NAME,
00550                  name, type, type, type_pos, type_len, array_type, array_type);
00551   
00552 #ifndef DBUS_DISABLE_ASSERT
00553   if (!_dbus_type_is_valid (array_type))
00554     {
00555       _dbus_warn ("type '%c' %d is not valid in %s\n",
00556                   array_type, array_type, _DBUS_FUNCTION_NAME);
00557       _dbus_assert_not_reached ("invalid type");
00558     }
00559 #endif
00560       
00561   alignment = get_type_alignment (array_type);
00562       
00563   if (alignment > 0)
00564     pos = _DBUS_ALIGN_VALUE (pos, alignment);
00565 
00566   _dbus_verbose ("%s: alignment %d value at pos %d\n",
00567                  _DBUS_FUNCTION_NAME, alignment, pos);
00568   
00569   /* pos now points to our value */
00570   if (!_dbus_marshal_get_arg_end_pos (str, byte_order,
00571                                       type, pos, &value_end))
00572     _dbus_assert_not_reached ("failed to get the byte after this header");
00573 
00574   value_pos = pos;
00575   value_len = value_end - value_pos;
00576 
00577   _dbus_verbose ("%s: value_pos %d value_len %d value_end %d\n",
00578                  _DBUS_FUNCTION_NAME, value_pos, value_len, value_end);
00579   
00580   if (next_offset_p)
00581     *next_offset_p = pos + value_len;
00582 
00583   if (field_name_p)
00584     *field_name_p = name;
00585 
00586   if (append_copy_to)
00587     {
00588       int orig_len;
00589 
00590       orig_len = _dbus_string_get_length (append_copy_to);
00591 
00592       if (copy_name_offset_p)
00593         *copy_name_offset_p = orig_len;
00594       
00595       if (!_dbus_string_append_byte (append_copy_to, name))
00596         goto failed_copy;
00597 
00598       if (!_dbus_string_copy_len (str, type_pos, type_len,
00599                                   append_copy_to,
00600                                   _dbus_string_get_length (append_copy_to)))
00601         goto failed_copy;
00602 
00603       if (!_dbus_string_align_length (append_copy_to, alignment))
00604         goto failed_copy;
00605 
00606       if (copy_value_offset_p)
00607         *copy_value_offset_p = _dbus_string_get_length (append_copy_to);
00608       
00609       if (!_dbus_string_copy_len (str, value_pos, value_len,
00610                                   append_copy_to,
00611                                   _dbus_string_get_length (append_copy_to)))
00612         goto failed_copy;
00613       
00614       return TRUE;
00615 
00616     failed_copy:
00617       _dbus_verbose ("%s: Failed copying old fields to new string\n",
00618                      _DBUS_FUNCTION_NAME);
00619       _dbus_string_set_length (append_copy_to, orig_len);
00620       return FALSE;
00621     }
00622   else
00623     return TRUE;
00624 }
00625 
00626 #ifndef DBUS_DISABLE_ASSERT
00627 static void
00628 verify_header_fields (DBusMessage *message)
00629 {
00630   int i;
00631   i = 0;
00632   while (i < DBUS_HEADER_FIELD_LAST)
00633     {
00634       if (message->header_fields[i].name_offset >= 0)
00635         _dbus_assert (_dbus_string_get_byte (&message->header,
00636                                              message->header_fields[i].name_offset) ==
00637                       i);
00638       ++i;
00639     }
00640 }
00641 #else /* DBUS_DISABLE_ASSERT */
00642 #define verify_header_fields(x)
00643 #endif /* DBUS_DISABLE_ASSERT */
00644 
00645 /* In this function we delete one field and re-align all the fields
00646  * following it.
00647  */
00648 static dbus_bool_t
00649 delete_one_and_re_align (DBusMessage *message,
00650                          int          name_offset_to_delete)
00651 {
00652   DBusString copy;
00653   int new_fields_front_padding;
00654   int next_offset;
00655   int field_name;
00656   dbus_bool_t retval;
00657   HeaderField new_header_fields[DBUS_HEADER_FIELD_LAST];
00658   
00659   _dbus_assert (name_offset_to_delete < _dbus_string_get_length (&message->header));
00660   verify_header_fields (message);
00661 
00662   _dbus_verbose ("%s: Deleting one field at offset %d\n",
00663                  _DBUS_FUNCTION_NAME,
00664                  name_offset_to_delete);
00665   
00666   retval = FALSE;
00667 
00668   clear_header_padding (message);
00669   
00670   if (!_dbus_string_init_preallocated (&copy,
00671                                        _dbus_string_get_length (&message->header) -
00672                                        name_offset_to_delete + 8))
00673     {
00674       _dbus_verbose ("%s: Failed to init string to hold copy of fields\n",
00675                      _DBUS_FUNCTION_NAME);
00676       goto out_0;
00677     }
00678   
00679   /* Align the name offset of the first field in the same way it's
00680    * aligned in the real header
00681    */
00682   new_fields_front_padding = name_offset_to_delete % 8;
00683 
00684   if (!_dbus_string_insert_bytes (&copy, 0, new_fields_front_padding,
00685                                   '\0'))
00686     _dbus_assert_not_reached ("Should not have failed to insert bytes into preallocated string\n");
00687 
00688   memcpy (new_header_fields, message->header_fields,
00689           sizeof (new_header_fields));
00690   
00691   /* Now just re-marshal each field in the header to our temporary
00692    * buffer, skipping the first one. The tricky part is that the
00693    * fields are padded as if for previous_name_offset, but are in fact
00694    * at unaligned_name_offset
00695    */
00696 
00697   if (!iterate_one_field (&message->header,
00698                           message->byte_order,
00699                           name_offset_to_delete,
00700                           &next_offset,
00701                           &field_name, NULL, NULL, NULL))
00702     _dbus_assert_not_reached ("shouldn't have failed to alloc memory to skip the deleted field");
00703 
00704   if (field_name < DBUS_HEADER_FIELD_LAST)
00705     {
00706       new_header_fields[field_name].name_offset = -1;
00707       new_header_fields[field_name].value_offset = -1;
00708     }
00709   
00710   while (next_offset < _dbus_string_get_length (&message->header))
00711     {
00712       int copy_name_offset;
00713       int copy_value_offset;
00714 
00715       if (!iterate_one_field (&message->header,
00716                               message->byte_order,
00717                               next_offset,
00718                               &next_offset,
00719                               &field_name,
00720                               &copy,
00721                               &copy_name_offset,
00722                               &copy_value_offset))
00723         {
00724           _dbus_verbose ("%s: OOM iterating one field\n",
00725                          _DBUS_FUNCTION_NAME);
00726           goto out_1;
00727         }
00728       
00729       if (field_name < DBUS_HEADER_FIELD_LAST)
00730         {
00731           new_header_fields[field_name].name_offset = copy_name_offset - new_fields_front_padding + name_offset_to_delete;
00732           new_header_fields[field_name].value_offset = copy_value_offset - new_fields_front_padding + name_offset_to_delete;
00733         }
00734     }
00735 
00736   if (!_dbus_string_replace_len (&copy,
00737                                  new_fields_front_padding,
00738                                  _dbus_string_get_length (&copy) - new_fields_front_padding,
00739                                  &message->header,
00740                                  name_offset_to_delete,
00741                                  _dbus_string_get_length (&message->header) - name_offset_to_delete))
00742     {
00743       _dbus_verbose ("%s: OOM moving copy back into header\n",
00744                      _DBUS_FUNCTION_NAME);
00745       goto out_1;
00746     }
00747   
00748   memcpy (message->header_fields, new_header_fields,
00749           sizeof (new_header_fields));
00750   verify_header_fields (message);
00751   
00752   retval = TRUE;
00753   
00754  out_1:
00755   _dbus_string_free (&copy);
00756   
00757  out_0:
00758   if (!append_header_padding (message))
00759     _dbus_assert_not_reached ("Failed to re-append header padding in re_align_field_recurse()");
00760   
00761   return retval;
00762 }
00763 
00764 static dbus_bool_t
00765 delete_field (DBusMessage *message,
00766               int          field,
00767               int          prealloc_header_space)
00768 {
00769   int offset;
00770 
00771   _dbus_assert (!message->locked);
00772 
00773   /* Prealloc */
00774   if (!_dbus_string_lengthen (&message->header, prealloc_header_space))
00775     {
00776       _dbus_verbose ("failed to prealloc %d bytes header space\n",
00777                      prealloc_header_space);
00778       return FALSE;
00779     }
00780   _dbus_string_shorten (&message->header, prealloc_header_space);
00781 
00782   /* Delete */
00783   offset = message->header_fields[field].name_offset;
00784   if (offset < 0)
00785     {
00786       _dbus_verbose ("header field didn't exist, no need to delete\n");
00787       return TRUE; /* field didn't exist */
00788     }
00789 
00790   return delete_one_and_re_align (message, offset);
00791 }
00792 
00793 #ifdef DBUS_BUILD_TESTS
00794 static dbus_bool_t
00795 set_int_field (DBusMessage *message,
00796                int          field,
00797                int          value)
00798 {
00799   int offset = message->header_fields[field].value_offset;
00800 
00801   _dbus_assert (!message->locked);
00802   
00803   if (offset < 0)
00804     {
00805       /* need to append the field */
00806       return append_int_field (message, field, value);
00807     }
00808   else
00809     {
00810       _dbus_marshal_set_int32 (&message->header,
00811                                message->byte_order,
00812                                offset, value);
00813 
00814       return TRUE;
00815     }
00816 }
00817 #endif
00818 
00819 static dbus_bool_t
00820 set_uint_field (DBusMessage  *message,
00821                 int           field,
00822                 dbus_uint32_t value)
00823 {
00824   int offset = message->header_fields[field].value_offset;
00825 
00826   _dbus_assert (!message->locked);
00827   
00828   if (offset < 0)
00829     {
00830       /* need to append the field */
00831       return append_uint_field (message, field, value);
00832     }
00833   else
00834     {
00835       _dbus_marshal_set_uint32 (&message->header,
00836                                 message->byte_order,
00837                                 offset, value);
00838 
00839       return TRUE;
00840     }
00841 }
00842 
00843 static dbus_bool_t
00844 set_string_field (DBusMessage *message,
00845                   int          field,
00846                   int          type,
00847                   const char  *value)
00848 {
00849   int prealloc;
00850   int value_len;
00851   
00852   _dbus_assert (!message->locked);
00853 
00854   value_len = value ? strlen (value) : 0;
00855   
00856   /* the prealloc is so the append_string_field()
00857    * below won't fail, leaving us in inconsistent state
00858    */
00859   prealloc = value_len + MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING;
00860 
00861   _dbus_verbose ("set_string_field() field %d prealloc %d\n",
00862                  field, prealloc);
00863   
00864   if (!delete_field (message, field, prealloc))
00865     return FALSE;
00866 
00867   if (value != NULL)
00868     {
00869       /* need to append the field */
00870       if (!append_string_field_len (message, field, type, value, value_len))
00871         _dbus_assert_not_reached ("Appending string field shouldn't have failed, due to preallocation");
00872     }
00873   
00874   return TRUE;
00875 }
00876 
00884 void
00885 _dbus_message_set_serial (DBusMessage  *message,
00886                           dbus_int32_t  serial)
00887 {
00888   _dbus_assert (!message->locked);
00889   _dbus_assert (dbus_message_get_serial (message) == 0);
00890 
00891   _dbus_marshal_set_uint32 (&message->header,
00892                             message->byte_order,
00893                             CLIENT_SERIAL_OFFSET,
00894                             serial);
00895 
00896   message->client_serial = serial;
00897 }
00898 
00907 dbus_bool_t
00908 dbus_message_set_reply_serial (DBusMessage   *message,
00909                                dbus_uint32_t  reply_serial)
00910 {
00911   _dbus_assert (!message->locked);
00912 
00913   if (set_uint_field (message,
00914                       DBUS_HEADER_FIELD_REPLY_SERIAL,
00915                       reply_serial))
00916     {
00917       message->reply_serial = reply_serial;
00918       return TRUE;
00919     }
00920   else
00921     return FALSE;
00922 }
00923 
00934 dbus_uint32_t
00935 dbus_message_get_serial (DBusMessage *message)
00936 {
00937   return message->client_serial;
00938 }
00939 
00946 dbus_uint32_t
00947 dbus_message_get_reply_serial  (DBusMessage *message)
00948 {
00949   return message->reply_serial;
00950 }
00951 
00964 void
00965 _dbus_message_add_size_counter_link (DBusMessage  *message,
00966                                      DBusList     *link)
00967 {
00968   /* right now we don't recompute the delta when message
00969    * size changes, and that's OK for current purposes
00970    * I think, but could be important to change later.
00971    * Do recompute it whenever there are no outstanding counters,
00972    * since it's basically free.
00973    */
00974   if (message->size_counters == NULL)
00975     {
00976       message->size_counter_delta =
00977         _dbus_string_get_length (&message->header) +
00978         _dbus_string_get_length (&message->body);
00979       
00980 #if 0
00981       _dbus_verbose ("message has size %ld\n",
00982                      message->size_counter_delta);
00983 #endif
00984     }
00985   
00986   _dbus_list_append_link (&message->size_counters, link);
00987   
00988   _dbus_counter_adjust (link->data, message->size_counter_delta);
00989 }
00990 
01000 dbus_bool_t
01001 _dbus_message_add_size_counter (DBusMessage *message,
01002                                 DBusCounter *counter)
01003 {
01004   DBusList *link;
01005 
01006   link = _dbus_list_alloc_link (counter);
01007   if (link == NULL)
01008     return FALSE;
01009 
01010   _dbus_counter_ref (counter);
01011   _dbus_message_add_size_counter_link (message, link);
01012 
01013   return TRUE;
01014 }
01015 
01024 void
01025 _dbus_message_remove_size_counter (DBusMessage  *message,
01026                                    DBusCounter  *counter,
01027                                    DBusList    **link_return)
01028 {
01029   DBusList *link;
01030 
01031   link = _dbus_list_find_last (&message->size_counters,
01032                                counter);
01033   _dbus_assert (link != NULL);
01034 
01035   _dbus_list_unlink (&message->size_counters,
01036                      link);
01037   if (link_return)
01038     *link_return = link;
01039   else
01040     _dbus_list_free_link (link);
01041 
01042   _dbus_counter_adjust (counter, - message->size_counter_delta);
01043 
01044   _dbus_counter_unref (counter);
01045 }
01046 
01047 static dbus_bool_t
01048 dbus_message_create_header (DBusMessage *message,
01049                             int          type,
01050                             const char  *service,
01051                             const char  *path,
01052                             const char  *interface,
01053                             const char  *member,
01054                             const char  *error_name)
01055 {
01056   unsigned int flags;
01057 
01058   _dbus_assert ((interface && member) ||
01059                 (error_name) ||
01060                 !(interface || member || error_name));
01061   _dbus_assert (error_name == NULL || is_valid_error_name (error_name));
01062   
01063   if (!_dbus_string_append_byte (&message->header, message->byte_order))
01064     return FALSE;
01065 
01066   if (!_dbus_string_append_byte (&message->header, type))
01067     return FALSE;
01068   
01069   flags = 0;
01070   if (!_dbus_string_append_byte (&message->header, flags))
01071     return FALSE;
01072 
01073   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
01074     return FALSE;
01075 
01076   /* header length */
01077   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01078     return FALSE;
01079 
01080   /* body length */
01081   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01082     return FALSE;
01083 
01084   /* serial */
01085   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01086     return FALSE;
01087   
01088   /* Marshal all the fields (Marshall Fields?) */
01089   
01090   if (path != NULL)
01091     {
01092       if (!append_string_field (message,
01093                                 DBUS_HEADER_FIELD_PATH,
01094                                 DBUS_TYPE_OBJECT_PATH,
01095                                 path))
01096         return FALSE;
01097     }
01098   
01099   if (service != NULL)
01100     {
01101       if (!append_string_field (message,
01102                                 DBUS_HEADER_FIELD_DESTINATION,
01103                                 DBUS_TYPE_STRING,
01104                                 service))
01105         return FALSE;
01106     }
01107 
01108   if (interface != NULL)
01109     {
01110       if (!append_string_field (message,
01111                                 DBUS_HEADER_FIELD_INTERFACE,
01112                                 DBUS_TYPE_STRING,
01113                                 interface))
01114         return FALSE;
01115     }
01116 
01117   if (member != NULL)
01118     {
01119       if (!append_string_field (message,
01120                                 DBUS_HEADER_FIELD_MEMBER,
01121                                 DBUS_TYPE_STRING,
01122                                 member))
01123         return FALSE;
01124     }
01125 
01126   if (error_name != NULL)
01127     {
01128       if (!append_string_field (message,
01129                                 DBUS_HEADER_FIELD_ERROR_NAME,
01130                                 DBUS_TYPE_STRING,
01131                                 error_name))
01132         return FALSE;
01133     }
01134 
01135   /* @todo if we make signature optional when body is empty, we don't
01136    * need to do this here.
01137    */
01138   if (!append_string_field (message,
01139                             DBUS_HEADER_FIELD_SIGNATURE,
01140                             DBUS_TYPE_STRING,
01141                             ""))
01142     return FALSE;
01143   
01144   return TRUE;
01145 }
01146 
01156 void
01157 _dbus_message_lock (DBusMessage  *message)
01158 {
01159   if (!message->locked)
01160     {
01161       /* Fill in our lengths */
01162       _dbus_marshal_set_uint32 (&message->header,
01163                                 message->byte_order,
01164                                 HEADER_LENGTH_OFFSET,
01165                                 _dbus_string_get_length (&message->header));
01166 
01167       _dbus_marshal_set_uint32 (&message->header,
01168                                 message->byte_order,
01169                                 BODY_LENGTH_OFFSET,
01170                                 _dbus_string_get_length (&message->body));
01171 
01172       message->locked = TRUE;
01173     }
01174 }
01175 
01207 static dbus_bool_t
01208 dbus_message_set_signature (DBusMessage *message,
01209                             const char  *signature)
01210 {
01211   _dbus_return_val_if_fail (message != NULL, FALSE);
01212   _dbus_return_val_if_fail (!message->locked, FALSE);
01213   
01214   return set_string_field (message,
01215                            DBUS_HEADER_FIELD_SIGNATURE,
01216                            DBUS_TYPE_STRING,
01217                            signature);
01218 }
01219 
01228 static dbus_bool_t
01229 dbus_message_append_to_signature (DBusMessage *message,
01230                                   const char  *append_bytes)
01231 {
01232   const char *signature;
01233   DBusString append_str;
01234   dbus_bool_t retval;
01235   
01236   _dbus_return_val_if_fail (append_bytes != NULL, FALSE);
01237   _dbus_return_val_if_fail (message != NULL, FALSE);
01238   _dbus_return_val_if_fail (!message->locked, FALSE);
01239 
01240   retval = FALSE;
01241   
01242   /* FIXME Just really inefficient for the moment; later we could
01243    * speed it up a lot by poking more directly at the header data
01244    */
01245   signature = dbus_message_get_signature (message);
01246 
01247   if (!_dbus_string_init (&append_str))
01248     return FALSE;
01249 
01250   if (signature && !_dbus_string_append (&append_str, signature))
01251     goto out;
01252 
01253   if (!_dbus_string_append (&append_str, append_bytes))
01254     goto out;
01255   
01256   if (!set_string_field (message,
01257                          DBUS_HEADER_FIELD_SIGNATURE,
01258                          DBUS_TYPE_STRING,
01259                          _dbus_string_get_const_data (&append_str)))
01260     goto out;
01261 
01262   retval = TRUE;
01263   
01264  out:
01265   
01266   _dbus_string_free (&append_str);
01267 
01268   return retval;
01269 }
01270 
01279 static dbus_bool_t
01280 _dbus_message_append_byte_to_signature (DBusMessage  *message,
01281                                         unsigned char append_byte)
01282 {
01283   char buf[2];
01284   
01285   _dbus_return_val_if_fail (message != NULL, FALSE);
01286   _dbus_return_val_if_fail (!message->locked, FALSE);
01287   
01288   buf[0] = append_byte;
01289   buf[1] = '\0';
01290 
01291   return dbus_message_append_to_signature (message, buf);
01292 }
01293 
01300 static void
01301 _dbus_message_remove_byte_from_signature (DBusMessage  *message)
01302 {
01303   const char *signature;
01304   
01305   _dbus_return_if_fail (message != NULL);
01306   _dbus_return_if_fail (!message->locked);
01307 
01308   signature = dbus_message_get_signature (message);
01309 
01310   _dbus_return_if_fail (signature != NULL);
01311   
01312   if (!delete_field (message,
01313                      DBUS_HEADER_FIELD_SIGNATURE,
01314                      0))
01315     _dbus_assert_not_reached ("failed to delete signature field");
01316 
01317   /* reappend one shorter (could this be any less efficient? the code will
01318    * go away later anyhow)
01319    */
01320   if (!append_string_field_len (message, DBUS_HEADER_FIELD_SIGNATURE,
01321                                 DBUS_TYPE_STRING, signature,
01322                                 strlen (signature) - 1))
01323     _dbus_assert_not_reached ("reappending shorter signature shouldn't have failed");
01324 }
01325 
01333 static DBusMessage*
01334 dbus_message_new_empty_header (void)
01335 {
01336   DBusMessage *message;
01337   int i;
01338   
01339   message = dbus_new0 (DBusMessage, 1);
01340   if (message == NULL)
01341     return NULL;
01342   
01343   message->refcount.value = 1;
01344   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
01345   message->client_serial = 0;
01346   message->reply_serial = 0;
01347 
01348   _dbus_data_slot_list_init (&message->slot_list);
01349   
01350   i = 0;
01351   while (i <= DBUS_HEADER_FIELD_LAST)
01352     {
01353       message->header_fields[i].name_offset  = -1;
01354       message->header_fields[i].value_offset = -1;
01355       ++i;
01356     }
01357   
01358   if (!_dbus_string_init_preallocated (&message->header, 64))
01359     {
01360       dbus_free (message);
01361       return NULL;
01362     }
01363   
01364   if (!_dbus_string_init_preallocated (&message->body, 64))
01365     {
01366       _dbus_string_free (&message->header);
01367       dbus_free (message);
01368       return NULL;
01369     }
01370   
01371   return message;
01372 }
01373 
01382 DBusMessage*
01383 dbus_message_new (int message_type)
01384 {
01385   DBusMessage *message;
01386 
01387   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01388   
01389   message = dbus_message_new_empty_header ();
01390   if (message == NULL)
01391     return NULL;
01392   
01393   if (!dbus_message_create_header (message,
01394                                    message_type,
01395                                    NULL, NULL, NULL, NULL, NULL))
01396     {
01397       dbus_message_unref (message);
01398       return NULL;
01399     }
01400   
01401   return message;
01402 }
01403 
01421 DBusMessage*
01422 dbus_message_new_method_call (const char *service,
01423                               const char *path,
01424                               const char *interface,
01425                               const char *method)
01426 {
01427   DBusMessage *message;
01428 
01429   _dbus_return_val_if_fail (path != NULL, NULL);
01430   _dbus_return_val_if_fail (method != NULL, NULL);
01431   
01432   message = dbus_message_new_empty_header ();
01433   if (message == NULL)
01434     return NULL;
01435   
01436   if (!dbus_message_create_header (message,
01437                                    DBUS_MESSAGE_TYPE_METHOD_CALL,
01438                                    service, path, interface, method, NULL))
01439     {
01440       dbus_message_unref (message);
01441       return NULL;
01442     }
01443   
01444   return message;
01445 }
01446 
01456 DBusMessage*
01457 dbus_message_new_method_return (DBusMessage *method_call)
01458 {
01459   DBusMessage *message;
01460   const char *sender;
01461 
01462   _dbus_return_val_if_fail (method_call != NULL, NULL);
01463   
01464   sender = get_string_field (method_call,
01465                              DBUS_HEADER_FIELD_SENDER,
01466                              NULL);
01467   
01468   /* sender is allowed to be null here in peer-to-peer case */
01469 
01470   message = dbus_message_new_empty_header ();
01471   if (message == NULL)
01472     return NULL;
01473   
01474   if (!dbus_message_create_header (message,
01475                                    DBUS_MESSAGE_TYPE_METHOD_RETURN,
01476                                    sender, NULL, NULL, NULL, NULL))
01477     {
01478       dbus_message_unref (message);
01479       return NULL;
01480     }
01481 
01482   dbus_message_set_no_reply (message, TRUE);
01483 
01484   if (!dbus_message_set_reply_serial (message,
01485                                       dbus_message_get_serial (method_call)))
01486     {
01487       dbus_message_unref (message);
01488       return NULL;
01489     }
01490 
01491   return message;
01492 }
01493 
01506 DBusMessage*
01507 dbus_message_new_signal (const char *path,
01508                          const char *interface,
01509                          const char *name)
01510 {
01511   DBusMessage *message;
01512 
01513   _dbus_return_val_if_fail (path != NULL, NULL);
01514   _dbus_return_val_if_fail (interface != NULL, NULL);
01515   _dbus_return_val_if_fail (name != NULL, NULL);
01516   
01517   message = dbus_message_new_empty_header ();
01518   if (message == NULL)
01519     return NULL;
01520   
01521   if (!dbus_message_create_header (message,
01522                                    DBUS_MESSAGE_TYPE_SIGNAL,
01523                                    NULL, path, interface, name, NULL))
01524     {
01525       dbus_message_unref (message);
01526       return NULL;
01527     }
01528 
01529   dbus_message_set_no_reply (message, TRUE);
01530   
01531   return message;
01532 }
01533 
01543 DBusMessage*
01544 dbus_message_new_error (DBusMessage *reply_to,
01545                         const char  *error_name,
01546                         const char  *error_message)
01547 {
01548   DBusMessage *message;
01549   const char *sender;
01550   DBusMessageIter iter;
01551 
01552   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01553   _dbus_return_val_if_fail (error_name != NULL, NULL);
01554   _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
01555   
01556   sender = get_string_field (reply_to,
01557                              DBUS_HEADER_FIELD_SENDER,
01558                              NULL);
01559 
01560   /* sender may be NULL for non-message-bus case or
01561    * when the message bus is dealing with an unregistered
01562    * connection.
01563    */
01564   message = dbus_message_new_empty_header ();
01565   if (message == NULL)
01566     return NULL;
01567   
01568   if (!dbus_message_create_header (message,
01569                                    DBUS_MESSAGE_TYPE_ERROR,
01570                                    sender, NULL, NULL, NULL, error_name))
01571     {
01572       dbus_message_unref (message);
01573       return NULL;
01574     }
01575 
01576   dbus_message_set_no_reply (message, TRUE);
01577   
01578   if (!dbus_message_set_reply_serial (message,
01579                                       dbus_message_get_serial (reply_to)))
01580     {
01581       dbus_message_unref (message);
01582       return NULL;
01583     }
01584 
01585   if (error_message != NULL)
01586     {
01587       dbus_message_append_iter_init (message, &iter);
01588       if (!dbus_message_iter_append_string (&iter, error_message))
01589         {
01590           dbus_message_unref (message);
01591           return NULL;
01592         }
01593     }
01594   
01595   return message;
01596 }
01597 
01608 DBusMessage*
01609 dbus_message_new_error_printf (DBusMessage *reply_to,
01610                                const char  *error_name,
01611                                const char  *error_format,
01612                                ...)
01613 {
01614   va_list args;
01615   DBusString str;
01616   DBusMessage *message;
01617 
01618   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01619   _dbus_return_val_if_fail (error_name != NULL, NULL);
01620   _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
01621   
01622   if (!_dbus_string_init (&str))
01623     return NULL;
01624 
01625   va_start (args, error_format);
01626 
01627   if (_dbus_string_append_printf_valist (&str, error_format, args))
01628     message = dbus_message_new_error (reply_to, error_name,
01629                                       _dbus_string_get_const_data (&str));
01630   else
01631     message = NULL;
01632   
01633   _dbus_string_free (&str);
01634 
01635   va_end (args);
01636 
01637   return message;
01638 }
01639 
01640 
01648 DBusMessage *
01649 dbus_message_copy (const DBusMessage *message)
01650 {
01651   DBusMessage *retval;
01652   int i;
01653 
01654   _dbus_return_val_if_fail (message != NULL, NULL);
01655   
01656   retval = dbus_new0 (DBusMessage, 1);
01657   if (retval == NULL)
01658     return NULL;
01659   
01660   retval->refcount.value = 1;
01661   retval->byte_order = message->byte_order;
01662   retval->client_serial = message->client_serial;
01663   retval->reply_serial = message->reply_serial;
01664   retval->header_padding = message->header_padding;
01665   retval->locked = FALSE;
01666   
01667   if (!_dbus_string_init_preallocated (&retval->header,
01668                                        _dbus_string_get_length (&message->header)))
01669     {
01670       dbus_free (retval);
01671       return NULL;
01672     }
01673   
01674   if (!_dbus_string_init_preallocated (&retval->body,
01675                                        _dbus_string_get_length (&message->body)))
01676     {
01677       _dbus_string_free (&retval->header);
01678       dbus_free (retval);
01679       return NULL;
01680     }
01681   
01682   if (!_dbus_string_copy (&message->header, 0,
01683                           &retval->header, 0))
01684     goto failed_copy;
01685 
01686   if (!_dbus_string_copy (&message->body, 0,
01687                           &retval->body, 0))
01688     goto failed_copy;
01689   
01690   for (i = 0; i <= DBUS_HEADER_FIELD_LAST; i++)
01691     {
01692       retval->header_fields[i] = message->header_fields[i];
01693     }
01694   
01695   return retval;
01696 
01697  failed_copy:
01698   _dbus_string_free (&retval->header);
01699   _dbus_string_free (&retval->body);
01700   dbus_free (retval);
01701   
01702   return NULL;  
01703 }
01704 
01705 
01713 DBusMessage *
01714 dbus_message_ref (DBusMessage *message)
01715 {
01716   dbus_int32_t old_refcount;
01717 
01718   _dbus_return_val_if_fail (message != NULL, NULL);
01719   
01720   old_refcount = _dbus_atomic_inc (&message->refcount);
01721   _dbus_assert (old_refcount >= 1);
01722 
01723   return message;
01724 }
01725 
01726 static void
01727 free_size_counter (void *element,
01728                    void *data)
01729 {
01730   DBusCounter *counter = element;
01731   DBusMessage *message = data;
01732   
01733   _dbus_counter_adjust (counter, - message->size_counter_delta);
01734 
01735   _dbus_counter_unref (counter);
01736 }
01737 
01744 void
01745 dbus_message_unref (DBusMessage *message)
01746 {
01747  dbus_int32_t old_refcount;
01748 
01749   _dbus_return_if_fail (message != NULL);
01750   
01751   old_refcount = _dbus_atomic_dec (&message->refcount);
01752   
01753   _dbus_assert (old_refcount >= 0);
01754 
01755   if (old_refcount == 1)
01756     {
01757       /* This calls application callbacks! */
01758       _dbus_data_slot_list_free (&message->slot_list);
01759       
01760       _dbus_list_foreach (&message->size_counters,
01761                           free_size_counter, message);
01762       _dbus_list_clear (&message->size_counters);
01763       
01764       _dbus_string_free (&message->header);
01765       _dbus_string_free (&message->body);
01766       
01767       dbus_free (message);
01768     }
01769 }
01770 
01782 int
01783 dbus_message_get_type (DBusMessage *message)
01784 {
01785   int type;
01786 
01787   type = _dbus_string_get_byte (&message->header, 1);
01788   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
01789 
01790   return type;
01791 }
01792 
01802 dbus_bool_t
01803 dbus_message_set_path (DBusMessage   *message,
01804                        const char    *object_path)
01805 {
01806   _dbus_return_val_if_fail (message != NULL, FALSE);
01807   _dbus_return_val_if_fail (!message->locked, FALSE);
01808 
01809   return set_string_field (message,
01810                            DBUS_HEADER_FIELD_PATH,
01811                            DBUS_TYPE_OBJECT_PATH,
01812                            object_path);
01813 }
01814 
01823 const char*
01824 dbus_message_get_path (DBusMessage   *message)
01825 {
01826   _dbus_return_val_if_fail (message != NULL, NULL);
01827   
01828   return get_string_field (message, DBUS_HEADER_FIELD_PATH, NULL);
01829 }
01830 
01846 dbus_bool_t
01847 dbus_message_get_path_decomposed (DBusMessage   *message,
01848                                   char        ***path)
01849 {
01850   _dbus_return_val_if_fail (message != NULL, FALSE);
01851   _dbus_return_val_if_fail (path != NULL, FALSE);
01852 
01853   return get_path_field_decomposed (message,
01854                                     DBUS_HEADER_FIELD_PATH,
01855                                     path);
01856 }
01857 
01868 dbus_bool_t
01869 dbus_message_set_interface (DBusMessage  *message,
01870                             const char   *interface)
01871 {
01872   _dbus_return_val_if_fail (message != NULL, FALSE);
01873   _dbus_return_val_if_fail (!message->locked, FALSE);
01874 
01875   return set_string_field (message,
01876                            DBUS_HEADER_FIELD_INTERFACE,
01877                            DBUS_TYPE_STRING,
01878                            interface);
01879 }
01880 
01890 const char*
01891 dbus_message_get_interface (DBusMessage *message)
01892 {
01893   _dbus_return_val_if_fail (message != NULL, NULL);
01894   
01895   return get_string_field (message, DBUS_HEADER_FIELD_INTERFACE, NULL);
01896 }
01897 
01908 dbus_bool_t
01909 dbus_message_set_member (DBusMessage  *message,
01910                        const char   *member)
01911 {
01912   _dbus_return_val_if_fail (message != NULL, FALSE);
01913   _dbus_return_val_if_fail (!message->locked, FALSE);
01914 
01915   return set_string_field (message,
01916                            DBUS_HEADER_FIELD_MEMBER,
01917                            DBUS_TYPE_STRING,
01918                            member);
01919 }
01920 
01929 const char*
01930 dbus_message_get_member (DBusMessage *message)
01931 {
01932   _dbus_return_val_if_fail (message != NULL, NULL);
01933   
01934   return get_string_field (message,
01935                            DBUS_HEADER_FIELD_MEMBER,
01936                            NULL);
01937 }
01938 
01947 dbus_bool_t
01948 dbus_message_set_error_name (DBusMessage  *message,
01949                              const char   *error_name)
01950 {
01951   _dbus_return_val_if_fail (message != NULL, FALSE);
01952   _dbus_return_val_if_fail (!message->locked, FALSE);
01953   _dbus_return_val_if_fail (error_name == NULL || is_valid_error_name (error_name), FALSE);
01954   
01955   return set_string_field (message,
01956                            DBUS_HEADER_FIELD_ERROR_NAME,
01957                            DBUS_TYPE_STRING,
01958                            error_name);
01959 }
01960 
01967 const char*
01968 dbus_message_get_error_name (DBusMessage *message)
01969 {
01970   _dbus_return_val_if_fail (message != NULL, NULL);
01971   
01972   return get_string_field (message,
01973                            DBUS_HEADER_FIELD_ERROR_NAME,
01974                            NULL);
01975 }
01976 
01984 dbus_bool_t
01985 dbus_message_set_destination (DBusMessage  *message,
01986                               const char   *destination)
01987 {
01988   _dbus_return_val_if_fail (message != NULL, FALSE);
01989   _dbus_return_val_if_fail (!message->locked, FALSE);
01990 
01991   return set_string_field (message,
01992                            DBUS_HEADER_FIELD_DESTINATION,
01993                            DBUS_TYPE_STRING,
01994                            destination);
01995 }
01996 
02003 const char*
02004 dbus_message_get_destination (DBusMessage *message)
02005 {
02006   _dbus_return_val_if_fail (message != NULL, NULL);
02007   
02008   return get_string_field (message,
02009                            DBUS_HEADER_FIELD_DESTINATION,
02010                            NULL);
02011 }
02012 
02031 dbus_bool_t
02032 dbus_message_append_args (DBusMessage *message,
02033                           int first_arg_type,
02034                           ...)
02035 {
02036   dbus_bool_t retval;
02037   va_list var_args;
02038 
02039   _dbus_return_val_if_fail (message != NULL, FALSE);
02040   
02041   va_start (var_args, first_arg_type);
02042   retval = dbus_message_append_args_valist (message,
02043                                             first_arg_type,
02044                                             var_args);
02045   va_end (var_args);
02046 
02047   return retval;
02048 }
02049 
02062 dbus_bool_t
02063 dbus_message_get_args (DBusMessage     *message,
02064                        DBusError       *error,
02065                        int              first_arg_type,
02066                        ...)
02067 {
02068   dbus_bool_t retval;
02069   va_list var_args;
02070 
02071   _dbus_return_val_if_fail (message != NULL, FALSE);
02072   _dbus_return_val_if_error_is_set (error, FALSE);
02073   
02074   va_start (var_args, first_arg_type);
02075   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
02076   va_end (var_args);
02077 
02078   return retval;
02079 }
02080 
02093 dbus_bool_t
02094 dbus_message_get_args_valist (DBusMessage     *message,
02095                               DBusError       *error,
02096                               int              first_arg_type,
02097                               va_list          var_args)
02098 {
02099   DBusMessageIter iter;
02100 
02101   _dbus_return_val_if_fail (message != NULL, FALSE);
02102   _dbus_return_val_if_error_is_set (error, FALSE);
02103   
02104   dbus_message_iter_init (message, &iter);
02105   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
02106 }
02107 
02120 dbus_bool_t
02121 dbus_message_iter_get_args (DBusMessageIter *iter,
02122                             DBusError       *error,
02123                             int              first_arg_type,
02124                             ...)
02125 {
02126   dbus_bool_t retval;
02127   va_list var_args;
02128 
02129   _dbus_return_val_if_fail (iter != NULL, FALSE);
02130   _dbus_return_val_if_error_is_set (error, FALSE);
02131   
02132   va_start (var_args, first_arg_type);
02133   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
02134   va_end (var_args);
02135 
02136   return retval;
02137 }
02138 
02147 dbus_bool_t
02148 dbus_message_iter_init (DBusMessage     *message,
02149                         DBusMessageIter *iter)
02150 {
02151   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02152 
02153   _dbus_return_val_if_fail (message != NULL, FALSE);
02154   _dbus_return_val_if_fail (iter != NULL, FALSE);
02155   
02156   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
02157   
02158   real->message = message;
02159   real->parent_iter = NULL;
02160   real->changed_stamp = message->changed_stamp;
02161   
02162   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
02163   real->pos = 0;
02164   real->end = _dbus_string_get_length (&message->body);
02165   
02166   real->container_start = 0;
02167   real->container_length_pos = 0;
02168   real->wrote_dict_key = 0;
02169   real->array_type_pos = 0;
02170 
02171   return real->end > real->pos;
02172 }
02173 
02174 #ifndef DBUS_DISABLE_CHECKS
02175 static dbus_bool_t
02176 dbus_message_iter_check (DBusMessageRealIter *iter)
02177 {
02178   if (iter == NULL)
02179     {
02180       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
02181       return FALSE;
02182     }
02183   
02184   if (iter->changed_stamp != iter->message->changed_stamp)
02185     {
02186       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
02187       return FALSE;
02188     }
02189   
02190   if (iter->pos < 0 || iter->pos > iter->end)
02191     {
02192       _dbus_warn ("dbus iterator check failed: invalid position\n");
02193       return FALSE;
02194     }
02195 
02196   return TRUE;
02197 }
02198 #endif /* DBUS_DISABLE_CHECKS */
02199 
02200 static int
02201 skip_array_type (DBusMessageRealIter *iter, int pos)
02202 {
02203   const char *data;
02204 
02205   do
02206     {
02207       data = _dbus_string_get_const_data_len (&iter->message->body,
02208                                               pos++, 1);
02209     }
02210   while (*data == DBUS_TYPE_ARRAY);
02211   
02212   return pos;
02213 }
02214 
02215 /* FIXME what are these _dbus_type_is_valid() checks for?
02216  * haven't we validated the message?
02217  */
02218 static int
02219 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
02220 {
02221   const char *data;
02222   int pos, len;
02223   
02224   switch (iter->type)
02225     {
02226     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02227       data = _dbus_string_get_const_data_len (&iter->message->body,
02228                                               iter->pos, 1);
02229       if (_dbus_type_is_valid (*data))
02230         *type = *data;
02231       else
02232         *type = DBUS_TYPE_INVALID;
02233       
02234       return skip_array_type (iter, iter->pos);
02235       
02236     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02237       data = _dbus_string_get_const_data_len (&iter->message->body,
02238                                               iter->array_type_pos, 1);
02239       if (_dbus_type_is_valid (*data))
02240         *type = *data;
02241       else
02242         *type = DBUS_TYPE_INVALID;
02243       
02244       return iter->pos;
02245       
02246     case DBUS_MESSAGE_ITER_TYPE_DICT:
02247       /* Get the length of the string */
02248       len = _dbus_demarshal_uint32 (&iter->message->body,
02249                                     iter->message->byte_order,
02250                                     iter->pos, &pos);
02251       pos = pos + len + 1;
02252 
02253       data = _dbus_string_get_const_data_len (&iter->message->body,
02254                                               pos, 1);
02255       if (_dbus_type_is_valid (*data))
02256         *type = *data;
02257       else
02258         *type = DBUS_TYPE_INVALID;
02259 
02260       return skip_array_type (iter, pos);
02261       
02262     default:
02263       _dbus_assert_not_reached ("Invalid iter type");
02264       break;
02265     }
02266   *type = DBUS_TYPE_INVALID;
02267   return iter->pos;
02268 }
02269 
02270 
02278 dbus_bool_t
02279 dbus_message_iter_has_next (DBusMessageIter *iter)
02280 {
02281   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02282   int end_pos;
02283   int type, pos;
02284 
02285   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02286 
02287   if (real->pos >= real->end)
02288     return FALSE;
02289   
02290   pos = dbus_message_iter_get_data_start (real, &type);
02291   
02292   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02293                                       real->message->byte_order,
02294                                       type, pos, &end_pos))
02295     return FALSE;
02296   
02297   if (end_pos >= real->end)
02298     return FALSE;
02299 
02300   return TRUE;  
02301 }
02302 
02309 dbus_bool_t
02310 dbus_message_iter_next (DBusMessageIter *iter)
02311 {
02312   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02313   int end_pos;
02314   int type, pos;
02315 
02316   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02317 
02318   pos = dbus_message_iter_get_data_start (real, &type);
02319   
02320   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02321                                       real->message->byte_order,
02322                                       type, pos, &end_pos))
02323     return FALSE;
02324 
02325   if (end_pos >= real->end)
02326     return FALSE;
02327 
02328   real->pos = end_pos;
02329 
02330   return TRUE;
02331 }
02332 
02340 int
02341 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02342 {
02343   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02344   int type, pos;
02345 
02346   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02347 
02348   if (real->pos >= real->end)
02349     {
02350       _dbus_verbose ("  iterator at or beyond end of message\n");
02351       return DBUS_TYPE_INVALID;
02352     }
02353 
02354   pos = dbus_message_iter_get_data_start (real, &type);
02355   
02356   return type;
02357 }
02358 
02359 /* FIXME why do we validate the typecode in here, hasn't the message
02360  * already been verified?
02361  */
02362 static int
02363 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
02364 {
02365   const char *data;
02366   int _array_type_pos;
02367   int len, pos;
02368   
02369   switch (iter->type)
02370     {
02371     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02372       _array_type_pos = iter->pos + 1;
02373       break;
02374     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02375       _array_type_pos = iter->array_type_pos + 1;
02376       break;
02377     case DBUS_MESSAGE_ITER_TYPE_DICT:
02378       /* Get the length of the string */
02379       len = _dbus_demarshal_uint32 (&iter->message->body,
02380                                     iter->message->byte_order,
02381                                     iter->pos, &pos);
02382       pos = pos + len + 1;
02383       data = _dbus_string_get_const_data_len (&iter->message->body,
02384                                               pos + 1, 1);
02385       _array_type_pos = pos + 1;
02386       break;
02387     default:
02388       _dbus_assert_not_reached ("wrong iter type");
02389       return DBUS_TYPE_INVALID;
02390     }
02391 
02392   if (array_type_pos != NULL)
02393     *array_type_pos = _array_type_pos;
02394   
02395   data = _dbus_string_get_const_data_len (&iter->message->body,
02396                                           _array_type_pos, 1);
02397   if (_dbus_type_is_valid (*data))
02398     return  *data;
02399   
02400   return DBUS_TYPE_INVALID;
02401 }
02402 
02403 
02413 int
02414 dbus_message_iter_get_array_type (DBusMessageIter *iter)
02415 {
02416   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02417   int type, pos;
02418 
02419   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02420 
02421   if (real->pos >= real->end)
02422     return DBUS_TYPE_INVALID;
02423 
02424   pos = dbus_message_iter_get_data_start (real, &type);
02425 
02426   _dbus_assert (type == DBUS_TYPE_ARRAY);
02427 
02428   return iter_get_array_type (real, NULL);
02429 }
02430 
02431 
02441 char *
02442 dbus_message_iter_get_string (DBusMessageIter *iter)
02443 {
02444   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02445   int type, pos;
02446 
02447   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02448   pos = dbus_message_iter_get_data_start (real, &type);
02449   
02450   _dbus_assert (type == DBUS_TYPE_STRING);
02451 
02452   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02453                                  pos, NULL);
02454 }
02455 
02465 char *
02466 dbus_message_iter_get_object_path (DBusMessageIter  *iter)
02467 {
02468   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02469   int type, pos;
02470 
02471   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02472 
02473   pos = dbus_message_iter_get_data_start (real, &type);
02474   
02475   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
02476 
02477   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02478                                  pos, NULL);
02479 }
02480 
02494 dbus_bool_t
02495 dbus_message_iter_get_custom (DBusMessageIter   *iter,
02496                               char             **name,
02497                               unsigned char    **value,
02498                               int               *len)
02499 {
02500   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02501   int type, pos;
02502   char *_name;
02503 
02504   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02505 
02506   pos = dbus_message_iter_get_data_start (real, &type);
02507   
02508   _dbus_assert (type == DBUS_TYPE_CUSTOM);
02509   
02510   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02511                                   pos, &pos);
02512 
02513   if (_name == NULL)
02514     return FALSE;
02515   
02516   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
02517                                    pos, NULL, value, len))
02518     {
02519       dbus_free (_name);
02520       return FALSE;
02521     }
02522 
02523   *name = _name;
02524   
02525   return TRUE;
02526 }
02527 
02528 static void
02529 _dbus_message_iter_get_basic_type (DBusMessageIter *iter,
02530                                    char             type,
02531                                    void            *value)
02532 {
02533   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02534   int item_type, pos;
02535 
02536   _dbus_return_if_fail (dbus_message_iter_check (real));
02537 
02538   pos = dbus_message_iter_get_data_start (real, &item_type);
02539   
02540   _dbus_assert (type == item_type);
02541   
02542   _dbus_demarshal_basic_type (&real->message->body,
02543                               type, value,
02544                               real->message->byte_order,
02545                               &pos);
02546 }
02547 
02548 
02571 dbus_bool_t
02572 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
02573                                    DBusError       *error,
02574                                    int              first_arg_type,
02575                                    va_list          var_args)
02576 {
02577   int spec_type, msg_type, i;
02578   dbus_bool_t retval;
02579 
02580   _dbus_return_val_if_fail (iter != NULL, FALSE);
02581   _dbus_return_val_if_error_is_set (error, FALSE);
02582 
02583   retval = FALSE;
02584   
02585   spec_type = first_arg_type;
02586   i = 0;
02587   
02588   while (spec_type != DBUS_TYPE_INVALID)
02589     {
02590       msg_type = dbus_message_iter_get_arg_type (iter);      
02591       
02592       if (msg_type != spec_type)
02593         {
02594           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02595                           "Argument %d is specified to be of type \"%s\", but "
02596                           "is actually of type \"%s\"\n", i,
02597                           _dbus_type_to_string (spec_type),
02598                           _dbus_type_to_string (msg_type));
02599 
02600           goto out;
02601         }
02602 
02603       switch (spec_type)
02604         {
02605         case DBUS_TYPE_NIL:
02606           break;
02607         case DBUS_TYPE_BOOLEAN:
02608           {
02609             dbus_bool_t *ptr;
02610 
02611             ptr = va_arg (var_args, dbus_bool_t *);
02612 
02613             *ptr = dbus_message_iter_get_boolean (iter);
02614             break;
02615           }
02616         case DBUS_TYPE_BYTE:
02617         case DBUS_TYPE_INT32:
02618         case DBUS_TYPE_UINT32:
02619 #ifdef DBUS_HAVE_INT64
02620         case DBUS_TYPE_INT64:
02621         case DBUS_TYPE_UINT64:
02622 #endif /* DBUS_HAVE_INT64 */
02623         case DBUS_TYPE_DOUBLE:
02624           {
02625             void *ptr = va_arg (var_args, double *);
02626             _dbus_message_iter_get_basic_type (iter, spec_type, ptr);
02627             break;
02628           }
02629 
02630         case DBUS_TYPE_STRING:
02631           {
02632             char **ptr;
02633 
02634             ptr = va_arg (var_args, char **);
02635 
02636             *ptr = dbus_message_iter_get_string (iter);
02637 
02638             if (!*ptr)
02639               {
02640                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02641                 goto out;
02642               }
02643             
02644             break;
02645           }
02646 
02647           case DBUS_TYPE_OBJECT_PATH:
02648           {
02649             char **ptr;
02650 
02651             ptr = va_arg (var_args, char **);
02652 
02653             *ptr = dbus_message_iter_get_object_path (iter);
02654 
02655             if (!*ptr)
02656               {
02657                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02658                 goto out;
02659               }
02660 
02661             break;
02662           }
02663 
02664         case DBUS_TYPE_CUSTOM:
02665           {
02666             char **name;
02667             unsigned char **data;
02668             int *len;
02669  
02670             name = va_arg (var_args, char **);
02671             data = va_arg (var_args, unsigned char **);
02672             len = va_arg (var_args, int *);
02673 
02674             if (!dbus_message_iter_get_custom (iter, name, data, len))
02675               {
02676                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02677                 goto out;
02678               }
02679           }
02680           break;
02681         case DBUS_TYPE_ARRAY:
02682           {
02683             void **data;
02684             int *len, type;
02685             dbus_bool_t err = FALSE;
02686  
02687             type = va_arg (var_args, int);
02688             data = va_arg (var_args, void *);
02689             len = va_arg (var_args, int *);
02690 
02691             _dbus_return_val_if_fail (data != NULL, FALSE);
02692             _dbus_return_val_if_fail (len != NULL, FALSE);
02693             
02694             if (dbus_message_iter_get_array_type (iter) != type)
02695               {
02696                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02697                                 "Argument %d is specified to be of type \"array of %s\", but "
02698                                 "is actually of type \"array of %s\"\n", i,
02699                                 _dbus_type_to_string (type),
02700                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
02701                 goto out;
02702               }
02703             
02704             switch (type)
02705               {
02706               case DBUS_TYPE_BYTE:
02707                 err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
02708                 break;
02709               case DBUS_TYPE_BOOLEAN:
02710                 err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
02711                 break;
02712               case DBUS_TYPE_INT32:
02713                 err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
02714                 break;
02715               case DBUS_TYPE_UINT32:
02716                 err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
02717                 break;
02718 #ifdef DBUS_HAVE_INT64
02719               case DBUS_TYPE_INT64:
02720                 err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
02721                 break;
02722               case DBUS_TYPE_UINT64:
02723                 err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
02724                 break;
02725 #endif /* DBUS_HAVE_INT64 */
02726               case DBUS_TYPE_DOUBLE:
02727                 err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
02728                 break;
02729               case DBUS_TYPE_STRING:
02730                 err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
02731                 break;
02732               case DBUS_TYPE_OBJECT_PATH:
02733                 err = !dbus_message_iter_get_object_path_array (iter, (char ***)data, len);
02734                 break;
02735 
02736               case DBUS_TYPE_NIL:
02737               case DBUS_TYPE_ARRAY:
02738               case DBUS_TYPE_CUSTOM:
02739               case DBUS_TYPE_DICT:
02740                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
02741                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02742                 goto out;
02743               default:
02744                 _dbus_warn ("Unknown field type %d\n", type);
02745                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02746                 goto out;
02747               }
02748             if (err)
02749               {
02750                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02751                 goto out;
02752               }
02753           }
02754           break;
02755         case DBUS_TYPE_DICT:
02756           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
02757           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02758           goto out;
02759         default:          
02760           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
02761           _dbus_warn ("Unknown field type %d\n", spec_type);
02762           goto out;
02763         }
02764 
02765       spec_type = va_arg (var_args, int);
02766       if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
02767         {
02768           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02769                           "Message has only %d arguments, but more were expected", i);
02770           goto out;
02771         }
02772 
02773       i++;
02774     }
02775   
02776   retval = TRUE;
02777   
02778  out:
02779   
02780   return retval;
02781 }
02782 
02792 unsigned char
02793 dbus_message_iter_get_byte (DBusMessageIter *iter)
02794 {
02795   unsigned char value = 0;
02796 
02797   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BYTE, &value);
02798 
02799   return value;
02800 }
02801 
02811 dbus_bool_t
02812 dbus_message_iter_get_boolean (DBusMessageIter *iter)
02813 {
02814   unsigned char value = 0;
02815 
02816   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BOOLEAN, &value);
02817 
02818   return (value != FALSE);
02819 }
02820 
02830 dbus_int32_t
02831 dbus_message_iter_get_int32 (DBusMessageIter *iter)
02832 {
02833   dbus_int32_t value = 0;
02834 
02835   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT32, &value);
02836 
02837   return value;
02838 }
02839 
02849 dbus_uint32_t
02850 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
02851 {
02852   dbus_int32_t value = 0;
02853 
02854   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT32, &value);
02855 
02856   return value;
02857 }
02858 
02859 #ifdef DBUS_HAVE_INT64
02860 
02872 dbus_int64_t
02873 dbus_message_iter_get_int64 (DBusMessageIter *iter)
02874 {
02875   dbus_int64_t value = 0;
02876 
02877   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT64, &value);
02878 
02879   return value;
02880 }
02881 
02893 dbus_uint64_t
02894 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
02895 {
02896   dbus_uint64_t value = 0;
02897 
02898   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT64, &value);
02899 
02900   return value;
02901 }
02902 
02903 #endif /* DBUS_HAVE_INT64 */
02904 
02914 double
02915 dbus_message_iter_get_double (DBusMessageIter *iter)
02916 {
02917   double value = 0.0;
02918 
02919   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_DOUBLE, &value);
02920 
02921   return value;
02922 }
02923 
02937 dbus_bool_t
02938 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
02939                                        DBusMessageIter *array_iter,
02940                                        int             *array_type)
02941 {
02942   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02943   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
02944   int type, pos, len_pos, len, array_type_pos;
02945   int _array_type;
02946 
02947   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02948 
02949   pos = dbus_message_iter_get_data_start (real, &type);
02950   
02951   _dbus_assert (type == DBUS_TYPE_ARRAY);
02952 
02953   _array_type = iter_get_array_type (real, &array_type_pos);
02954   
02955   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
02956   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
02957                                 pos, &pos);
02958   
02959   array_real->parent_iter = real;
02960   array_real->message = real->message;
02961   array_real->changed_stamp = real->message->changed_stamp;
02962   
02963   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
02964   array_real->pos = pos;
02965   array_real->end = pos + len;
02966   
02967   array_real->container_start = pos;
02968   array_real->container_length_pos = len_pos;
02969   array_real->wrote_dict_key = 0;
02970   array_real->array_type_pos = array_type_pos;
02971   array_real->array_type_done = TRUE;
02972   
02973   if (array_type != NULL)
02974     *array_type = _array_type;
02975 
02976   return len > 0;
02977 }
02978 
02979 
02989 dbus_bool_t
02990 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
02991                                       DBusMessageIter *dict_iter)
02992 {
02993   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02994   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
02995   int type, pos, len_pos, len;
02996 
02997   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02998 
02999   pos = dbus_message_iter_get_data_start (real, &type);
03000   
03001   _dbus_assert (type == DBUS_TYPE_DICT);
03002 
03003   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
03004   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
03005                                 pos, &pos);
03006   
03007   dict_real->parent_iter = real;
03008   dict_real->message = real->message;
03009   dict_real->changed_stamp = real->message->changed_stamp;
03010   
03011   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
03012   dict_real->pos = pos;
03013   dict_real->end = pos + len;
03014   
03015   dict_real->container_start = pos;
03016   dict_real->container_length_pos = len_pos;
03017   dict_real->wrote_dict_key = 0;
03018 
03019   return len > 0;
03020 }
03021 
03022 static dbus_bool_t
03023 _dbus_message_iter_get_basic_type_array  (DBusMessageIter *iter,
03024                                           char             type,
03025                                           void           **array,
03026                                           int             *array_len)
03027 {
03028   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03029   int item_type, pos;
03030 
03031   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03032 
03033   pos = dbus_message_iter_get_data_start (real, &item_type);
03034   
03035   _dbus_assert (item_type == DBUS_TYPE_ARRAY);
03036 
03037   item_type = iter_get_array_type (real, NULL);
03038   
03039   _dbus_assert (type == item_type);
03040 
03041   return _dbus_demarshal_basic_type_array (&real->message->body,
03042                                            item_type, array, array_len,
03043                                            real->message->byte_order, &pos);
03044 }
03045 
03056 dbus_bool_t
03057 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
03058                                   unsigned char   **value,
03059                                   int              *len)
03060 {
03061   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BYTE,
03062                                                   (void **) value, len);
03063 }
03064 
03075 dbus_bool_t
03076 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
03077                                      unsigned char    **value,
03078                                      int               *len)
03079 {
03080   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BOOLEAN,
03081                                                   (void **) value, len);
03082 }
03083 
03094 dbus_bool_t
03095 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
03096                                     dbus_int32_t   **value,
03097                                     int             *len)
03098 {
03099   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT32,
03100                                                   (void **) value, len);
03101 }
03102 
03113 dbus_bool_t
03114 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
03115                                      dbus_uint32_t  **value,
03116                                      int             *len)
03117 {
03118   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT32,
03119                                                   (void **) value, len);
03120 }
03121 
03122 #ifdef DBUS_HAVE_INT64
03123 
03136 dbus_bool_t
03137 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
03138                                     dbus_int64_t   **value,
03139                                     int             *len)
03140 {
03141   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT64,
03142                                                   (void **) value, len);
03143 }
03144 
03157 dbus_bool_t
03158 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
03159                                      dbus_uint64_t  **value,
03160                                      int             *len)
03161 {
03162   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT64,
03163                                                   (void **) value, len);
03164 }
03165 
03166 #endif /* DBUS_HAVE_INT64 */
03167 
03178 dbus_bool_t
03179 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
03180                                      double         **value,
03181                                      int             *len)
03182 {
03183   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_DOUBLE,
03184                                                   (void **) value, len);
03185 }
03186 
03202 dbus_bool_t
03203 dbus_message_iter_get_string_array (DBusMessageIter *iter,
03204                                     char          ***value,
03205                                     int             *len)
03206 {
03207   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03208   int type, pos;
03209 
03210   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03211 
03212   pos = dbus_message_iter_get_data_start (real, &type);
03213   
03214   _dbus_assert (type == DBUS_TYPE_ARRAY);
03215 
03216   type = iter_get_array_type (real, NULL);
03217   _dbus_assert (type == DBUS_TYPE_STRING);
03218 
03219   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
03220                                      pos, NULL, value, len))
03221     return FALSE;
03222   else
03223     return TRUE;
03224 }
03225 
03241 dbus_bool_t
03242 dbus_message_iter_get_object_path_array (DBusMessageIter *iter,
03243                                          char          ***value,
03244                                          int             *len)
03245 {
03246   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03247   int type, pos;
03248 
03249   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03250 
03251   pos = dbus_message_iter_get_data_start (real, &type);
03252   
03253   _dbus_assert (type == DBUS_TYPE_ARRAY);
03254 
03255   type = iter_get_array_type (real, NULL);
03256   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
03257 
03258   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
03259                                      pos, NULL, value, len))
03260     return FALSE;
03261   else
03262     return TRUE;
03263 }
03264 
03274 char *
03275 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
03276 {
03277   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03278 
03279   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
03280 
03281   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03282 
03283   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
03284                                  real->pos, NULL);
03285 }
03286 
03295 void
03296 dbus_message_append_iter_init (DBusMessage     *message,
03297                                DBusMessageIter *iter)
03298 {
03299   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03300 
03301   _dbus_return_if_fail (message != NULL);
03302   _dbus_return_if_fail (iter != NULL);
03303   
03304   real->message = message;
03305   real->parent_iter = NULL;
03306   real->changed_stamp = message->changed_stamp;
03307   
03308   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
03309   real->end = _dbus_string_get_length (&real->message->body);
03310   real->pos = real->end;
03311   
03312   real->container_length_pos = 0;
03313   real->wrote_dict_key = 0;
03314 }
03315 
03316 #ifndef DBUS_DISABLE_CHECKS
03317 static dbus_bool_t
03318 dbus_message_iter_append_check (DBusMessageRealIter *iter)
03319 {
03320   if (iter == NULL)
03321     {
03322       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
03323       return FALSE;
03324     }
03325   
03326   if (iter->message->locked)
03327     {
03328       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
03329       return FALSE;
03330     }
03331       
03332   if (iter->changed_stamp != iter->message->changed_stamp)
03333     {
03334       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
03335       return FALSE;
03336     }
03337   
03338   if (iter->pos != iter->end)
03339     {
03340       _dbus_warn ("dbus iterator check failed: can only append at end of message");
03341       return FALSE;
03342     }
03343   
03344   if (iter->pos != _dbus_string_get_length (&iter->message->body))
03345     {
03346       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
03347       return FALSE;
03348     }
03349 
03350   return TRUE;
03351 }
03352 #endif /* DBUS_DISABLE_CHECKS */
03353 
03354 static dbus_bool_t
03355 dbus_message_iter_append_type (DBusMessageRealIter *iter,
03356                                int                  type)
03357 {
03358   const char *data;
03359 
03360   switch (iter->type)
03361     {
03362     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
03363       if (!_dbus_string_append_byte (&iter->message->body, type))
03364         return FALSE;
03365 
03366       if (!_dbus_message_append_byte_to_signature (iter->message, type))
03367         {
03368           _dbus_string_shorten (&iter->message->body, 1);
03369           return FALSE;
03370         }
03371       break;
03372       
03373     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
03374       data = _dbus_string_get_const_data_len (&iter->message->body,
03375                                               iter->array_type_pos, 1);
03376       if (type != *data)
03377         {
03378           _dbus_warn ("Appended element of wrong type for array\n");
03379           return FALSE;
03380         }
03381       break;
03382       
03383     case DBUS_MESSAGE_ITER_TYPE_DICT:
03384       if (!iter->wrote_dict_key)
03385         {
03386           _dbus_warn ("Appending dict data before key name\n");
03387           return FALSE;
03388         }
03389       
03390       if (!_dbus_string_append_byte (&iter->message->body, type))
03391         return FALSE;
03392       
03393       break;
03394       
03395     default:
03396       _dbus_assert_not_reached ("Invalid iter type");
03397       break;
03398     }
03399   
03400   return TRUE;
03401 }
03402 
03403 static void
03404 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
03405 {
03406   iter->changed_stamp = iter->message->changed_stamp;
03407   
03408   /* Set new end of iter */
03409   iter->end = _dbus_string_get_length (&iter->message->body);
03410   iter->pos = iter->end;
03411 
03412   /* Set container length */
03413   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
03414       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
03415     _dbus_marshal_set_uint32 (&iter->message->body,
03416                               iter->message->byte_order,
03417                               iter->container_length_pos,
03418                               iter->end - iter->container_start);
03419   
03420   if (iter->parent_iter)
03421     dbus_message_iter_update_after_change (iter->parent_iter);
03422 }
03423 
03424 static void
03425 dbus_message_iter_append_done (DBusMessageRealIter *iter)
03426 {
03427   iter->message->changed_stamp++;
03428   dbus_message_iter_update_after_change (iter);
03429   iter->wrote_dict_key = FALSE;
03430 }
03431 
03438 dbus_bool_t
03439 dbus_message_iter_append_nil (DBusMessageIter *iter)
03440 {
03441   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03442 
03443   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03444 
03445   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
03446     return FALSE;
03447   
03448   dbus_message_iter_append_done (real);
03449   
03450   return TRUE;
03451 }
03452 
03453 static dbus_bool_t
03454 dbus_message_iter_append_basic (DBusMessageIter *iter,
03455                                 char             type,
03456                                 void            *value)
03457 {
03458   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03459 
03460   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03461 
03462   if (!dbus_message_iter_append_type (real, type))
03463     return FALSE;
03464 
03465   if (!_dbus_marshal_basic_type (&real->message->body,
03466                                  type, value,
03467                                  real->message->byte_order))
03468     {
03469       _dbus_string_set_length (&real->message->body, real->pos);
03470       return FALSE;
03471     }
03472 
03473   dbus_message_iter_append_done (real);
03474   
03475   return TRUE;  
03476 }
03477 
03485 dbus_bool_t
03486 dbus_message_iter_append_boolean (DBusMessageIter *iter,
03487                                   dbus_bool_t     value)
03488 {
03489   unsigned char val = (value != FALSE);
03490   return dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &val);
03491 }
03492 
03500 dbus_bool_t
03501 dbus_message_iter_append_byte (DBusMessageIter *iter,
03502                                unsigned char    value)
03503 {
03504   return dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &value);
03505 }
03506 
03514 dbus_bool_t
03515 dbus_message_iter_append_int32   (DBusMessageIter *iter,
03516                                   dbus_int32_t  value)
03517 {
03518   return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &value);
03519 }
03520 
03528 dbus_bool_t
03529 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
03530                                  dbus_uint32_t    value)
03531 {
03532   return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &value);
03533 }
03534 
03535 #ifdef DBUS_HAVE_INT64
03536 
03546 dbus_bool_t
03547 dbus_message_iter_append_int64   (DBusMessageIter *iter,
03548                                   dbus_int64_t  value)
03549 {
03550   return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &value);
03551 }
03552 
03562 dbus_bool_t
03563 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
03564                                  dbus_uint64_t    value)
03565 {
03566   return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &value);
03567 }
03568 
03569 #endif /* DBUS_HAVE_INT64 */
03570 
03578 dbus_bool_t
03579 dbus_message_iter_append_double (DBusMessageIter *iter,
03580                                  double           value)
03581 {
03582   return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &value);
03583 }
03584 
03594 dbus_bool_t
03595 dbus_message_iter_append_string (DBusMessageIter *iter,
03596                                  const char      *value)
03597 {
03598   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03599 
03600   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03601   
03602   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
03603     return FALSE;
03604   
03605   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03606     {
03607       _dbus_string_set_length (&real->message->body, real->pos);
03608       return FALSE;
03609     }
03610 
03611   dbus_message_iter_append_done (real);
03612   
03613   return TRUE;
03614 }
03615 
03625 dbus_bool_t
03626 dbus_message_iter_append_object_path (DBusMessageIter *iter,
03627                                       const char      *value)
03628 {
03629   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03630 
03631   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03632   
03633   if (!dbus_message_iter_append_type (real, DBUS_TYPE_OBJECT_PATH))
03634     return FALSE;
03635   
03636   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03637     {
03638       _dbus_string_set_length (&real->message->body, real->pos);
03639       return FALSE;
03640     }
03641 
03642   dbus_message_iter_append_done (real);
03643   
03644   return TRUE;
03645 }
03646 
03659 dbus_bool_t
03660 dbus_message_iter_append_custom (DBusMessageIter      *iter,
03661                                  const char           *name,
03662                                  const unsigned char  *data,
03663                                  int                   len)
03664 {
03665   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03666 
03667   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03668 
03669   if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
03670     return FALSE;
03671   
03672    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
03673     {
03674       _dbus_string_set_length (&real->message->body, real->pos);
03675       return FALSE;
03676     }
03677    
03678   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
03679     {
03680       _dbus_string_set_length (&real->message->body, real->pos);
03681       return FALSE;
03682     }
03683 
03684   dbus_message_iter_append_done (real);
03685   
03686   return TRUE;
03687 }
03688 
03689 
03698 dbus_bool_t
03699 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
03700                                    const char      *value)
03701 {
03702   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03703 
03704   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03705   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03706   
03707   if (real->wrote_dict_key)
03708     {
03709       _dbus_warn ("Appending multiple dict key names\n");
03710       return FALSE;
03711     }
03712   
03713   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03714     {
03715       return FALSE;
03716     }
03717 
03718   dbus_message_iter_append_done (real);
03719   real->wrote_dict_key = TRUE;
03720   
03721   return TRUE;
03722 }
03723 
03724 static dbus_bool_t
03725 array_iter_type_mark_done (DBusMessageRealIter *iter)
03726 {
03727   int len_pos;
03728   
03729   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
03730     array_iter_type_mark_done (iter->parent_iter);
03731   else
03732     return TRUE;
03733 
03734   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
03735                                sizeof (dbus_uint32_t));
03736 
03737   /* Empty length for now, backfill later */
03738   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
03739     {
03740       _dbus_string_set_length (&iter->message->body, iter->pos);
03741       return FALSE;
03742     }
03743 
03744   iter->container_start = _dbus_string_get_length (&iter->message->body);
03745   iter->container_length_pos = len_pos;
03746   iter->array_type_done = TRUE;
03747 
03748   return TRUE;
03749 }
03750 
03751 static dbus_bool_t
03752 append_array_type (DBusMessageRealIter *real,
03753                    int                  element_type,
03754                    dbus_bool_t         *array_type_done,
03755                    int                 *array_type_pos)
03756 {
03757   int existing_element_type;
03758   
03759   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
03760     return FALSE;
03761   
03762   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
03763       real->array_type_done)
03764     {
03765       existing_element_type = iter_get_array_type (real, array_type_pos);
03766       if (existing_element_type != element_type)
03767         {
03768           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
03769                       _dbus_type_to_string (element_type),
03770                       _dbus_type_to_string (existing_element_type));
03771           _dbus_string_set_length (&real->message->body, real->pos);
03772           return FALSE;
03773         }
03774       if (array_type_done != NULL)
03775           *array_type_done = TRUE;
03776     }
03777   else
03778     {
03779       if (array_type_pos != NULL)
03780         *array_type_pos = _dbus_string_get_length (&real->message->body);
03781 
03782 
03783       if (!_dbus_message_append_byte_to_signature (real->message, element_type))
03784         {
03785           _dbus_string_set_length (&real->message->body, real->pos);
03786           return FALSE;
03787         }
03788       
03789       /* Append element type */
03790       if (!_dbus_string_append_byte (&real->message->body, element_type))
03791         {
03792           _dbus_message_remove_byte_from_signature (real->message);
03793           _dbus_string_set_length (&real->message->body, real->pos);
03794           return FALSE;
03795         }
03796 
03797       if (array_type_done != NULL)
03798         *array_type_done = element_type != DBUS_TYPE_ARRAY;
03799       
03800       if (element_type != DBUS_TYPE_ARRAY &&
03801           !array_iter_type_mark_done (real))
03802         {
03803           _dbus_message_remove_byte_from_signature (real->message);
03804           return FALSE;
03805         }
03806     }
03807 
03808   return TRUE;
03809 }
03810 
03820 dbus_bool_t
03821 dbus_message_iter_append_array (DBusMessageIter      *iter,
03822                                 DBusMessageIter      *array_iter,
03823                                 int                   element_type)
03824 {
03825   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03826   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
03827   int len_pos;
03828   int array_type_pos;
03829   dbus_bool_t array_type_done;
03830 
03831   if (element_type == DBUS_TYPE_NIL)
03832     {
03833       _dbus_warn ("Can't create NIL arrays\n");
03834       return FALSE;
03835     }
03836   
03837   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03838 
03839   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
03840     return FALSE;
03841 
03842   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
03843 
03844   if (array_type_done)
03845     {
03846       /* Empty length for now, backfill later */
03847       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
03848         {
03849           _dbus_string_set_length (&real->message->body, real->pos);
03850           return FALSE;
03851         }
03852     }
03853   
03854   array_real->parent_iter = real;
03855   array_real->message = real->message;
03856   array_real->changed_stamp = real->message->changed_stamp;
03857   
03858   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
03859   array_real->pos = _dbus_string_get_length (&real->message->body);
03860   array_real->end = array_real->end;
03861   
03862   array_real->container_start = array_real->pos;
03863   array_real->container_length_pos = len_pos;
03864   array_real->wrote_dict_key = 0;
03865   array_real->array_type_done = array_type_done;
03866   array_real->array_type_pos = array_type_pos;
03867 
03868   dbus_message_iter_append_done (array_real);
03869   
03870   return TRUE;
03871 }
03872 
03881 dbus_bool_t
03882 dbus_message_iter_append_dict (DBusMessageIter      *iter,
03883                                DBusMessageIter      *dict_iter)
03884 {
03885   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03886   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
03887   int len_pos;
03888 
03889   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03890   
03891   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
03892     return FALSE;  
03893   
03894   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
03895 
03896   /* Empty length for now, backfill later */
03897   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
03898     {
03899       _dbus_string_set_length (&real->message->body, real->pos);
03900       return FALSE;
03901     }
03902   
03903   dict_real->parent_iter = real;
03904   dict_real->message = real->message;
03905   dict_real->changed_stamp = real->message->changed_stamp;
03906   
03907   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
03908   dict_real->pos = _dbus_string_get_length (&real->message->body);
03909   dict_real->end = dict_real->end;
03910   
03911   dict_real->container_start = dict_real->pos;
03912   dict_real->container_length_pos = len_pos;
03913   dict_real->wrote_dict_key = 0;
03914 
03915   dbus_message_iter_append_done (dict_real);
03916   
03917   real->wrote_dict_key = FALSE;
03918   
03919   return TRUE;
03920 }
03921 
03922 static dbus_bool_t
03923 _dbus_message_iter_append_basic_array (DBusMessageIter *iter,
03924                                        char             type,
03925                                        const void      *value,
03926                                        int              len)
03927 {
03928   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03929 
03930   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03931 
03932   if (!append_array_type (real, type, NULL, NULL))
03933     return FALSE;
03934   
03935   if (!_dbus_marshal_basic_type_array (&real->message->body,
03936                                        type, value, len,
03937                                        real->message->byte_order))
03938     {
03939       _dbus_string_set_length (&real->message->body, real->pos);
03940       return FALSE;
03941     }
03942 
03943   dbus_message_iter_append_done (real);
03944   
03945   return TRUE;
03946 }
03947 
03948 
03962 dbus_bool_t
03963 dbus_message_append_args_valist (DBusMessage *message,
03964                                  int          first_arg_type,
03965                                  va_list      var_args)
03966 {
03967   int type, old_len;
03968   DBusMessageIter iter;
03969 
03970   _dbus_return_val_if_fail (message != NULL, FALSE);
03971   
03972   old_len = _dbus_string_get_length (&message->body);
03973   
03974   type = first_arg_type;
03975 
03976   dbus_message_append_iter_init (message, &iter);
03977   
03978   while (type != DBUS_TYPE_INVALID)
03979     {
03980       switch (type)
03981         {
03982         case DBUS_TYPE_NIL:
03983           if (!dbus_message_iter_append_nil (&iter))
03984             goto errorout;
03985           break;
03986         case DBUS_TYPE_BYTE:
03987           /* Read an int from varargs, because the original unsigned
03988            * char has been promoted to int. */
03989           if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, int)))
03990             goto errorout;
03991           break;
03992         case DBUS_TYPE_BOOLEAN:
03993           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
03994             goto errorout;
03995           break;
03996         case DBUS_TYPE_INT32:
03997           /* FIXME this is probably wrong, because an int passed in probably gets
03998            * converted to plain "int" not necessarily 32-bit.
03999            */
04000           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
04001             goto errorout;
04002           break;
04003         case DBUS_TYPE_UINT32:
04004           /* FIXME this is probably wrong, because an int passed in probably gets
04005            * converted to plain "int" not necessarily 32-bit.
04006            */
04007           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
04008             goto errorout;          
04009           break;
04010 #ifdef DBUS_HAVE_INT64
04011         case DBUS_TYPE_INT64:
04012           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
04013             goto errorout;
04014           break;
04015         case DBUS_TYPE_UINT64:
04016           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
04017             goto errorout;          
04018           break;
04019 #endif /* DBUS_HAVE_INT64 */
04020         case DBUS_TYPE_DOUBLE:
04021           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
04022             goto errorout;
04023           break;
04024         case DBUS_TYPE_STRING:
04025           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
04026             goto errorout;
04027           break;
04028         case DBUS_TYPE_OBJECT_PATH:
04029           if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
04030             goto errorout;
04031           break;
04032         case DBUS_TYPE_CUSTOM:
04033           {
04034             const char *name;
04035             unsigned char *data;
04036             int len;
04037  
04038             name = va_arg (var_args, const char *);
04039             data = va_arg (var_args, unsigned char *);
04040             len = va_arg (var_args, int);
04041 
04042             if (!dbus_message_iter_append_custom (&iter, name, data, len))
04043               goto errorout;
04044             break;
04045           }
04046         case DBUS_TYPE_ARRAY:
04047           {
04048             void *data;
04049             int len, type;
04050  
04051             type = va_arg (var_args, int);
04052             data = va_arg (var_args, void *);
04053             len = va_arg (var_args, int);
04054 
04055             switch (type)
04056               {
04057               case DBUS_TYPE_BYTE:
04058               case DBUS_TYPE_BOOLEAN:
04059               case DBUS_TYPE_INT32:
04060               case DBUS_TYPE_UINT32:
04061 #ifdef DBUS_HAVE_INT64
04062               case DBUS_TYPE_INT64:
04063               case DBUS_TYPE_UINT64:
04064 #endif /* DBUS_HAVE_INT64 */
04065               case DBUS_TYPE_DOUBLE:
04066                 if (!_dbus_message_iter_append_basic_array (&iter, type, data, len))
04067                   goto errorout;
04068                 break;
04069               case DBUS_TYPE_STRING:
04070                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
04071                   goto errorout;
04072                 break;
04073               case DBUS_TYPE_OBJECT_PATH:
04074                 if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
04075                   goto errorout;
04076                 break;
04077               case DBUS_TYPE_NIL:
04078               case DBUS_TYPE_ARRAY:
04079               case DBUS_TYPE_CUSTOM:
04080               case DBUS_TYPE_DICT:
04081                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
04082                 goto errorout;
04083               default:
04084                 _dbus_warn ("Unknown field type %d\n", type);
04085                 goto errorout;
04086               }
04087           }
04088           break;
04089           
04090         case DBUS_TYPE_DICT:
04091           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
04092           goto errorout;
04093         default:
04094           _dbus_warn ("Unknown field type %d\n", type);
04095           goto errorout;
04096         }
04097 
04098       type = va_arg (var_args, int);
04099     }
04100 
04101   return TRUE;
04102 
04103  errorout:
04104   return FALSE;
04105 }
04106 
04115 dbus_bool_t
04116 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
04117                                         unsigned const char *value,
04118                                         int                  len)
04119 {
04120   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BOOLEAN,
04121                                                 value, len);
04122 }
04123 
04132 dbus_bool_t
04133 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
04134                                       const dbus_int32_t *value,
04135                                       int                 len)
04136 {
04137   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT32,
04138                                                 value, len);
04139 }
04140 
04149 dbus_bool_t
04150 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
04151                                        const dbus_uint32_t *value,
04152                                        int                  len)
04153 {
04154   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT32,
04155                                                 value, len);
04156 }
04157 
04158 #ifdef DBUS_HAVE_INT64
04159 
04170 dbus_bool_t
04171 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
04172                                       const dbus_int64_t *value,
04173                                       int                 len)
04174 {
04175   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT64,
04176                                                 value, len);
04177 }
04178 
04189 dbus_bool_t
04190 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
04191                                        const dbus_uint64_t *value,
04192                                        int                  len)
04193 {
04194   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT64,
04195                                                 value, len);
04196 }
04197 #endif /* DBUS_HAVE_INT64 */
04198 
04207 dbus_bool_t
04208 dbus_message_iter_append_double_array (DBusMessageIter *iter,
04209                                        const double    *value,
04210                                        int              len)
04211 {
04212   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_DOUBLE,
04213                                                 value, len);
04214 }
04215 
04224 dbus_bool_t
04225 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
04226                                      unsigned const char *value,
04227                                      int                  len)
04228 {
04229   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BYTE,
04230                                                 value, len);
04231 }
04232 
04241 dbus_bool_t
04242 dbus_message_iter_append_string_array (DBusMessageIter *iter,
04243                                        const char     **value,
04244                                        int              len)
04245 {
04246   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04247 
04248   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04249 
04250   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
04251     return FALSE;
04252   
04253   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04254     {
04255       _dbus_string_set_length (&real->message->body, real->pos);
04256       return FALSE;
04257     }
04258 
04259   dbus_message_iter_append_done (real);
04260   
04261   return TRUE;
04262 }
04263 
04272 dbus_bool_t
04273 dbus_message_iter_append_object_path_array (DBusMessageIter *iter,
04274                                             const char     **value,
04275                                             int              len)
04276 {
04277   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04278 
04279   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04280 
04281   if (!append_array_type (real, DBUS_TYPE_OBJECT_PATH, NULL, NULL))
04282     return FALSE;
04283   
04284   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04285     {
04286       _dbus_string_set_length (&real->message->body, real->pos);
04287       return FALSE;
04288     }
04289 
04290   dbus_message_iter_append_done (real);
04291   
04292   return TRUE;
04293 }
04294 
04302 dbus_bool_t
04303 dbus_message_set_sender (DBusMessage  *message,
04304                          const char   *sender)
04305 {
04306   _dbus_return_val_if_fail (message != NULL, FALSE);
04307   _dbus_return_val_if_fail (!message->locked, FALSE);
04308 
04309   return set_string_field (message,
04310                            DBUS_HEADER_FIELD_SENDER,
04311                            DBUS_TYPE_STRING,
04312                            sender);
04313 }
04314 
04325 void
04326 dbus_message_set_no_reply (DBusMessage *message,
04327                            dbus_bool_t  no_reply)
04328 {
04329   char *header;
04330 
04331   _dbus_return_if_fail (message != NULL);
04332   _dbus_return_if_fail (!message->locked);
04333   
04334   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04335   
04336   if (no_reply)
04337     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
04338   else
04339     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
04340 }
04341 
04349 dbus_bool_t
04350 dbus_message_get_no_reply (DBusMessage *message)
04351 {
04352   const char *header;
04353 
04354   _dbus_return_val_if_fail (message != NULL, FALSE);
04355   
04356   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04357 
04358   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
04359 }
04360 
04361 
04371 void
04372 dbus_message_set_auto_activation (DBusMessage *message,
04373                                   dbus_bool_t  auto_activation)
04374 {
04375   char *header;
04376 
04377   _dbus_return_if_fail (message != NULL);
04378   _dbus_return_if_fail (!message->locked);
04379   
04380   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04381   
04382   if (auto_activation)
04383     *header |= DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04384   else
04385     *header &= ~DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04386 }
04387 
04395 dbus_bool_t
04396 dbus_message_get_auto_activation (DBusMessage *message)
04397 {
04398   const char *header;
04399 
04400   _dbus_return_val_if_fail (message != NULL, FALSE);
04401   
04402   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04403 
04404   return (*header & DBUS_HEADER_FLAG_AUTO_ACTIVATION) != 0;
04405 }
04406 
04414 const char*
04415 dbus_message_get_sender (DBusMessage *message)
04416 {
04417   _dbus_return_val_if_fail (message != NULL, NULL);
04418   
04419   return get_string_field (message, 
04420                            DBUS_HEADER_FIELD_SENDER,
04421                            NULL);
04422 }
04423 
04439 const char*
04440 dbus_message_get_signature (DBusMessage *message)
04441 {
04442   _dbus_return_val_if_fail (message != NULL, NULL);
04443 
04444   return get_string_field (message, 
04445                            DBUS_HEADER_FIELD_SIGNATURE,
04446                            NULL);
04447 }
04448 
04449 static dbus_bool_t
04450 _dbus_message_has_type_interface_member (DBusMessage *message,
04451                                          int          type,
04452                                          const char  *interface,
04453                                          const char  *method)
04454 {
04455   const char *n;
04456 
04457   _dbus_assert (message != NULL);
04458   _dbus_assert (interface != NULL);
04459   _dbus_assert (method != NULL);
04460 
04461   if (dbus_message_get_type (message) != type)
04462     return FALSE;
04463 
04464   /* Optimize by checking the short method name first
04465    * instead of the longer interface name
04466    */  
04467 
04468   n = dbus_message_get_member (message);
04469 
04470   if (n && strcmp (n, method) == 0)
04471     {
04472       n = dbus_message_get_interface (message);
04473       
04474       if (n && strcmp (n, interface) == 0)
04475         return TRUE;
04476     }
04477 
04478   return FALSE;
04479 }
04480 
04493 dbus_bool_t
04494 dbus_message_is_method_call (DBusMessage *message,
04495                              const char  *interface,
04496                              const char  *method)
04497 {
04498   _dbus_return_val_if_fail (message != NULL, FALSE);
04499   _dbus_return_val_if_fail (interface != NULL, FALSE);
04500   _dbus_return_val_if_fail (method != NULL, FALSE);
04501 
04502   return _dbus_message_has_type_interface_member (message,
04503                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
04504                                                   interface, method);
04505 }
04506 
04519 dbus_bool_t
04520 dbus_message_is_signal (DBusMessage *message,
04521                         const char  *interface,
04522                         const char  *signal_name)
04523 {
04524   _dbus_return_val_if_fail (message != NULL, FALSE);
04525   _dbus_return_val_if_fail (interface != NULL, FALSE);
04526   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
04527 
04528   return _dbus_message_has_type_interface_member (message,
04529                                                   DBUS_MESSAGE_TYPE_SIGNAL,
04530                                                   interface, signal_name);
04531 }
04532 
04543 dbus_bool_t
04544 dbus_message_is_error (DBusMessage *message,
04545                        const char  *error_name)
04546 {
04547   const char *n;
04548   
04549   _dbus_return_val_if_fail (message != NULL, FALSE);
04550   _dbus_return_val_if_fail (error_name != NULL, FALSE);
04551   _dbus_return_val_if_fail (is_valid_error_name (error_name), FALSE);
04552   
04553   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04554     return FALSE;
04555 
04556   n = dbus_message_get_error_name (message);
04557 
04558   if (n && strcmp (n, error_name) == 0)
04559     return TRUE;
04560   else
04561     return FALSE;
04562 }
04563 
04574 dbus_bool_t
04575 dbus_message_has_destination (DBusMessage  *message,
04576                               const char   *service)
04577 {
04578   const char *s;
04579 
04580   _dbus_return_val_if_fail (message != NULL, FALSE);
04581   _dbus_return_val_if_fail (service != NULL, FALSE);
04582   
04583   s = dbus_message_get_destination (message);
04584 
04585   if (s && strcmp (s, service) == 0)
04586     return TRUE;
04587   else
04588     return FALSE;
04589 }
04590 
04605 dbus_bool_t
04606 dbus_message_has_sender (DBusMessage  *message,
04607                          const char   *service)
04608 {
04609   const char *s;
04610 
04611   _dbus_return_val_if_fail (message != NULL, FALSE);
04612   _dbus_return_val_if_fail (service != NULL, FALSE);
04613   
04614   s = dbus_message_get_sender (message);
04615 
04616   if (s && strcmp (s, service) == 0)
04617     return TRUE;
04618   else
04619     return FALSE;
04620 }
04621 
04631 dbus_bool_t
04632 dbus_message_has_signature (DBusMessage   *message,
04633                             const char    *signature)
04634 {
04635   const char *s;
04636 
04637   _dbus_return_val_if_fail (message != NULL, FALSE);
04638   _dbus_return_val_if_fail (signature != NULL, FALSE);
04639   
04640   s = dbus_message_get_signature (message);
04641 
04642   if (s && strcmp (s, signature) == 0)
04643     return TRUE;
04644   else
04645     return FALSE;
04646 }
04647 
04665 dbus_bool_t
04666 dbus_set_error_from_message (DBusError   *error,
04667                              DBusMessage *message)
04668 {
04669   char *str;
04670 
04671   _dbus_return_val_if_fail (message != NULL, FALSE);
04672   _dbus_return_val_if_error_is_set (error, FALSE);
04673   
04674   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04675     return FALSE;
04676 
04677   str = NULL;
04678   dbus_message_get_args (message, NULL,
04679                          DBUS_TYPE_STRING, &str,
04680                          DBUS_TYPE_INVALID);
04681 
04682   dbus_set_error (error, dbus_message_get_error_name (message),
04683                   str ? "%s" : NULL, str);
04684 
04685   dbus_free (str);
04686   
04687   return TRUE;
04688 }
04689 
04714 /* we definitely use signed ints for sizes, so don't exceed
04715  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
04716  * over 128M is pretty nuts anyhow.
04717  */
04718 
04722 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
04723 
04728 struct DBusMessageLoader
04729 {
04730   int refcount;        
04732   DBusString data;     
04734   DBusList *messages;  
04736   long max_message_size; 
04738   unsigned int buffer_outstanding : 1; 
04740   unsigned int corrupted : 1; 
04741 };
04742 
04753 #define INITIAL_LOADER_DATA_LEN 32
04754 
04761 DBusMessageLoader*
04762 _dbus_message_loader_new (void)
04763 {
04764   DBusMessageLoader *loader;
04765 
04766   loader = dbus_new0 (DBusMessageLoader, 1);
04767   if (loader == NULL)
04768     return NULL;
04769   
04770   loader->refcount = 1;
04771 
04772   /* Try to cap message size at something that won't *totally* hose
04773    * the system if we have a couple of them.
04774    */
04775   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
04776   
04777   if (!_dbus_string_init (&loader->data))
04778     {
04779       dbus_free (loader);
04780       return NULL;
04781     }
04782 
04783   /* preallocate the buffer for speed, ignore failure */
04784   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
04785   _dbus_string_set_length (&loader->data, 0);
04786   
04787   return loader;
04788 }
04789 
04796 DBusMessageLoader *
04797 _dbus_message_loader_ref (DBusMessageLoader *loader)
04798 {
04799   loader->refcount += 1;
04800 
04801   return loader;
04802 }
04803 
04810 void
04811 _dbus_message_loader_unref (DBusMessageLoader *loader)
04812 {
04813   loader->refcount -= 1;
04814   if (loader->refcount == 0)
04815     {
04816       _dbus_list_foreach (&loader->messages,
04817                           (DBusForeachFunction) dbus_message_unref,
04818                           NULL);
04819       _dbus_list_clear (&loader->messages);
04820       _dbus_string_free (&loader->data);
04821       dbus_free (loader);
04822     }
04823 }
04824 
04843 void
04844 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
04845                                  DBusString        **buffer)
04846 {
04847   _dbus_assert (!loader->buffer_outstanding);
04848 
04849   *buffer = &loader->data;
04850   
04851   loader->buffer_outstanding = TRUE;
04852 }
04853 
04858 #define DBUS_MINIMUM_HEADER_SIZE 16
04859 
04860 static dbus_bool_t
04861 decode_string_field (const DBusString   *data,
04862                      int                 field,
04863                      HeaderField        *header_field,
04864                      DBusString         *field_data,
04865                      int                 pos,
04866                      int                 type)
04867 {
04868   int string_data_pos;
04869 
04870   _dbus_assert (header_field != NULL);
04871   _dbus_assert (field_data != NULL);
04872   
04873   if (header_field->name_offset >= 0)
04874     {
04875       _dbus_verbose ("%s field provided twice\n",
04876                      _dbus_header_field_to_string (field));
04877       return FALSE;
04878     }
04879 
04880   if (type != DBUS_TYPE_STRING)
04881     {
04882       _dbus_verbose ("%s field has wrong type %s\n",
04883                      _dbus_header_field_to_string (field),
04884                      _dbus_type_to_string (type));
04885       return FALSE;
04886     }
04887 
04888   /* skip padding after typecode, skip string length;
04889    * we assume that the string arg has already been validated
04890    * for sanity and UTF-8
04891    */
04892   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
04893   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
04894   
04895   _dbus_string_init_const (field_data,
04896                            _dbus_string_get_const_data (data) + string_data_pos);
04897 
04898   header_field->name_offset  = pos - 2;
04899   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
04900   
04901 #if 0
04902   _dbus_verbose ("Found field %s at offset %d\n",
04903                  _dbus_header_field_to_string (field),
04904                  header_field->value_offset);
04905 #endif
04906 
04907   return TRUE;
04908 }
04909 
04910 /* FIXME because the service/interface/member/error names are already
04911  * validated to be in the particular ASCII subset, UTF-8 validating
04912  * them could be skipped as a probably-interesting optimization.
04913  * The UTF-8 validation definitely shows up in profiles.
04914  */
04915 static dbus_bool_t
04916 decode_header_data (const DBusString   *data,
04917                     int                 header_len,
04918                     int                 byte_order,
04919                     int                 message_type,
04920                     HeaderField         fields[DBUS_HEADER_FIELD_LAST + 1],
04921                     int                *message_padding)
04922 {
04923   DBusString field_data;
04924   int pos, new_pos;
04925   int i;
04926   int field;
04927   int type;
04928   dbus_bool_t signature_required;
04929   
04930   if (header_len < 16)
04931     {
04932       _dbus_verbose ("Header length %d is too short\n", header_len);
04933       return FALSE;
04934     }
04935   
04936   i = 0;
04937   while (i <= DBUS_HEADER_FIELD_LAST)
04938     {
04939       fields[i].name_offset  = -1;
04940       fields[i].value_offset = -1;
04941       ++i;
04942     }
04943   
04944   pos = 16;
04945   while (pos < header_len)
04946     {
04947       field = _dbus_string_get_byte (data, pos);
04948       if (field == DBUS_HEADER_FIELD_INVALID)
04949         break; /* Must be padding */
04950       pos++;
04951 
04952       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
04953         {
04954           _dbus_verbose ("Failed to validate type of named header field pos = %d\n",
04955                          pos);
04956           return FALSE;
04957         }
04958       
04959       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
04960         {
04961           _dbus_verbose ("Failed to validate argument to named header field pos = %d\n",
04962                          pos);
04963           return FALSE;
04964         }
04965 
04966       if (new_pos > header_len)
04967         {
04968           _dbus_verbose ("Named header field tries to extend beyond header length\n");
04969           return FALSE;
04970         }
04971       
04972       switch (field)
04973         {
04974         case DBUS_HEADER_FIELD_DESTINATION:
04975           if (!decode_string_field (data, field, &fields[field],
04976                                     &field_data, pos, type))
04977             return FALSE;
04978 
04979           if (!_dbus_string_validate_service (&field_data, 0,
04980                                               _dbus_string_get_length (&field_data)))
04981             {
04982               _dbus_verbose ("service field has invalid content \"%s\"\n",
04983                              _dbus_string_get_const_data (&field_data));
04984               return FALSE;
04985             }
04986           break;
04987 
04988         case DBUS_HEADER_FIELD_INTERFACE:
04989           if (!decode_string_field (data, field, &fields[field],
04990                                     &field_data, pos, type))
04991             return FALSE;
04992 
04993           if (!_dbus_string_validate_interface (&field_data, 0,
04994                                                 _dbus_string_get_length (&field_data)))
04995             {
04996               _dbus_verbose ("interface field has invalid content \"%s\"\n",
04997                              _dbus_string_get_const_data (&field_data));
04998               return FALSE;
04999             }
05000       
05001           if (_dbus_string_equal_c_str (&field_data,
05002                                         DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
05003             {
05004               _dbus_verbose ("Message is on the local interface\n");
05005               return FALSE;
05006             }
05007           break;
05008 
05009         case DBUS_HEADER_FIELD_MEMBER:
05010           if (!decode_string_field (data, field, &fields[field],
05011                                     &field_data, pos, type))
05012             return FALSE;
05013           
05014           if (!_dbus_string_validate_member (&field_data, 0,
05015                                              _dbus_string_get_length (&field_data)))
05016             {
05017               _dbus_verbose ("member field has invalid content \"%s\"\n",
05018                              _dbus_string_get_const_data (&field_data));
05019               return FALSE;
05020             }
05021           break;
05022 
05023         case DBUS_HEADER_FIELD_ERROR_NAME:
05024           if (!decode_string_field (data, field, &fields[field],
05025                                     &field_data, pos, type))
05026             return FALSE;
05027           
05028           if (!_dbus_string_validate_error_name (&field_data, 0,
05029                                                  _dbus_string_get_length (&field_data)))
05030             {
05031               _dbus_verbose ("error-name field has invalid content \"%s\"\n",
05032                              _dbus_string_get_const_data (&field_data));
05033               return FALSE;
05034             }
05035           break;
05036           
05037         case DBUS_HEADER_FIELD_SENDER:
05038           if (!decode_string_field (data, field, &fields[field],
05039                                     &field_data, pos, type))
05040             return FALSE;
05041           
05042           if (!_dbus_string_validate_service (&field_data, 0,
05043                                               _dbus_string_get_length (&field_data)))
05044             {
05045               _dbus_verbose ("sender-service field has invalid content \"%s\"\n",
05046                              _dbus_string_get_const_data (&field_data));
05047               return FALSE;
05048             }
05049           break;
05050 
05051         case DBUS_HEADER_FIELD_PATH:
05052 
05053           /* Path was already validated as part of standard
05054            * type validation, since there's an OBJECT_PATH
05055            * type.
05056            */
05057           
05058           if (fields[field].name_offset >= 0)
05059             {
05060               _dbus_verbose ("path field provided twice\n");
05061               return FALSE;
05062             }
05063           if (type != DBUS_TYPE_OBJECT_PATH)
05064             {
05065               _dbus_verbose ("path field has wrong type\n");
05066               return FALSE;
05067             }
05068 
05069           fields[field].name_offset  = pos - 2;
05070           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05071 
05072           /* No forging signals from the local path */
05073           {
05074             const char *s;
05075             s = _dbus_string_get_const_data_len (data,
05076                                                  fields[field].value_offset,
05077                                                  _dbus_string_get_length (data) -
05078                                                  fields[field].value_offset);
05079             if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
05080               {
05081                 _dbus_verbose ("Message is on the local path\n");
05082                 return FALSE;
05083               }
05084           }
05085           
05086           _dbus_verbose ("Found path at offset %d\n",
05087                          fields[field].value_offset);
05088           break;
05089           
05090         case DBUS_HEADER_FIELD_REPLY_SERIAL:
05091           if (fields[field].name_offset >= 0)
05092             {
05093               _dbus_verbose ("reply field provided twice\n");
05094               return FALSE;
05095             }
05096 
05097           if (type != DBUS_TYPE_UINT32)
05098             {
05099               _dbus_verbose ("reply field has wrong type\n");
05100               return FALSE;
05101             }
05102           
05103           fields[field].name_offset  = pos - 2;
05104           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05105 
05106           _dbus_verbose ("Found reply serial %u at offset %d\n",
05107                          _dbus_demarshal_uint32 (data,
05108                                                  byte_order,
05109                                                  fields[field].value_offset,
05110                                                  NULL),
05111                          fields[field].value_offset);
05112           break;
05113 
05114         case DBUS_HEADER_FIELD_SIGNATURE:
05115           if (!decode_string_field (data, field, &fields[field],
05116                                     &field_data, pos, type))
05117             return FALSE;
05118 
05119 #if 0
05120           /* FIXME */
05121           if (!_dbus_string_validate_signature (&field_data, 0,
05122                                                 _dbus_string_get_length (&field_data)))
05123             {
05124               _dbus_verbose ("signature field has invalid content \"%s\"\n",
05125                              _dbus_string_get_const_data (&field_data));
05126               return FALSE;
05127             }
05128 #endif
05129           break;
05130           
05131         default:
05132           _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
05133                          field, pos);
05134         }
05135       
05136       pos = new_pos;
05137     }
05138 
05139   if (pos < header_len)
05140     {
05141       /* Alignment padding, verify that it's nul */
05142       if ((header_len - pos) >= 8)
05143         {
05144           _dbus_verbose ("too much header alignment padding\n");
05145           return FALSE;
05146         }
05147 
05148       if (!_dbus_string_validate_nul (data,
05149                                       pos, (header_len - pos)))
05150         {
05151           _dbus_verbose ("header alignment padding is not nul\n");
05152           return FALSE;
05153         }
05154     }
05155 
05156   /* Depending on message type, enforce presence of certain fields. */
05157   signature_required = TRUE;
05158   
05159   switch (message_type)
05160     {
05161     case DBUS_MESSAGE_TYPE_SIGNAL:
05162     case DBUS_MESSAGE_TYPE_METHOD_CALL:
05163       if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
05164         {
05165           _dbus_verbose ("No path field provided\n");
05166           return FALSE;
05167         }
05168       /* FIXME make this optional, only for method calls */
05169       if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
05170         {
05171           _dbus_verbose ("No interface field provided\n");
05172           return FALSE;
05173         }
05174       if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
05175         {
05176           _dbus_verbose ("No member field provided\n");
05177           return FALSE;
05178         }
05179       break;
05180     case DBUS_MESSAGE_TYPE_ERROR:
05181       if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
05182         {
05183           _dbus_verbose ("No error-name field provided\n");
05184           return FALSE;
05185         }
05186       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05187         {
05188           _dbus_verbose ("No reply serial field provided in error\n");
05189           return FALSE;
05190         }
05191       break;
05192     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
05193       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05194         {
05195           _dbus_verbose ("No reply serial field provided in method return\n");
05196           return FALSE;
05197         }
05198       break;
05199     default:
05200       /* An unknown type, spec requires us to ignore it */
05201       signature_required = FALSE;
05202       break;
05203     }
05204 
05205   /* FIXME allow omitting signature field for a message with no arguments? */
05206   if (signature_required)
05207     {
05208       if (fields[DBUS_HEADER_FIELD_SIGNATURE].value_offset < 0)
05209         {
05210           _dbus_verbose ("No signature field provided\n");
05211           return FALSE;
05212         }
05213     }
05214   
05215   if (message_padding)
05216     *message_padding = header_len - pos;  
05217   
05218   return TRUE;
05219 }
05220 
05231 void
05232 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
05233                                     DBusString         *buffer,
05234                                     int                 bytes_read)
05235 {
05236   _dbus_assert (loader->buffer_outstanding);
05237   _dbus_assert (buffer == &loader->data);
05238 
05239   loader->buffer_outstanding = FALSE;
05240 }
05241 
05242 static dbus_bool_t
05243 load_one_message (DBusMessageLoader *loader,
05244                   int                byte_order,
05245                   int                message_type,
05246                   int                header_len,
05247                   int                body_len)
05248 {
05249   DBusMessage *message;
05250   HeaderField fields[DBUS_HEADER_FIELD_LAST + 1];
05251   int i;
05252   int next_arg;
05253   dbus_bool_t oom;
05254   int header_padding;
05255   
05256   message = NULL;
05257   oom = FALSE;
05258   
05259 #if 0
05260   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
05261 #endif    
05262 
05263   if (!decode_header_data (&loader->data,
05264                            header_len, byte_order,
05265                            message_type,
05266                            fields, &header_padding))
05267     {
05268       _dbus_verbose ("Header was invalid\n");
05269       loader->corrupted = TRUE;
05270       goto failed;
05271     }
05272           
05273   next_arg = header_len;
05274   while (next_arg < (header_len + body_len))
05275     {
05276       int type;
05277       int prev = next_arg;
05278 
05279       if (!_dbus_marshal_validate_type (&loader->data, next_arg,
05280                                         &type, &next_arg))
05281         {
05282           _dbus_verbose ("invalid typecode at offset %d\n", prev);
05283           loader->corrupted = TRUE;
05284           goto failed;
05285         }
05286       
05287       if (!_dbus_marshal_validate_arg (&loader->data,
05288                                        byte_order,
05289                                        0,
05290                                        type, -1,
05291                                        next_arg,
05292                                        &next_arg))
05293         {
05294           _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
05295           loader->corrupted = TRUE;
05296           goto failed;
05297         }
05298 
05299       _dbus_assert (next_arg > prev);
05300     }
05301           
05302   if (next_arg > (header_len + body_len))
05303     {
05304       _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
05305                      next_arg, header_len, body_len,
05306                      header_len + body_len);
05307       loader->corrupted = TRUE;
05308       goto failed;
05309     }
05310 
05311   message = dbus_message_new_empty_header ();
05312   if (message == NULL)
05313     {
05314       _dbus_verbose ("Failed to allocate empty message\n");
05315       oom = TRUE;
05316       goto failed;
05317     }
05318 
05319   message->byte_order = byte_order;
05320   message->header_padding = header_padding;
05321           
05322   /* Copy in the offsets we found */
05323   i = 0;
05324   while (i <= DBUS_HEADER_FIELD_LAST)
05325     {
05326       message->header_fields[i] = fields[i];
05327       ++i;
05328     }
05329           
05330   if (!_dbus_list_append (&loader->messages, message))
05331     {
05332       _dbus_verbose ("Failed to append new message to loader queue\n");
05333       oom = TRUE;
05334       goto failed;
05335     }
05336 
05337   _dbus_assert (_dbus_string_get_length (&message->header) == 0);
05338   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
05339 
05340   _dbus_assert (_dbus_string_get_length (&loader->data) >=
05341                 (header_len + body_len));
05342           
05343   if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
05344     {
05345       _dbus_verbose ("Failed to move header into new message\n");
05346       oom = TRUE;
05347       goto failed;
05348     }
05349           
05350   if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
05351     {
05352       _dbus_verbose ("Failed to move body into new message\n");
05353       
05354       oom = TRUE;
05355       goto failed;
05356     }
05357 
05358   _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
05359   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
05360 
05361   /* Fill in caches (we checked the types of these fields
05362    * earlier)
05363    */
05364   message->reply_serial = get_uint_field (message,
05365                                           DBUS_HEADER_FIELD_REPLY_SERIAL);
05366   
05367   message->client_serial = _dbus_demarshal_uint32 (&message->header,
05368                                                    message->byte_order,
05369                                                    CLIENT_SERIAL_OFFSET,
05370                                                    NULL);
05371   if (message->client_serial == 0 ||
05372       (message->header_fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset >= 0 && message->reply_serial == 0))
05373     {
05374       _dbus_verbose ("client_serial = %d reply_serial = %d, one of these no good\n",
05375                      message->client_serial,
05376                      message->reply_serial);
05377       
05378       loader->corrupted = TRUE;
05379       goto failed;
05380     }
05381   
05382   _dbus_verbose ("Loaded message %p\n", message);
05383 
05384   _dbus_assert (!oom);
05385   _dbus_assert (!loader->corrupted);
05386 
05387   return TRUE;
05388 
05389  failed:
05390   
05391   /* Clean up */
05392   
05393   if (message != NULL)
05394     {
05395       /* Put the data back so we can try again later if it was an OOM issue */
05396       if (_dbus_string_get_length (&message->body) > 0)
05397         {
05398           dbus_bool_t result;
05399           
05400           result = _dbus_string_copy_len (&message->body, 0, body_len,
05401                                           &loader->data, 0);
05402           
05403           _dbus_assert (result); /* because DBusString never reallocs smaller */
05404         }
05405       
05406       if (_dbus_string_get_length (&message->header) > 0)
05407         {
05408           dbus_bool_t result;
05409           
05410           result = _dbus_string_copy_len (&message->header, 0, header_len,
05411                                           &loader->data, 0);
05412           
05413           _dbus_assert (result); /* because DBusString never reallocs smaller */
05414         }
05415 
05416       /* does nothing if the message isn't in the list */
05417       _dbus_list_remove_last (&loader->messages, message);
05418 
05419       dbus_message_unref (message);
05420     }
05421 
05422   
05423   return !oom;
05424 }
05425 
05439 dbus_bool_t
05440 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
05441 {
05442   while (!loader->corrupted && _dbus_string_get_length (&loader->data) >= 16)
05443     {
05444       const char *header_data;
05445       int byte_order, message_type, header_len, body_len;
05446       dbus_uint32_t header_len_unsigned, body_len_unsigned;
05447       
05448       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
05449 
05450       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
05451 
05452       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
05453         {
05454           _dbus_verbose ("Message has protocol version %d ours is %d\n",
05455                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
05456           loader->corrupted = TRUE;
05457           return TRUE;
05458         }
05459       
05460       byte_order = header_data[BYTE_ORDER_OFFSET];
05461 
05462       if (byte_order != DBUS_LITTLE_ENDIAN &&
05463           byte_order != DBUS_BIG_ENDIAN)
05464         {
05465           _dbus_verbose ("Message with bad byte order '%c' received\n",
05466                          byte_order);
05467           loader->corrupted = TRUE;
05468           return TRUE;
05469         }
05470 
05471       /* Unknown types are ignored, but INVALID is
05472        * disallowed
05473        */
05474       message_type = header_data[TYPE_OFFSET];
05475       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
05476         {
05477           _dbus_verbose ("Message with bad type '%d' received\n",
05478                          message_type);
05479           loader->corrupted = TRUE;
05480           return TRUE;
05481         }      
05482       
05483       header_len_unsigned = _dbus_unpack_uint32 (byte_order, 
05484                                                  (const unsigned char *) header_data + 4);
05485       body_len_unsigned = _dbus_unpack_uint32 (byte_order, 
05486                                                (const unsigned char *) header_data + 8);
05487 
05488       if (header_len_unsigned < 16)
05489         {
05490           _dbus_verbose ("Message had broken too-small header length %u\n",
05491                          header_len_unsigned);
05492           loader->corrupted = TRUE;
05493           return TRUE;
05494         }
05495 
05496       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
05497           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
05498         {
05499           _dbus_verbose ("Header or body length too large (%u %u)\n",
05500                          header_len_unsigned,
05501                          body_len_unsigned);
05502           loader->corrupted = TRUE;
05503           return TRUE;
05504         }
05505 
05506       /* Now that we know the values are in signed range, get
05507        * rid of stupid unsigned, just causes bugs
05508        */
05509       header_len = header_len_unsigned;
05510       body_len = body_len_unsigned;
05511 
05512       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
05513         {
05514           
05515           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
05516                          header_len);
05517           loader->corrupted = TRUE;
05518           return TRUE;
05519         }
05520       
05521       if (header_len + body_len > loader->max_message_size)
05522         {
05523           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
05524                          header_len, body_len, loader->max_message_size);
05525           loader->corrupted = TRUE;
05526           return TRUE;
05527         }
05528 
05529       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
05530         {
05531           if (!load_one_message (loader, byte_order, message_type,
05532                                  header_len, body_len))
05533             return FALSE;
05534         }
05535       else
05536         return TRUE;
05537     }
05538 
05539   return TRUE;
05540 }
05541 
05549 DBusMessage*
05550 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
05551 {
05552   if (loader->messages)
05553     return loader->messages->data;
05554   else
05555     return NULL;
05556 }
05557 
05566 DBusMessage*
05567 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
05568 {
05569   return _dbus_list_pop_first (&loader->messages);
05570 }
05571 
05580 DBusList*
05581 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
05582 {
05583   return _dbus_list_pop_first_link (&loader->messages);
05584 }
05585 
05592 void
05593 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
05594                                            DBusList           *link)
05595 {
05596   _dbus_list_prepend_link (&loader->messages, link);
05597 }
05598 
05608 dbus_bool_t
05609 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
05610 {
05611   return loader->corrupted;
05612 }
05613 
05620 void
05621 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
05622                                            long                size)
05623 {
05624   if (size > MAX_SANE_MESSAGE_SIZE)
05625     {
05626       _dbus_verbose ("clamping requested max message size %ld to %d\n",
05627                      size, MAX_SANE_MESSAGE_SIZE);
05628       size = MAX_SANE_MESSAGE_SIZE;
05629     }
05630   loader->max_message_size = size;
05631 }
05632 
05639 long
05640 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
05641 {
05642   return loader->max_message_size;
05643 }
05644 
05645 static DBusDataSlotAllocator slot_allocator;
05646 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
05647 
05662 dbus_bool_t
05663 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
05664 {
05665   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05666                                           _DBUS_LOCK_NAME (message_slots),
05667                                           slot_p);
05668 }
05669 
05681 void
05682 dbus_message_free_data_slot (dbus_int32_t *slot_p)
05683 {
05684   _dbus_return_if_fail (*slot_p >= 0);
05685   
05686   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05687 }
05688 
05702 dbus_bool_t
05703 dbus_message_set_data (DBusMessage     *message,
05704                        dbus_int32_t     slot,
05705                        void            *data,
05706                        DBusFreeFunction free_data_func)
05707 {
05708   DBusFreeFunction old_free_func;
05709   void *old_data;
05710   dbus_bool_t retval;
05711 
05712   _dbus_return_val_if_fail (message != NULL, FALSE);
05713   _dbus_return_val_if_fail (slot >= 0, FALSE);
05714 
05715   retval = _dbus_data_slot_list_set (&slot_allocator,
05716                                      &message->slot_list,
05717                                      slot, data, free_data_func,
05718                                      &old_free_func, &old_data);
05719 
05720   if (retval)
05721     {
05722       /* Do the actual free outside the message lock */
05723       if (old_free_func)
05724         (* old_free_func) (old_data);
05725     }
05726 
05727   return retval;
05728 }
05729 
05738 void*
05739 dbus_message_get_data (DBusMessage   *message,
05740                        dbus_int32_t   slot)
05741 {
05742   void *res;
05743 
05744   _dbus_return_val_if_fail (message != NULL, NULL);
05745   
05746   res = _dbus_data_slot_list_get (&slot_allocator,
05747                                   &message->slot_list,
05748                                   slot);
05749 
05750   return res;
05751 }
05752 
05766 int
05767 dbus_message_type_from_string (const char *type_str)
05768 {
05769   if (strcmp (type_str, "method_call") == 0)
05770     return DBUS_MESSAGE_TYPE_METHOD_CALL;
05771   if (strcmp (type_str, "method_return") == 0)
05772     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
05773   else if (strcmp (type_str, "signal") == 0)
05774     return DBUS_MESSAGE_TYPE_SIGNAL;
05775   else if (strcmp (type_str, "error") == 0)
05776     return DBUS_MESSAGE_TYPE_ERROR;
05777   else
05778     return DBUS_MESSAGE_TYPE_INVALID;
05779 }
05780 
05782 #ifdef DBUS_BUILD_TESTS
05783 #include "dbus-test.h"
05784 #include <stdio.h>
05785 #include <stdlib.h>
05786 
05787 static void
05788 message_iter_test (DBusMessage *message)
05789 {
05790   DBusMessageIter iter, dict, dict2, array, array2;
05791   char *str;
05792   unsigned char *data;
05793   dbus_int32_t *our_int_array;
05794   int len;
05795   
05796   dbus_message_iter_init (message, &iter);
05797 
05798   /* String tests */
05799   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
05800     _dbus_assert_not_reached ("Argument type isn't string");
05801 
05802   str = dbus_message_iter_get_string (&iter);
05803   if (strcmp (str, "Test string") != 0)
05804     _dbus_assert_not_reached ("Strings differ");
05805   dbus_free (str);
05806 
05807   if (!dbus_message_iter_next (&iter))
05808     _dbus_assert_not_reached ("Reached end of arguments");
05809 
05810   /* Signed integer tests */
05811   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
05812     _dbus_assert_not_reached ("Argument type isn't int32");
05813 
05814   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
05815     _dbus_assert_not_reached ("Signed integers differ");
05816 
05817   if (!dbus_message_iter_next (&iter))
05818     _dbus_assert_not_reached ("Reached end of fields");
05819   
05820   /* Unsigned integer tests */
05821   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
05822     _dbus_assert_not_reached ("Argument type isn't int32");
05823 
05824   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
05825     _dbus_assert_not_reached ("Unsigned integers differ");
05826 
05827   if (!dbus_message_iter_next (&iter))
05828     _dbus_assert_not_reached ("Reached end of arguments");
05829 
05830   /* Double tests */
05831   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
05832     _dbus_assert_not_reached ("Argument type isn't double");
05833 
05834   if (dbus_message_iter_get_double (&iter) != 3.14159)
05835     _dbus_assert_not_reached ("Doubles differ");
05836 
05837   if (!dbus_message_iter_next (&iter))
05838     _dbus_assert_not_reached ("Reached end of arguments");
05839 
05840   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
05841     _dbus_assert_not_reached ("Argument type not an array");
05842 
05843   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
05844     _dbus_assert_not_reached ("Array type not double");
05845 
05846   
05847   dbus_message_iter_init_array_iterator (&iter, &array, NULL);
05848 
05849   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
05850     _dbus_assert_not_reached ("Argument type isn't double");
05851 
05852   if (dbus_message_iter_get_double (&array) != 1.5)
05853     _dbus_assert_not_reached ("Unsigned integers differ");
05854 
05855   if (!dbus_message_iter_next (&array))
05856     _dbus_assert_not_reached ("Reached end of arguments");
05857 
05858   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
05859     _dbus_assert_not_reached ("Argument type isn't double");
05860 
05861   if (dbus_message_iter_get_double (&array) != 2.5)
05862     _dbus_assert_not_reached ("Unsigned integers differ");
05863 
05864   if (dbus_message_iter_next (&array))
05865     _dbus_assert_not_reached ("Didn't reach end of arguments");
05866   
05867   if (!dbus_message_iter_next (&iter))
05868     _dbus_assert_not_reached ("Reached end of arguments");
05869   
05870 
05871   /* dict */
05872 
05873   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
05874     _dbus_assert_not_reached ("not dict type");
05875      
05876   dbus_message_iter_init_dict_iterator (&iter, &dict);
05877 
05878   str = dbus_message_iter_get_dict_key (&dict);
05879   if (str == NULL || strcmp (str, "test") != 0)
05880     _dbus_assert_not_reached ("wrong dict key");
05881   dbus_free (str);
05882 
05883   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
05884     _dbus_assert_not_reached ("wrong dict entry type");
05885 
05886   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
05887     _dbus_assert_not_reached ("wrong dict entry value");
05888 
05889   /* dict (in dict) */
05890 
05891   if (!dbus_message_iter_next (&dict))
05892     _dbus_assert_not_reached ("reached end of dict");
05893   
05894   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_DICT)
05895     _dbus_assert_not_reached ("not dict type");
05896     
05897   dbus_message_iter_init_dict_iterator (&dict, &dict2);
05898   
05899   str = dbus_message_iter_get_dict_key (&dict2);
05900   if (str == NULL || strcmp (str, "dictkey") != 0)
05901     _dbus_assert_not_reached ("wrong dict key");
05902   dbus_free (str);
05903   
05904   if (dbus_message_iter_get_arg_type (&dict2) != DBUS_TYPE_STRING)
05905     _dbus_assert_not_reached ("wrong dict entry type");
05906   
05907   str = dbus_message_iter_get_string (&dict2);
05908   if (str == NULL || strcmp (str, "dictvalue") != 0)
05909     _dbus_assert_not_reached ("wrong dict entry value");
05910   dbus_free (str);
05911   
05912   if (dbus_message_iter_next (&dict2))
05913     _dbus_assert_not_reached ("didn't reach end of dict");
05914 
05915   if (!dbus_message_iter_next (&dict))
05916     _dbus_assert_not_reached ("reached end of dict");
05917   
05918   /* array of array of int32 (in dict) */
05919 
05920   str = dbus_message_iter_get_dict_key (&dict);
05921   if (str == NULL || strcmp (str, "array") != 0)
05922     _dbus_assert_not_reached ("wrong dict key");
05923   dbus_free (str);
05924   
05925   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
05926     _dbus_assert_not_reached ("Argument type not an array");
05927 
05928   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
05929     _dbus_assert_not_reached ("Array type not array");
05930 
05931   dbus_message_iter_init_array_iterator (&dict, &array, NULL);
05932 
05933   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
05934     _dbus_assert_not_reached ("Argument type isn't array");
05935   
05936   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
05937     _dbus_assert_not_reached ("Array type not int32");
05938   
05939   dbus_message_iter_init_array_iterator (&array, &array2, NULL);
05940 
05941   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
05942     _dbus_assert_not_reached ("Argument type isn't int32");
05943 
05944   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
05945     _dbus_assert_not_reached ("Signed integers differ");
05946 
05947   if (!dbus_message_iter_next (&array2))
05948     _dbus_assert_not_reached ("Reached end of arguments");
05949 
05950   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
05951     _dbus_assert_not_reached ("Signed integers differ");
05952 
05953   if (dbus_message_iter_next (&array2))
05954     _dbus_assert_not_reached ("Didn't reached end of arguments");
05955 
05956   if (!dbus_message_iter_next (&array))
05957     _dbus_assert_not_reached ("Reached end of arguments");
05958 
05959   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
05960     _dbus_assert_not_reached ("Array type not int32");
05961 
05962   if (!dbus_message_iter_get_int32_array (&array,
05963                                           &our_int_array,
05964                                           &len))
05965     _dbus_assert_not_reached ("couldn't get int32 array");
05966 
05967   _dbus_assert (len == 3);
05968   _dbus_assert (our_int_array[0] == 0x34567812 &&
05969                 our_int_array[1] == 0x45678123 &&
05970                 our_int_array[2] == 0x56781234);
05971   dbus_free (our_int_array);
05972   
05973   if (dbus_message_iter_next (&array))
05974     _dbus_assert_not_reached ("Didn't reach end of array");
05975 
05976   if (dbus_message_iter_next (&dict))
05977     _dbus_assert_not_reached ("Didn't reach end of dict");
05978   
05979   if (!dbus_message_iter_next (&iter))
05980     _dbus_assert_not_reached ("Reached end of arguments");
05981   
05982   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
05983     {
05984       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
05985       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
05986     }
05987   
05988   if (dbus_message_iter_get_byte (&iter) != 0xF0)
05989     _dbus_assert_not_reached ("wrong value after dict");
05990 
05991 
05992   if (!dbus_message_iter_next (&iter))
05993     _dbus_assert_not_reached ("Reached end of arguments");
05994   
05995   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
05996     _dbus_assert_not_reached ("not a nil type");
05997   
05998   if (!dbus_message_iter_next (&iter))
05999     _dbus_assert_not_reached ("Reached end of arguments");
06000   
06001   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_CUSTOM)
06002     _dbus_assert_not_reached ("wrong type after dict");
06003 
06004   if (!dbus_message_iter_get_custom (&iter, &str, &data, &len))
06005     _dbus_assert_not_reached ("failed to get custom type");
06006 
06007   _dbus_assert (strcmp (str, "MyTypeName")==0);
06008   _dbus_assert (len == 5);
06009   _dbus_assert (strcmp (data, "data")==0);
06010   dbus_free (str);
06011   dbus_free (data);
06012   
06013   if (!dbus_message_iter_next (&iter))
06014     _dbus_assert_not_reached ("Reached end of arguments");
06015 
06016   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06017     _dbus_assert_not_reached ("wrong value after custom");
06018 
06019   if (!dbus_message_iter_next (&iter))
06020     _dbus_assert_not_reached ("Reached end of arguments");
06021 
06022   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
06023     _dbus_assert_not_reached ("no array");
06024 
06025   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_INT32)
06026     _dbus_assert_not_reached ("Array type not int32");
06027 
06028   if (dbus_message_iter_init_array_iterator (&iter, &array, NULL))
06029     _dbus_assert_not_reached ("non empty array");
06030   
06031   if (!dbus_message_iter_next (&iter))
06032     _dbus_assert_not_reached ("Reached end of arguments");
06033 
06034   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06035     _dbus_assert_not_reached ("wrong value after empty array");
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_DICT)
06041     _dbus_assert_not_reached ("non dict");
06042 
06043   if (dbus_message_iter_init_dict_iterator (&iter, &dict))
06044     _dbus_assert_not_reached ("non empty dict");
06045 
06046   if (!dbus_message_iter_next (&iter))
06047     _dbus_assert_not_reached ("Reached end of arguments");
06048 
06049   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06050     _dbus_assert_not_reached ("wrong value after empty dict");
06051 
06052   if (dbus_message_iter_next (&iter))
06053     _dbus_assert_not_reached ("Didn't reach end of arguments");
06054 }
06055 
06056 
06057 static dbus_bool_t
06058 check_message_handling_type (DBusMessageIter *iter,
06059                              int type)
06060 {
06061   DBusMessageIter child_iter;
06062   
06063   switch (type)
06064     {
06065     case DBUS_TYPE_NIL:
06066       break;
06067     case DBUS_TYPE_BYTE:
06068       dbus_message_iter_get_byte (iter);
06069       break;
06070     case DBUS_TYPE_BOOLEAN:
06071       dbus_message_iter_get_boolean (iter);
06072       break;
06073     case DBUS_TYPE_INT32:
06074       dbus_message_iter_get_int32 (iter);
06075       break;
06076     case DBUS_TYPE_UINT32:
06077       dbus_message_iter_get_uint32 (iter);
06078       break;
06079     case DBUS_TYPE_INT64:
06080 #ifdef DBUS_HAVE_INT64
06081       dbus_message_iter_get_int64 (iter);
06082 #endif
06083       break;
06084     case DBUS_TYPE_UINT64:
06085 #ifdef DBUS_HAVE_INT64
06086       dbus_message_iter_get_uint64 (iter);
06087 #endif
06088       break;
06089     case DBUS_TYPE_DOUBLE:
06090       dbus_message_iter_get_double (iter);
06091       break;
06092     case DBUS_TYPE_STRING:
06093       {
06094         char *str;
06095         str = dbus_message_iter_get_string (iter);
06096         if (str == NULL)
06097           {
06098             _dbus_warn ("NULL string in message\n");
06099             return FALSE;
06100           }
06101         dbus_free (str);
06102       }
06103       break;
06104     case DBUS_TYPE_CUSTOM:
06105       {
06106         char *name;
06107         unsigned char *data;
06108         int len;
06109         
06110         if (!dbus_message_iter_get_custom (iter, &name, &data, &len))
06111           {
06112             _dbus_warn ("error reading name from custom type\n");
06113             return FALSE;
06114           }
06115         dbus_free (data);
06116         dbus_free (name);
06117       }
06118       break;
06119     case DBUS_TYPE_ARRAY:
06120       {
06121         int array_type;
06122 
06123         dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type);
06124 
06125         while (dbus_message_iter_has_next (&child_iter))
06126           {
06127             if (!check_message_handling_type (&child_iter, array_type))
06128               {
06129                 _dbus_warn ("error in array element\n");
06130                 return FALSE;
06131               }
06132             
06133             if (!dbus_message_iter_next (&child_iter))
06134               break;
06135           }
06136       }
06137       break;
06138     case DBUS_TYPE_DICT:
06139       {
06140         int entry_type;
06141         char *key;
06142         
06143         dbus_message_iter_init_dict_iterator (iter, &child_iter);
06144 
06145         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
06146           {
06147             key = dbus_message_iter_get_dict_key (&child_iter);
06148             if (key == NULL)
06149               {
06150                 _dbus_warn ("error reading dict key\n");
06151                 return FALSE;
06152               }
06153             dbus_free (key);
06154             
06155             if (!check_message_handling_type (&child_iter, entry_type))
06156               {
06157                 _dbus_warn ("error in dict value\n");
06158                 return FALSE;
06159               }
06160             
06161             if (!dbus_message_iter_next (&child_iter))
06162               break;
06163           }
06164       }
06165       break;
06166       
06167     default:
06168       _dbus_warn ("unknown type %d\n", type);
06169       return FALSE;
06170       break;
06171     }
06172   return TRUE;
06173 }
06174   
06175   
06176 static dbus_bool_t
06177 check_message_handling (DBusMessage *message)
06178 {
06179   DBusMessageIter iter;
06180   int type;
06181   dbus_bool_t retval;
06182   dbus_uint32_t client_serial;
06183   
06184   retval = FALSE;
06185   
06186   client_serial = dbus_message_get_serial (message);
06187 
06188   /* can't use set_serial due to the assertions at the start of it */
06189   _dbus_marshal_set_uint32 (&message->header,
06190                             message->byte_order,
06191                             CLIENT_SERIAL_OFFSET,
06192                             client_serial);
06193   
06194   if (client_serial != dbus_message_get_serial (message))
06195     {
06196       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
06197       goto failed;
06198     }
06199   
06200   /* If we implement message_set_arg (message, n, value)
06201    * then we would want to test it here
06202    */
06203 
06204   dbus_message_iter_init (message, &iter);
06205   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
06206     {
06207       if (!check_message_handling_type (&iter, type))
06208         goto failed;
06209 
06210       if (!dbus_message_iter_next (&iter))
06211         break;
06212     }
06213   
06214   retval = TRUE;
06215   
06216  failed:
06217   return retval;
06218 }
06219 
06220 static dbus_bool_t
06221 check_have_valid_message (DBusMessageLoader *loader)
06222 {
06223   DBusMessage *message;
06224   dbus_bool_t retval;
06225 
06226   message = NULL;
06227   retval = FALSE;
06228 
06229   if (!_dbus_message_loader_queue_messages (loader))
06230     _dbus_assert_not_reached ("no memory to queue messages");
06231   
06232   if (_dbus_message_loader_get_is_corrupted (loader))
06233     {
06234       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
06235       goto failed;
06236     }
06237   
06238   message = _dbus_message_loader_pop_message (loader);
06239   if (message == NULL)
06240     {
06241       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
06242       goto failed;
06243     }
06244   
06245   if (_dbus_string_get_length (&loader->data) > 0)
06246     {
06247       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
06248       goto failed;
06249     }
06250 
06251   /* Verify that we're able to properly deal with the message.
06252    * For example, this would detect improper handling of messages
06253    * in nonstandard byte order.
06254    */
06255   if (!check_message_handling (message))
06256     goto failed;  
06257   
06258   retval = TRUE;
06259 
06260  failed:
06261   if (message)
06262     dbus_message_unref (message);
06263 
06264   return retval;
06265 }
06266 
06267 static dbus_bool_t
06268 check_invalid_message (DBusMessageLoader *loader)
06269 {
06270   dbus_bool_t retval;
06271 
06272   retval = FALSE;
06273 
06274   if (!_dbus_message_loader_queue_messages (loader))
06275     _dbus_assert_not_reached ("no memory to queue messages");
06276   
06277   if (!_dbus_message_loader_get_is_corrupted (loader))
06278     {
06279       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
06280       goto failed;
06281     }
06282 
06283   retval = TRUE;
06284 
06285  failed:
06286   return retval;
06287 }
06288 
06289 static dbus_bool_t
06290 check_incomplete_message (DBusMessageLoader *loader)
06291 {
06292   DBusMessage *message;
06293   dbus_bool_t retval;
06294 
06295   message = NULL;
06296   retval = FALSE;
06297 
06298   if (!_dbus_message_loader_queue_messages (loader))
06299     _dbus_assert_not_reached ("no memory to queue messages");
06300   
06301   if (_dbus_message_loader_get_is_corrupted (loader))
06302     {
06303       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
06304       goto failed;
06305     }
06306   
06307   message = _dbus_message_loader_pop_message (loader);
06308   if (message != NULL)
06309     {
06310       _dbus_warn ("loaded message that was expected to be incomplete\n");
06311       goto failed;
06312     }
06313 
06314   retval = TRUE;
06315 
06316  failed:
06317   if (message)
06318     dbus_message_unref (message);
06319   return retval;
06320 }
06321 
06322 static dbus_bool_t
06323 check_loader_results (DBusMessageLoader      *loader,
06324                       DBusMessageValidity     validity)
06325 {
06326   if (!_dbus_message_loader_queue_messages (loader))
06327     _dbus_assert_not_reached ("no memory to queue messages");
06328   
06329   switch (validity)
06330     {
06331     case _DBUS_MESSAGE_VALID:
06332       return check_have_valid_message (loader);
06333     case _DBUS_MESSAGE_INVALID:
06334       return check_invalid_message (loader);
06335     case _DBUS_MESSAGE_INCOMPLETE:
06336       return check_incomplete_message (loader);
06337     case _DBUS_MESSAGE_UNKNOWN:
06338       return TRUE;
06339     }
06340 
06341   _dbus_assert_not_reached ("bad DBusMessageValidity");
06342   return FALSE;
06343 }
06344 
06345 
06354 dbus_bool_t
06355 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
06356                                             dbus_bool_t          is_raw,
06357                                             DBusString          *data)
06358 {
06359   dbus_bool_t retval;
06360 
06361   retval = FALSE;  
06362 
06363   if (is_raw)
06364     {
06365       DBusError error;
06366 
06367       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
06368       dbus_error_init (&error);
06369       if (!_dbus_file_get_contents (data, filename, &error))
06370         {
06371           _dbus_warn ("Could not load message file %s: %s\n",
06372                       _dbus_string_get_const_data (filename),
06373                       error.message);
06374           dbus_error_free (&error);
06375           goto failed;
06376         }
06377     }
06378   else
06379     {
06380       if (!_dbus_message_data_load (data, filename))
06381         {
06382           _dbus_warn ("Could not load message file %s\n",
06383                       _dbus_string_get_const_data (filename));
06384           goto failed;
06385         }
06386     }
06387 
06388   retval = TRUE;
06389   
06390  failed:
06391 
06392   return retval;
06393 }
06394 
06404 dbus_bool_t
06405 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
06406                                            dbus_bool_t          is_raw,
06407                                            DBusMessageValidity  expected_validity)
06408 {
06409   DBusString data;
06410   dbus_bool_t retval;
06411 
06412   retval = FALSE;
06413   
06414   if (!_dbus_string_init (&data))
06415     _dbus_assert_not_reached ("could not allocate string\n");
06416 
06417   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
06418                                                    &data))
06419     goto failed;
06420 
06421   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
06422 
06423  failed:
06424 
06425   if (!retval)
06426     {
06427       if (_dbus_string_get_length (&data) > 0)
06428         _dbus_verbose_bytes_of_string (&data, 0,
06429                                        _dbus_string_get_length (&data));
06430       
06431       _dbus_warn ("Failed message loader test on %s\n",
06432                   _dbus_string_get_const_data (filename));
06433     }
06434   
06435   _dbus_string_free (&data);
06436 
06437   return retval;
06438 }
06439 
06448 dbus_bool_t
06449 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
06450                                            DBusMessageValidity  expected_validity)
06451 {
06452   DBusMessageLoader *loader;
06453   dbus_bool_t retval;
06454   int len;
06455   int i;
06456 
06457   loader = NULL;
06458   retval = FALSE;
06459 
06460   /* Write the data one byte at a time */
06461   
06462   loader = _dbus_message_loader_new ();
06463 
06464   /* check some trivial loader functions */
06465   _dbus_message_loader_ref (loader);
06466   _dbus_message_loader_unref (loader);
06467   _dbus_message_loader_get_max_message_size (loader);
06468   
06469   len = _dbus_string_get_length (data);
06470   for (i = 0; i < len; i++)
06471     {
06472       DBusString *buffer;
06473 
06474       _dbus_message_loader_get_buffer (loader, &buffer);
06475       _dbus_string_append_byte (buffer,
06476                                 _dbus_string_get_byte (data, i));
06477       _dbus_message_loader_return_buffer (loader, buffer, 1);
06478     }
06479   
06480   if (!check_loader_results (loader, expected_validity))
06481     goto failed;
06482 
06483   _dbus_message_loader_unref (loader);
06484   loader = NULL;
06485 
06486   /* Write the data all at once */
06487   
06488   loader = _dbus_message_loader_new ();
06489 
06490   {
06491     DBusString *buffer;
06492     
06493     _dbus_message_loader_get_buffer (loader, &buffer);
06494     _dbus_string_copy (data, 0, buffer,
06495                        _dbus_string_get_length (buffer));
06496     _dbus_message_loader_return_buffer (loader, buffer, 1);
06497   }
06498   
06499   if (!check_loader_results (loader, expected_validity))
06500     goto failed;
06501 
06502   _dbus_message_loader_unref (loader);
06503   loader = NULL;  
06504 
06505   /* Write the data 2 bytes at a time */
06506   
06507   loader = _dbus_message_loader_new ();
06508 
06509   len = _dbus_string_get_length (data);
06510   for (i = 0; i < len; i += 2)
06511     {
06512       DBusString *buffer;
06513 
06514       _dbus_message_loader_get_buffer (loader, &buffer);
06515       _dbus_string_append_byte (buffer,
06516                                 _dbus_string_get_byte (data, i));
06517       if ((i+1) < len)
06518         _dbus_string_append_byte (buffer,
06519                                   _dbus_string_get_byte (data, i+1));
06520       _dbus_message_loader_return_buffer (loader, buffer, 1);
06521     }
06522   
06523   if (!check_loader_results (loader, expected_validity))
06524     goto failed;
06525 
06526   _dbus_message_loader_unref (loader);
06527   loader = NULL;
06528   
06529   retval = TRUE;
06530   
06531  failed:
06532   
06533   if (loader)
06534     _dbus_message_loader_unref (loader);
06535   
06536   return retval;
06537 }
06538 
06539 static dbus_bool_t
06540 process_test_subdir (const DBusString          *test_base_dir,
06541                      const char                *subdir,
06542                      DBusMessageValidity        validity,
06543                      DBusForeachMessageFileFunc function,
06544                      void                      *user_data)
06545 {
06546   DBusString test_directory;
06547   DBusString filename;
06548   DBusDirIter *dir;
06549   dbus_bool_t retval;
06550   DBusError error;
06551 
06552   retval = FALSE;
06553   dir = NULL;
06554   
06555   if (!_dbus_string_init (&test_directory))
06556     _dbus_assert_not_reached ("didn't allocate test_directory\n");
06557 
06558   _dbus_string_init_const (&filename, subdir);
06559   
06560   if (!_dbus_string_copy (test_base_dir, 0,
06561                           &test_directory, 0))
06562     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
06563   
06564   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
06565     _dbus_assert_not_reached ("couldn't allocate full path");
06566 
06567   _dbus_string_free (&filename);
06568   if (!_dbus_string_init (&filename))
06569     _dbus_assert_not_reached ("didn't allocate filename string\n");
06570 
06571   dbus_error_init (&error);
06572   dir = _dbus_directory_open (&test_directory, &error);
06573   if (dir == NULL)
06574     {
06575       _dbus_warn ("Could not open %s: %s\n",
06576                   _dbus_string_get_const_data (&test_directory),
06577                   error.message);
06578       dbus_error_free (&error);
06579       goto failed;
06580     }
06581 
06582   printf ("Testing %s:\n", subdir);
06583   
06584  next:
06585   while (_dbus_directory_get_next_file (dir, &filename, &error))
06586     {
06587       DBusString full_path;
06588       dbus_bool_t is_raw;
06589       
06590       if (!_dbus_string_init (&full_path))
06591         _dbus_assert_not_reached ("couldn't init string");
06592 
06593       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
06594         _dbus_assert_not_reached ("couldn't copy dir to full_path");
06595 
06596       if (!_dbus_concat_dir_and_file (&full_path, &filename))
06597         _dbus_assert_not_reached ("couldn't concat file to dir");
06598 
06599       if (_dbus_string_ends_with_c_str (&filename, ".message"))
06600         is_raw = FALSE;
06601       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
06602         is_raw = TRUE;
06603       else
06604         {
06605           _dbus_verbose ("Skipping non-.message file %s\n",
06606                          _dbus_string_get_const_data (&filename));
06607           _dbus_string_free (&full_path);
06608           goto next;
06609         }
06610 
06611       printf ("    %s\n",
06612               _dbus_string_get_const_data (&filename));
06613       
06614       _dbus_verbose (" expecting %s for %s\n",
06615                      validity == _DBUS_MESSAGE_VALID ? "valid" :
06616                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
06617                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
06618                      _dbus_string_get_const_data (&filename));
06619       
06620       if (! (*function) (&full_path, is_raw, validity, user_data))
06621         {
06622           _dbus_string_free (&full_path);
06623           goto failed;
06624         }
06625       else
06626         _dbus_string_free (&full_path);
06627     }
06628 
06629   if (dbus_error_is_set (&error))
06630     {
06631       _dbus_warn ("Could not get next file in %s: %s\n",
06632                   _dbus_string_get_const_data (&test_directory),
06633                   error.message);
06634       dbus_error_free (&error);
06635       goto failed;
06636     }
06637     
06638   retval = TRUE;
06639   
06640  failed:
06641 
06642   if (dir)
06643     _dbus_directory_close (dir);
06644   _dbus_string_free (&test_directory);
06645   _dbus_string_free (&filename);
06646 
06647   return retval;
06648 }
06649                      
06659 dbus_bool_t
06660 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
06661                                                DBusForeachMessageFileFunc func,
06662                                                void                      *user_data)
06663 {
06664   DBusString test_directory;
06665   dbus_bool_t retval;
06666 
06667   retval = FALSE;
06668   
06669   _dbus_string_init_const (&test_directory, test_data_dir);
06670 
06671   if (!process_test_subdir (&test_directory, "valid-messages",
06672                             _DBUS_MESSAGE_VALID, func, user_data))
06673     goto failed;
06674 
06675   if (!process_test_subdir (&test_directory, "invalid-messages",
06676                             _DBUS_MESSAGE_INVALID, func, user_data))
06677     goto failed;
06678   
06679   if (!process_test_subdir (&test_directory, "incomplete-messages",
06680                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
06681     goto failed;
06682 
06683   retval = TRUE;
06684   
06685  failed:
06686 
06687   _dbus_string_free (&test_directory);
06688   
06689   return retval;
06690 }
06691 
06692 static void
06693 verify_test_message (DBusMessage *message)
06694 {
06695   DBusMessageIter iter, dict;
06696   DBusError error;
06697   dbus_int32_t our_int;
06698   char *our_str;
06699   double our_double;
06700   dbus_bool_t our_bool;
06701   unsigned char our_byte_1, our_byte_2;
06702   dbus_uint32_t our_uint32;
06703   dbus_int32_t *our_uint32_array;
06704   int our_uint32_array_len;
06705   dbus_int32_t *our_int32_array;
06706   int our_int32_array_len;
06707   char **our_string_array;
06708   int our_string_array_len;
06709 #ifdef DBUS_HAVE_INT64
06710   dbus_int64_t our_int64;
06711   dbus_uint64_t our_uint64;
06712   dbus_int64_t *our_uint64_array;
06713   int our_uint64_array_len;
06714   dbus_int64_t *our_int64_array;
06715   int our_int64_array_len;
06716 #endif
06717   double *our_double_array;
06718   int our_double_array_len;
06719   unsigned char *our_byte_array;
06720   int our_byte_array_len;
06721   unsigned char *our_boolean_array;
06722   int our_boolean_array_len;
06723   
06724   dbus_message_iter_init (message, &iter);
06725 
06726   dbus_error_init (&error);
06727   if (!dbus_message_iter_get_args (&iter, &error,
06728                                    DBUS_TYPE_INT32, &our_int,
06729 #ifdef DBUS_HAVE_INT64
06730                                    DBUS_TYPE_INT64, &our_int64,
06731                                    DBUS_TYPE_UINT64, &our_uint64,
06732 #endif
06733                                    DBUS_TYPE_STRING, &our_str,
06734                                    DBUS_TYPE_DOUBLE, &our_double,
06735                                    DBUS_TYPE_BOOLEAN, &our_bool,
06736                                    DBUS_TYPE_BYTE, &our_byte_1,
06737                                    DBUS_TYPE_BYTE, &our_byte_2,
06738                                    DBUS_TYPE_NIL,
06739                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
06740                                    &our_uint32_array, &our_uint32_array_len,
06741                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
06742                                    &our_int32_array, &our_int32_array_len,
06743 #ifdef DBUS_HAVE_INT64
06744                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
06745                                    &our_uint64_array, &our_uint64_array_len,
06746                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
06747                                    &our_int64_array, &our_int64_array_len,
06748 #endif
06749                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
06750                                    &our_string_array, &our_string_array_len,
06751                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
06752                                    &our_double_array, &our_double_array_len,
06753                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
06754                                    &our_byte_array, &our_byte_array_len,
06755                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
06756                                    &our_boolean_array, &our_boolean_array_len,
06757                                    0))
06758     {
06759       _dbus_warn ("error: %s - %s\n", error.name,
06760                   (error.message != NULL) ? error.message : "no message");
06761       _dbus_assert_not_reached ("Could not get arguments");
06762     }
06763 
06764   if (our_int != -0x12345678)
06765     _dbus_assert_not_reached ("integers differ!");
06766 
06767 #ifdef DBUS_HAVE_INT64
06768   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
06769     _dbus_assert_not_reached ("64-bit integers differ!");
06770   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
06771     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
06772 #endif
06773   
06774   if (our_double != 3.14159)
06775     _dbus_assert_not_reached ("doubles differ!");
06776 
06777   if (strcmp (our_str, "Test string") != 0)
06778     _dbus_assert_not_reached ("strings differ!");
06779   dbus_free (our_str);
06780 
06781   if (!our_bool)
06782     _dbus_assert_not_reached ("booleans differ");
06783 
06784   if (our_byte_1 != 42)
06785     _dbus_assert_not_reached ("bytes differ!");
06786 
06787   if (our_byte_2 != 24)
06788     _dbus_assert_not_reached ("bytes differ!");
06789 
06790   if (our_uint32_array_len != 4 ||
06791       our_uint32_array[0] != 0x12345678 ||
06792       our_uint32_array[1] != 0x23456781 ||
06793       our_uint32_array[2] != 0x34567812 ||
06794       our_uint32_array[3] != 0x45678123)
06795     _dbus_assert_not_reached ("uint array differs");
06796   dbus_free (our_uint32_array);
06797 
06798   if (our_int32_array_len != 4 ||
06799       our_int32_array[0] != 0x12345678 ||
06800       our_int32_array[1] != -0x23456781 ||
06801       our_int32_array[2] != 0x34567812 ||
06802       our_int32_array[3] != -0x45678123)
06803     _dbus_assert_not_reached ("int array differs");
06804   dbus_free (our_int32_array);
06805 
06806 #ifdef DBUS_HAVE_INT64
06807   if (our_uint64_array_len != 4 ||
06808       our_uint64_array[0] != 0x12345678 ||
06809       our_uint64_array[1] != 0x23456781 ||
06810       our_uint64_array[2] != 0x34567812 ||
06811       our_uint64_array[3] != 0x45678123)
06812     _dbus_assert_not_reached ("uint64 array differs");
06813   dbus_free (our_uint64_array);
06814   
06815   if (our_int64_array_len != 4 ||
06816       our_int64_array[0] != 0x12345678 ||
06817       our_int64_array[1] != -0x23456781 ||
06818       our_int64_array[2] != 0x34567812 ||
06819       our_int64_array[3] != -0x45678123)
06820     _dbus_assert_not_reached ("int64 array differs");
06821   dbus_free (our_int64_array);
06822 #endif /* DBUS_HAVE_INT64 */
06823   
06824   if (our_string_array_len != 4)
06825     _dbus_assert_not_reached ("string array has wrong length");
06826 
06827   if (strcmp (our_string_array[0], "Foo") != 0 ||
06828       strcmp (our_string_array[1], "bar") != 0 ||
06829       strcmp (our_string_array[2], "") != 0 ||
06830       strcmp (our_string_array[3], "woo woo woo woo") != 0)
06831     _dbus_assert_not_reached ("string array differs");
06832 
06833   dbus_free_string_array (our_string_array);
06834 
06835   if (our_double_array_len != 3)
06836     _dbus_assert_not_reached ("double array had wrong length");
06837 
06838   /* On all IEEE machines (i.e. everything sane) exact equality
06839    * should be preserved over the wire
06840    */
06841   if (our_double_array[0] != 0.1234 ||
06842       our_double_array[1] != 9876.54321 ||
06843       our_double_array[2] != -300.0)
06844     _dbus_assert_not_reached ("double array had wrong values");
06845 
06846   dbus_free (our_double_array);
06847 
06848   if (our_byte_array_len != 4)
06849     _dbus_assert_not_reached ("byte array had wrong length");
06850 
06851   if (our_byte_array[0] != 'a' ||
06852       our_byte_array[1] != 'b' ||
06853       our_byte_array[2] != 'c' ||
06854       our_byte_array[3] != 234)
06855     _dbus_assert_not_reached ("byte array had wrong values");
06856 
06857   dbus_free (our_byte_array);
06858 
06859   if (our_boolean_array_len != 5)
06860     _dbus_assert_not_reached ("bool array had wrong length");
06861 
06862   if (our_boolean_array[0] != TRUE ||
06863       our_boolean_array[1] != FALSE ||
06864       our_boolean_array[2] != TRUE ||
06865       our_boolean_array[3] != TRUE ||
06866       our_boolean_array[4] != FALSE)
06867     _dbus_assert_not_reached ("bool array had wrong values");
06868 
06869   dbus_free (our_boolean_array);
06870 
06871   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
06872     _dbus_assert_not_reached ("not dict type");
06873      
06874   dbus_message_iter_init_dict_iterator (&iter, &dict);
06875 
06876   our_str = dbus_message_iter_get_dict_key (&dict);
06877   if (our_str == NULL || strcmp (our_str, "test") != 0)
06878     _dbus_assert_not_reached ("wrong dict key");
06879   dbus_free (our_str);
06880 
06881   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
06882     {
06883       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
06884       _dbus_assert_not_reached ("wrong dict entry type");
06885     }
06886 
06887   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
06888     {
06889       _dbus_verbose ("dict entry val: %x\n", our_uint32);
06890       _dbus_assert_not_reached ("wrong dict entry value");
06891     }
06892 
06893   if (dbus_message_iter_next (&dict))
06894     _dbus_assert_not_reached ("Didn't reach end of dict");
06895   
06896   if (!dbus_message_iter_next (&iter))
06897     _dbus_assert_not_reached ("Reached end of arguments");
06898   
06899   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
06900     _dbus_assert_not_reached ("wrong type after dict");
06901   
06902   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
06903     _dbus_assert_not_reached ("wrong value after dict");
06904 
06905   if (dbus_message_iter_next (&iter))
06906     _dbus_assert_not_reached ("Didn't reach end of arguments");
06907 }
06908 
06915 dbus_bool_t
06916 _dbus_message_test (const char *test_data_dir)
06917 {
06918   DBusMessage *message;
06919   DBusMessageLoader *loader;
06920   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
06921   int i;
06922   const char *data;
06923   DBusMessage *copy;
06924   const char *name1;
06925   const char *name2;
06926   const dbus_uint32_t our_uint32_array[] =
06927     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
06928   const dbus_uint32_t our_int32_array[] =
06929     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
06930 #ifdef DBUS_HAVE_INT64
06931   const dbus_uint64_t our_uint64_array[] =
06932     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
06933   const dbus_uint64_t our_int64_array[] =
06934     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
06935 #endif
06936   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
06937   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
06938   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
06939   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
06940   char sig[64];
06941   const char *s;
06942   char *t;
06943   DBusError error;
06944   
06945   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
06946 
06947   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
06948                                           "/org/freedesktop/TestPath",
06949                                           "Foo.TestInterface",
06950                                           "TestMethod");
06951   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
06952   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
06953                                              "TestMethod"));
06954   _dbus_assert (strcmp (dbus_message_get_path (message),
06955                         "/org/freedesktop/TestPath") == 0);
06956   _dbus_message_set_serial (message, 1234);
06957   /* string length including nul byte not a multiple of 4 */
06958   if (!dbus_message_set_sender (message, "org.foo.bar1"))
06959     _dbus_assert_not_reached ("out of memory");
06960   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
06961   dbus_message_set_reply_serial (message, 5678);
06962   if (!dbus_message_set_sender (message, NULL))
06963     _dbus_assert_not_reached ("out of memory");
06964   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
06965   _dbus_assert (dbus_message_get_serial (message) == 1234);
06966   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
06967   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
06968 
06969   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
06970   dbus_message_set_no_reply (message, TRUE);
06971   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
06972   dbus_message_set_no_reply (message, FALSE);
06973   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
06974 
06975   /* Set/get some header fields */
06976   
06977   if (!dbus_message_set_path (message, "/foo"))
06978     _dbus_assert_not_reached ("out of memory");
06979   _dbus_assert (strcmp (dbus_message_get_path (message),
06980                         "/foo") == 0);
06981 
06982   if (!dbus_message_set_interface (message, "org.Foo"))
06983     _dbus_assert_not_reached ("out of memory");
06984   _dbus_assert (strcmp (dbus_message_get_interface (message),
06985                         "org.Foo") == 0);
06986   
06987   if (!dbus_message_set_member (message, "Bar"))
06988     _dbus_assert_not_reached ("out of memory");
06989   _dbus_assert (strcmp (dbus_message_get_member (message),
06990                         "Bar") == 0);
06991 
06992   /* Set/get them with longer values */
06993   if (!dbus_message_set_path (message, "/foo/bar"))
06994     _dbus_assert_not_reached ("out of memory");
06995   _dbus_assert (strcmp (dbus_message_get_path (message),
06996                         "/foo/bar") == 0);
06997 
06998   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
06999     _dbus_assert_not_reached ("out of memory");
07000   _dbus_assert (strcmp (dbus_message_get_interface (message),
07001                         "org.Foo.Bar") == 0);
07002   
07003   if (!dbus_message_set_member (message, "BarFoo"))
07004     _dbus_assert_not_reached ("out of memory");
07005   _dbus_assert (strcmp (dbus_message_get_member (message),
07006                         "BarFoo") == 0);
07007 
07008   /* Realloc shorter again */
07009   
07010   if (!dbus_message_set_path (message, "/foo"))
07011     _dbus_assert_not_reached ("out of memory");
07012   _dbus_assert (strcmp (dbus_message_get_path (message),
07013                         "/foo") == 0);
07014 
07015   if (!dbus_message_set_interface (message, "org.Foo"))
07016     _dbus_assert_not_reached ("out of memory");
07017   _dbus_assert (strcmp (dbus_message_get_interface (message),
07018                         "org.Foo") == 0);
07019   
07020   if (!dbus_message_set_member (message, "Bar"))
07021     _dbus_assert_not_reached ("out of memory");
07022   _dbus_assert (strcmp (dbus_message_get_member (message),
07023                         "Bar") == 0);
07024   
07025   dbus_message_unref (message);
07026   
07027   /* Test the vararg functions */
07028   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07029                                           "/org/freedesktop/TestPath",
07030                                           "Foo.TestInterface",
07031                                           "TestMethod");
07032   _dbus_message_set_serial (message, 1);
07033   dbus_message_append_args (message,
07034                             DBUS_TYPE_INT32, -0x12345678,
07035 #ifdef DBUS_HAVE_INT64
07036                             DBUS_TYPE_INT64, DBUS_INT64_CONSTANT (-0x123456789abcd),
07037                             DBUS_TYPE_UINT64, DBUS_UINT64_CONSTANT (0x123456789abcd),
07038 #endif
07039                             DBUS_TYPE_STRING, "Test string",
07040                             DBUS_TYPE_DOUBLE, 3.14159,
07041                             DBUS_TYPE_BOOLEAN, TRUE,
07042                             DBUS_TYPE_BYTE, (unsigned char) 42,
07043                             DBUS_TYPE_BYTE, 24,
07044                             DBUS_TYPE_NIL,
07045                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
07046                             _DBUS_N_ELEMENTS (our_uint32_array),
07047                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
07048                             _DBUS_N_ELEMENTS (our_int32_array),
07049 #ifdef DBUS_HAVE_INT64
07050                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
07051                             _DBUS_N_ELEMENTS (our_uint64_array),
07052                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
07053                             _DBUS_N_ELEMENTS (our_int64_array),
07054 #endif
07055                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
07056                             _DBUS_N_ELEMENTS (our_string_array),
07057                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
07058                             _DBUS_N_ELEMENTS (our_double_array),
07059                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
07060                             _DBUS_N_ELEMENTS (our_byte_array),
07061                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
07062                             _DBUS_N_ELEMENTS (our_boolean_array),
07063                             0);
07064   
07065   dbus_message_append_iter_init (message, &iter);
07066   dbus_message_iter_append_dict (&iter, &child_iter);
07067   dbus_message_iter_append_dict_key (&child_iter, "test");
07068   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07069   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
07070 
07071   i = 0;
07072   sig[i++] = DBUS_TYPE_INT32;
07073 #ifdef DBUS_HAVE_INT64
07074   sig[i++] = DBUS_TYPE_INT64;
07075   sig[i++] = DBUS_TYPE_UINT64;
07076 #endif
07077   sig[i++] = DBUS_TYPE_STRING;
07078   sig[i++] = DBUS_TYPE_DOUBLE;
07079   sig[i++] = DBUS_TYPE_BOOLEAN;
07080   sig[i++] = DBUS_TYPE_BYTE;
07081   sig[i++] = DBUS_TYPE_BYTE;
07082   sig[i++] = DBUS_TYPE_NIL;
07083   sig[i++] = DBUS_TYPE_ARRAY;
07084   sig[i++] = DBUS_TYPE_UINT32;
07085   sig[i++] = DBUS_TYPE_ARRAY;
07086   sig[i++] = DBUS_TYPE_INT32;
07087 #ifdef DBUS_HAVE_INT64
07088   sig[i++] = DBUS_TYPE_ARRAY;
07089   sig[i++] = DBUS_TYPE_UINT64;
07090   sig[i++] = DBUS_TYPE_ARRAY;
07091   sig[i++] = DBUS_TYPE_INT64;
07092 #endif
07093   sig[i++] = DBUS_TYPE_ARRAY;
07094   sig[i++] = DBUS_TYPE_STRING;
07095   sig[i++] = DBUS_TYPE_ARRAY;
07096   sig[i++] = DBUS_TYPE_DOUBLE;
07097   sig[i++] = DBUS_TYPE_ARRAY;
07098   sig[i++] = DBUS_TYPE_BYTE;
07099   sig[i++] = DBUS_TYPE_ARRAY;
07100   sig[i++] = DBUS_TYPE_BOOLEAN;
07101   sig[i++] = DBUS_TYPE_DICT;
07102   sig[i++] = DBUS_TYPE_UINT32;
07103   sig[i++] = DBUS_TYPE_INVALID;
07104 
07105   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
07106   
07107   _dbus_verbose_bytes_of_string (&message->header, 0,
07108                                  _dbus_string_get_length (&message->header));
07109   _dbus_verbose_bytes_of_string (&message->body, 0,
07110                                  _dbus_string_get_length (&message->body));
07111   
07112   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
07113                  sig, dbus_message_get_signature (message));
07114   
07115   s = dbus_message_get_signature (message);
07116   
07117   _dbus_assert (dbus_message_has_signature (message, sig));
07118   _dbus_assert (strcmp (s, sig) == 0);
07119   
07120   verify_test_message (message);
07121 
07122   copy = dbus_message_copy (message);
07123   
07124   _dbus_assert (message->client_serial == copy->client_serial);
07125   _dbus_assert (message->reply_serial == copy->reply_serial);
07126   _dbus_assert (message->header_padding == copy->header_padding);
07127   
07128   _dbus_assert (_dbus_string_get_length (&message->header) ==
07129                 _dbus_string_get_length (&copy->header));
07130 
07131   _dbus_assert (_dbus_string_get_length (&message->body) ==
07132                 _dbus_string_get_length (&copy->body));
07133   
07134   verify_test_message (copy);
07135 
07136   name1 = dbus_message_get_interface (message);
07137   name2 = dbus_message_get_interface (copy);
07138 
07139   _dbus_assert (strcmp (name1, name2) == 0);
07140 
07141   name1 = dbus_message_get_member (message);
07142   name2 = dbus_message_get_member (copy);
07143 
07144   _dbus_assert (strcmp (name1, name2) == 0);
07145   
07146   dbus_message_unref (message);  
07147   dbus_message_unref (copy);
07148 
07149   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07150                                           "/org/freedesktop/TestPath",
07151                                           "Foo.TestInterface",
07152                                           "TestMethod");
07153 
07154   _dbus_message_set_serial (message, 1);
07155   dbus_message_set_reply_serial (message, 0x12345678);
07156 
07157   dbus_message_append_iter_init (message, &iter);
07158   dbus_message_iter_append_string (&iter, "Test string");
07159   dbus_message_iter_append_int32 (&iter, -0x12345678);
07160   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
07161   dbus_message_iter_append_double (&iter, 3.14159);
07162 
07163   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
07164   dbus_message_iter_append_double (&child_iter, 1.5);
07165   dbus_message_iter_append_double (&child_iter, 2.5);
07166 
07167   /* dict */
07168   dbus_message_iter_append_dict (&iter, &child_iter);
07169   dbus_message_iter_append_dict_key (&child_iter, "test");
07170   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07171 
07172   /* dict (in dict) */
07173   dbus_message_iter_append_dict_key (&child_iter, "testdict");
07174   dbus_message_iter_append_dict (&child_iter, &child_iter2);
07175 
07176   dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
07177   dbus_message_iter_append_string (&child_iter2, "dictvalue");
07178 
07179   /* array of array of int32  (in dict) */
07180   dbus_message_iter_append_dict_key (&child_iter, "array");
07181   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
07182   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07183   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
07184   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
07185   _dbus_warn ("next call expected to fail with wrong array type\n");
07186   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
07187   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07188   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
07189   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
07190   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
07191   
07192   dbus_message_iter_append_byte (&iter, 0xF0);
07193 
07194   dbus_message_iter_append_nil (&iter);
07195 
07196   dbus_message_iter_append_custom (&iter, "MyTypeName",
07197                                    "data", 5);
07198   
07199   dbus_message_iter_append_byte (&iter, 0xF0);
07200 
07201   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_INT32);
07202 
07203   dbus_message_iter_append_byte (&iter, 0xF0);
07204 
07205   dbus_message_iter_append_dict (&iter, &child_iter);
07206 
07207   dbus_message_iter_append_byte (&iter, 0xF0);
07208 
07209   message_iter_test (message);
07210   
07211   /* Message loader test */
07212   _dbus_message_lock (message);
07213   loader = _dbus_message_loader_new ();
07214 
07215   /* check ref/unref */
07216   _dbus_message_loader_ref (loader);
07217   _dbus_message_loader_unref (loader);
07218   
07219   /* Write the header data one byte at a time */
07220   data = _dbus_string_get_const_data (&message->header);
07221   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
07222     {
07223       DBusString *buffer;
07224 
07225       _dbus_message_loader_get_buffer (loader, &buffer);
07226       _dbus_string_append_byte (buffer, data[i]);
07227       _dbus_message_loader_return_buffer (loader, buffer, 1);
07228     }
07229 
07230   /* Write the body data one byte at a time */
07231   data = _dbus_string_get_const_data (&message->body);
07232   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
07233     {
07234       DBusString *buffer;
07235 
07236       _dbus_message_loader_get_buffer (loader, &buffer);
07237       _dbus_string_append_byte (buffer, data[i]);
07238       _dbus_message_loader_return_buffer (loader, buffer, 1);
07239     }
07240 
07241   copy = dbus_message_copy (message); /* save for tests below */
07242   dbus_message_unref (message);
07243 
07244   /* Now pop back the message */
07245   if (!_dbus_message_loader_queue_messages (loader))
07246     _dbus_assert_not_reached ("no memory to queue messages");
07247   
07248   if (_dbus_message_loader_get_is_corrupted (loader))
07249     _dbus_assert_not_reached ("message loader corrupted");
07250   
07251   message = _dbus_message_loader_pop_message (loader);
07252   if (!message)
07253     _dbus_assert_not_reached ("received a NULL message");
07254 
07255   if (dbus_message_get_reply_serial (message) != 0x12345678)
07256     _dbus_assert_not_reached ("reply serial fields differ");
07257   
07258   message_iter_test (message);
07259   
07260   dbus_message_unref (message);
07261   _dbus_message_loader_unref (loader);
07262 
07263   message = dbus_message_new_method_return (copy);
07264   if (message == NULL)
07265     _dbus_assert_not_reached ("out of memory\n");
07266   dbus_message_unref (copy);
07267 
07268   if (!dbus_message_append_args (message,
07269                                  DBUS_TYPE_STRING, "hello",
07270                                  DBUS_TYPE_INVALID))
07271     _dbus_assert_not_reached ("no memory");
07272 
07273   if (!dbus_message_has_signature (message, "s"))
07274     _dbus_assert_not_reached ("method return has wrong signature");
07275 
07276   dbus_error_init (&error);
07277   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
07278                               &t, DBUS_TYPE_INVALID))
07279     
07280     {
07281       _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
07282       exit (1);
07283     }
07284   dbus_free (t);
07285   
07286   dbus_message_unref (message);
07287   
07288   /* Now load every message in test_data_dir if we have one */
07289   if (test_data_dir == NULL)
07290     return TRUE;
07291 
07292   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
07293                                                         (DBusForeachMessageFileFunc)
07294                                                         dbus_internal_do_not_use_try_message_file,
07295                                                         NULL);
07296 }
07297 
07298 #endif /* DBUS_BUILD_TESTS */

Generated on Sat Sep 25 19:17:12 2004 for D-BUS by  doxygen 1.3.8-20040913