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.0
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-marshal.h"
00027 #include "dbus-message.h"
00028 #include "dbus-message-internal.h"
00029 #include "dbus-memory.h"
00030 #include "dbus-list.h"
00031 #include "dbus-message-builder.h"
00032 #include "dbus-dataslot.h"
00033 #include <string.h>
00034 
00048 typedef struct
00049 {
00050   int name_offset;  
00051   int value_offset; 
00052 } HeaderField;
00053 
00055 #define BYTE_ORDER_OFFSET    0
00056 
00057 #define TYPE_OFFSET          1
00058 
00059 #define FLAGS_OFFSET         2
00060 
00061 #define VERSION_OFFSET       3
00062 
00063 #define HEADER_LENGTH_OFFSET 4
00064 
00065 #define BODY_LENGTH_OFFSET   8
00066 
00067 #define CLIENT_SERIAL_OFFSET 12
00068 
00069 
00077 struct DBusMessage
00078 {
00079   DBusAtomic refcount; 
00081   DBusString header; 
00086   HeaderField header_fields[DBUS_HEADER_FIELD_LAST + 1]; 
00090   dbus_uint32_t client_serial; 
00091   dbus_uint32_t reply_serial;  
00093   int header_padding; 
00095   DBusString body;   
00097   char byte_order; 
00099   DBusList *size_counters;   
00100   long size_counter_delta;   
00102   dbus_uint32_t changed_stamp; 
00104   unsigned int locked : 1; 
00106   DBusDataSlotList slot_list;   
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, void *);
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           /* FIXME if you pass an unsigned char to varargs it gets promoted to int,
03988            * so probably we should read an int here.
03989            */
03990           if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, unsigned char)))
03991             goto errorout;
03992           break;
03993         case DBUS_TYPE_BOOLEAN:
03994           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
03995             goto errorout;
03996           break;
03997         case DBUS_TYPE_INT32:
03998           /* FIXME this is probably wrong, because an int passed in probably gets
03999            * converted to plain "int" not necessarily 32-bit.
04000            */
04001           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
04002             goto errorout;
04003           break;
04004         case DBUS_TYPE_UINT32:
04005           /* FIXME this is probably wrong, because an int passed in probably gets
04006            * converted to plain "int" not necessarily 32-bit.
04007            */
04008           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
04009             goto errorout;          
04010           break;
04011 #ifdef DBUS_HAVE_INT64
04012         case DBUS_TYPE_INT64:
04013           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
04014             goto errorout;
04015           break;
04016         case DBUS_TYPE_UINT64:
04017           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
04018             goto errorout;          
04019           break;
04020 #endif /* DBUS_HAVE_INT64 */
04021         case DBUS_TYPE_DOUBLE:
04022           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
04023             goto errorout;
04024           break;
04025         case DBUS_TYPE_STRING:
04026           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
04027             goto errorout;
04028           break;
04029         case DBUS_TYPE_OBJECT_PATH:
04030           if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
04031             goto errorout;
04032           break;
04033         case DBUS_TYPE_CUSTOM:
04034           {
04035             const char *name;
04036             unsigned char *data;
04037             int len;
04038  
04039             name = va_arg (var_args, const char *);
04040             data = va_arg (var_args, unsigned char *);
04041             len = va_arg (var_args, int);
04042 
04043             if (!dbus_message_iter_append_custom (&iter, name, data, len))
04044               goto errorout;
04045             break;
04046           }
04047         case DBUS_TYPE_ARRAY:
04048           {
04049             void *data;
04050             int len, type;
04051  
04052             type = va_arg (var_args, int);
04053             data = va_arg (var_args, void *);
04054             len = va_arg (var_args, int);
04055 
04056             switch (type)
04057               {
04058               case DBUS_TYPE_BYTE:
04059               case DBUS_TYPE_BOOLEAN:
04060               case DBUS_TYPE_INT32:
04061               case DBUS_TYPE_UINT32:
04062 #ifdef DBUS_HAVE_INT64
04063               case DBUS_TYPE_INT64:
04064               case DBUS_TYPE_UINT64:
04065 #endif /* DBUS_HAVE_INT64 */
04066               case DBUS_TYPE_DOUBLE:
04067                 if (!_dbus_message_iter_append_basic_array (&iter, type, data, len))
04068                   goto errorout;
04069                 break;
04070               case DBUS_TYPE_STRING:
04071                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
04072                   goto errorout;
04073                 break;
04074               case DBUS_TYPE_OBJECT_PATH:
04075                 if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
04076                   goto errorout;
04077                 break;
04078               case DBUS_TYPE_NIL:
04079               case DBUS_TYPE_ARRAY:
04080               case DBUS_TYPE_CUSTOM:
04081               case DBUS_TYPE_DICT:
04082                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
04083                 goto errorout;
04084               default:
04085                 _dbus_warn ("Unknown field type %d\n", type);
04086                 goto errorout;
04087               }
04088           }
04089           break;
04090           
04091         case DBUS_TYPE_DICT:
04092           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
04093           goto errorout;
04094         default:
04095           _dbus_warn ("Unknown field type %d\n", type);
04096           goto errorout;
04097         }
04098 
04099       type = va_arg (var_args, int);
04100     }
04101 
04102   return TRUE;
04103 
04104  errorout:
04105   return FALSE;
04106 }
04107 
04116 dbus_bool_t
04117 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
04118                                         unsigned const char *value,
04119                                         int                  len)
04120 {
04121   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BOOLEAN,
04122                                                 value, len);
04123 }
04124 
04133 dbus_bool_t
04134 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
04135                                       const dbus_int32_t *value,
04136                                       int                 len)
04137 {
04138   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT32,
04139                                                 value, len);
04140 }
04141 
04150 dbus_bool_t
04151 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
04152                                        const dbus_uint32_t *value,
04153                                        int                  len)
04154 {
04155   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT32,
04156                                                 value, len);
04157 }
04158 
04159 #ifdef DBUS_HAVE_INT64
04160 
04171 dbus_bool_t
04172 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
04173                                       const dbus_int64_t *value,
04174                                       int                 len)
04175 {
04176   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT64,
04177                                                 value, len);
04178 }
04179 
04190 dbus_bool_t
04191 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
04192                                        const dbus_uint64_t *value,
04193                                        int                  len)
04194 {
04195   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT64,
04196                                                 value, len);
04197 }
04198 #endif /* DBUS_HAVE_INT64 */
04199 
04208 dbus_bool_t
04209 dbus_message_iter_append_double_array (DBusMessageIter *iter,
04210                                        const double    *value,
04211                                        int              len)
04212 {
04213   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_DOUBLE,
04214                                                 value, len);
04215 }
04216 
04225 dbus_bool_t
04226 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
04227                                      unsigned const char *value,
04228                                      int                  len)
04229 {
04230   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BYTE,
04231                                                 value, len);
04232 }
04233 
04242 dbus_bool_t
04243 dbus_message_iter_append_string_array (DBusMessageIter *iter,
04244                                        const char     **value,
04245                                        int              len)
04246 {
04247   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04248 
04249   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04250 
04251   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
04252     return FALSE;
04253   
04254   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04255     {
04256       _dbus_string_set_length (&real->message->body, real->pos);
04257       return FALSE;
04258     }
04259 
04260   dbus_message_iter_append_done (real);
04261   
04262   return TRUE;
04263 }
04264 
04273 dbus_bool_t
04274 dbus_message_iter_append_object_path_array (DBusMessageIter *iter,
04275                                             const char     **value,
04276                                             int              len)
04277 {
04278   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04279 
04280   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04281 
04282   if (!append_array_type (real, DBUS_TYPE_OBJECT_PATH, NULL, NULL))
04283     return FALSE;
04284   
04285   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04286     {
04287       _dbus_string_set_length (&real->message->body, real->pos);
04288       return FALSE;
04289     }
04290 
04291   dbus_message_iter_append_done (real);
04292   
04293   return TRUE;
04294 }
04295 
04303 dbus_bool_t
04304 dbus_message_set_sender (DBusMessage  *message,
04305                          const char   *sender)
04306 {
04307   _dbus_return_val_if_fail (message != NULL, FALSE);
04308   _dbus_return_val_if_fail (!message->locked, FALSE);
04309 
04310   return set_string_field (message,
04311                            DBUS_HEADER_FIELD_SENDER,
04312                            DBUS_TYPE_STRING,
04313                            sender);
04314 }
04315 
04326 void
04327 dbus_message_set_no_reply (DBusMessage *message,
04328                            dbus_bool_t  no_reply)
04329 {
04330   char *header;
04331 
04332   _dbus_return_if_fail (message != NULL);
04333   _dbus_return_if_fail (!message->locked);
04334   
04335   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04336   
04337   if (no_reply)
04338     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
04339   else
04340     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
04341 }
04342 
04350 dbus_bool_t
04351 dbus_message_get_no_reply (DBusMessage *message)
04352 {
04353   const char *header;
04354 
04355   _dbus_return_val_if_fail (message != NULL, FALSE);
04356   
04357   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04358 
04359   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
04360 }
04361 
04362 
04372 void
04373 dbus_message_set_auto_activation (DBusMessage *message,
04374                                   dbus_bool_t  auto_activation)
04375 {
04376   char *header;
04377 
04378   _dbus_return_if_fail (message != NULL);
04379   _dbus_return_if_fail (!message->locked);
04380   
04381   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04382   
04383   if (auto_activation)
04384     *header |= DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04385   else
04386     *header &= ~DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04387 }
04388 
04396 dbus_bool_t
04397 dbus_message_get_auto_activation (DBusMessage *message)
04398 {
04399   const char *header;
04400 
04401   _dbus_return_val_if_fail (message != NULL, FALSE);
04402   
04403   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04404 
04405   return (*header & DBUS_HEADER_FLAG_AUTO_ACTIVATION) != 0;
04406 }
04407 
04415 const char*
04416 dbus_message_get_sender (DBusMessage *message)
04417 {
04418   _dbus_return_val_if_fail (message != NULL, NULL);
04419   
04420   return get_string_field (message, 
04421                            DBUS_HEADER_FIELD_SENDER,
04422                            NULL);
04423 }
04424 
04440 const char*
04441 dbus_message_get_signature (DBusMessage *message)
04442 {
04443   _dbus_return_val_if_fail (message != NULL, NULL);
04444 
04445   return get_string_field (message, 
04446                            DBUS_HEADER_FIELD_SIGNATURE,
04447                            NULL);
04448 }
04449 
04450 static dbus_bool_t
04451 _dbus_message_has_type_interface_member (DBusMessage *message,
04452                                          int          type,
04453                                          const char  *interface,
04454                                          const char  *method)
04455 {
04456   const char *n;
04457 
04458   _dbus_assert (message != NULL);
04459   _dbus_assert (interface != NULL);
04460   _dbus_assert (method != NULL);
04461 
04462   if (dbus_message_get_type (message) != type)
04463     return FALSE;
04464 
04465   /* Optimize by checking the short method name first
04466    * instead of the longer interface name
04467    */  
04468 
04469   n = dbus_message_get_member (message);
04470 
04471   if (n && strcmp (n, method) == 0)
04472     {
04473       n = dbus_message_get_interface (message);
04474       
04475       if (n && strcmp (n, interface) == 0)
04476         return TRUE;
04477     }
04478 
04479   return FALSE;
04480 }
04481 
04494 dbus_bool_t
04495 dbus_message_is_method_call (DBusMessage *message,
04496                              const char  *interface,
04497                              const char  *method)
04498 {
04499   _dbus_return_val_if_fail (message != NULL, FALSE);
04500   _dbus_return_val_if_fail (interface != NULL, FALSE);
04501   _dbus_return_val_if_fail (method != NULL, FALSE);
04502 
04503   return _dbus_message_has_type_interface_member (message,
04504                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
04505                                                   interface, method);
04506 }
04507 
04520 dbus_bool_t
04521 dbus_message_is_signal (DBusMessage *message,
04522                         const char  *interface,
04523                         const char  *signal_name)
04524 {
04525   _dbus_return_val_if_fail (message != NULL, FALSE);
04526   _dbus_return_val_if_fail (interface != NULL, FALSE);
04527   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
04528 
04529   return _dbus_message_has_type_interface_member (message,
04530                                                   DBUS_MESSAGE_TYPE_SIGNAL,
04531                                                   interface, signal_name);
04532 }
04533 
04544 dbus_bool_t
04545 dbus_message_is_error (DBusMessage *message,
04546                        const char  *error_name)
04547 {
04548   const char *n;
04549   
04550   _dbus_return_val_if_fail (message != NULL, FALSE);
04551   _dbus_return_val_if_fail (error_name != NULL, FALSE);
04552   _dbus_return_val_if_fail (is_valid_error_name (error_name), FALSE);
04553   
04554   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04555     return FALSE;
04556 
04557   n = dbus_message_get_error_name (message);
04558 
04559   if (n && strcmp (n, error_name) == 0)
04560     return TRUE;
04561   else
04562     return FALSE;
04563 }
04564 
04575 dbus_bool_t
04576 dbus_message_has_destination (DBusMessage  *message,
04577                               const char   *service)
04578 {
04579   const char *s;
04580 
04581   _dbus_return_val_if_fail (message != NULL, FALSE);
04582   _dbus_return_val_if_fail (service != NULL, FALSE);
04583   
04584   s = dbus_message_get_destination (message);
04585 
04586   if (s && strcmp (s, service) == 0)
04587     return TRUE;
04588   else
04589     return FALSE;
04590 }
04591 
04606 dbus_bool_t
04607 dbus_message_has_sender (DBusMessage  *message,
04608                          const char   *service)
04609 {
04610   const char *s;
04611 
04612   _dbus_return_val_if_fail (message != NULL, FALSE);
04613   _dbus_return_val_if_fail (service != NULL, FALSE);
04614   
04615   s = dbus_message_get_sender (message);
04616 
04617   if (s && strcmp (s, service) == 0)
04618     return TRUE;
04619   else
04620     return FALSE;
04621 }
04622 
04632 dbus_bool_t
04633 dbus_message_has_signature (DBusMessage   *message,
04634                             const char    *signature)
04635 {
04636   const char *s;
04637 
04638   _dbus_return_val_if_fail (message != NULL, FALSE);
04639   _dbus_return_val_if_fail (signature != NULL, FALSE);
04640   
04641   s = dbus_message_get_signature (message);
04642 
04643   if (s && strcmp (s, signature) == 0)
04644     return TRUE;
04645   else
04646     return FALSE;
04647 }
04648 
04666 dbus_bool_t
04667 dbus_set_error_from_message (DBusError   *error,
04668                              DBusMessage *message)
04669 {
04670   char *str;
04671 
04672   _dbus_return_val_if_fail (message != NULL, FALSE);
04673   _dbus_return_val_if_error_is_set (error, FALSE);
04674   
04675   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04676     return FALSE;
04677 
04678   str = NULL;
04679   dbus_message_get_args (message, NULL,
04680                          DBUS_TYPE_STRING, &str,
04681                          DBUS_TYPE_INVALID);
04682 
04683   dbus_set_error (error, dbus_message_get_error_name (message),
04684                   str ? "%s" : NULL, str);
04685 
04686   dbus_free (str);
04687   
04688   return TRUE;
04689 }
04690 
04715 /* we definitely use signed ints for sizes, so don't exceed
04716  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
04717  * over 128M is pretty nuts anyhow.
04718  */
04719 
04723 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
04724 
04729 struct DBusMessageLoader
04730 {
04731   int refcount;        
04733   DBusString data;     
04735   DBusList *messages;  
04737   long max_message_size; 
04739   unsigned int buffer_outstanding : 1; 
04741   unsigned int corrupted : 1; 
04742 };
04743 
04754 #define INITIAL_LOADER_DATA_LEN 32
04755 
04762 DBusMessageLoader*
04763 _dbus_message_loader_new (void)
04764 {
04765   DBusMessageLoader *loader;
04766 
04767   loader = dbus_new0 (DBusMessageLoader, 1);
04768   if (loader == NULL)
04769     return NULL;
04770   
04771   loader->refcount = 1;
04772 
04773   /* Try to cap message size at something that won't *totally* hose
04774    * the system if we have a couple of them.
04775    */
04776   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
04777   
04778   if (!_dbus_string_init (&loader->data))
04779     {
04780       dbus_free (loader);
04781       return NULL;
04782     }
04783 
04784   /* preallocate the buffer for speed, ignore failure */
04785   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
04786   _dbus_string_set_length (&loader->data, 0);
04787   
04788   return loader;
04789 }
04790 
04797 DBusMessageLoader *
04798 _dbus_message_loader_ref (DBusMessageLoader *loader)
04799 {
04800   loader->refcount += 1;
04801 
04802   return loader;
04803 }
04804 
04811 void
04812 _dbus_message_loader_unref (DBusMessageLoader *loader)
04813 {
04814   loader->refcount -= 1;
04815   if (loader->refcount == 0)
04816     {
04817       _dbus_list_foreach (&loader->messages,
04818                           (DBusForeachFunction) dbus_message_unref,
04819                           NULL);
04820       _dbus_list_clear (&loader->messages);
04821       _dbus_string_free (&loader->data);
04822       dbus_free (loader);
04823     }
04824 }
04825 
04844 void
04845 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
04846                                  DBusString        **buffer)
04847 {
04848   _dbus_assert (!loader->buffer_outstanding);
04849 
04850   *buffer = &loader->data;
04851   
04852   loader->buffer_outstanding = TRUE;
04853 }
04854 
04859 #define DBUS_MINIMUM_HEADER_SIZE 16
04860 
04861 static dbus_bool_t
04862 decode_string_field (const DBusString   *data,
04863                      int                 field,
04864                      HeaderField        *header_field,
04865                      DBusString         *field_data,
04866                      int                 pos,
04867                      int                 type)
04868 {
04869   int string_data_pos;
04870 
04871   _dbus_assert (header_field != NULL);
04872   _dbus_assert (field_data != NULL);
04873   
04874   if (header_field->name_offset >= 0)
04875     {
04876       _dbus_verbose ("%s field provided twice\n",
04877                      _dbus_header_field_to_string (field));
04878       return FALSE;
04879     }
04880 
04881   if (type != DBUS_TYPE_STRING)
04882     {
04883       _dbus_verbose ("%s field has wrong type %s\n",
04884                      _dbus_header_field_to_string (field),
04885                      _dbus_type_to_string (type));
04886       return FALSE;
04887     }
04888 
04889   /* skip padding after typecode, skip string length;
04890    * we assume that the string arg has already been validated
04891    * for sanity and UTF-8
04892    */
04893   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
04894   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
04895   
04896   _dbus_string_init_const (field_data,
04897                            _dbus_string_get_const_data (data) + string_data_pos);
04898 
04899   header_field->name_offset  = pos - 2;
04900   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
04901   
04902 #if 0
04903   _dbus_verbose ("Found field %s at offset %d\n",
04904                  _dbus_header_field_to_string (field),
04905                  header_field->value_offset);
04906 #endif
04907 
04908   return TRUE;
04909 }
04910 
04911 /* FIXME because the service/interface/member/error names are already
04912  * validated to be in the particular ASCII subset, UTF-8 validating
04913  * them could be skipped as a probably-interesting optimization.
04914  * The UTF-8 validation definitely shows up in profiles.
04915  */
04916 static dbus_bool_t
04917 decode_header_data (const DBusString   *data,
04918                     int                 header_len,
04919                     int                 byte_order,
04920                     int                 message_type,
04921                     HeaderField         fields[DBUS_HEADER_FIELD_LAST + 1],
04922                     int                *message_padding)
04923 {
04924   DBusString field_data;
04925   int pos, new_pos;
04926   int i;
04927   int field;
04928   int type;
04929   dbus_bool_t signature_required;
04930   
04931   if (header_len < 16)
04932     {
04933       _dbus_verbose ("Header length %d is too short\n", header_len);
04934       return FALSE;
04935     }
04936   
04937   i = 0;
04938   while (i <= DBUS_HEADER_FIELD_LAST)
04939     {
04940       fields[i].name_offset  = -1;
04941       fields[i].value_offset = -1;
04942       ++i;
04943     }
04944   
04945   pos = 16;
04946   while (pos < header_len)
04947     {
04948       field = _dbus_string_get_byte (data, pos);
04949       if (field == DBUS_HEADER_FIELD_INVALID)
04950         break; /* Must be padding */
04951       pos++;
04952 
04953       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
04954         {
04955           _dbus_verbose ("Failed to validate type of named header field pos = %d\n",
04956                          pos);
04957           return FALSE;
04958         }
04959       
04960       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
04961         {
04962           _dbus_verbose ("Failed to validate argument to named header field pos = %d\n",
04963                          pos);
04964           return FALSE;
04965         }
04966 
04967       if (new_pos > header_len)
04968         {
04969           _dbus_verbose ("Named header field tries to extend beyond header length\n");
04970           return FALSE;
04971         }
04972       
04973       switch (field)
04974         {
04975         case DBUS_HEADER_FIELD_DESTINATION:
04976           if (!decode_string_field (data, field, &fields[field],
04977                                     &field_data, pos, type))
04978             return FALSE;
04979 
04980           if (!_dbus_string_validate_service (&field_data, 0,
04981                                               _dbus_string_get_length (&field_data)))
04982             {
04983               _dbus_verbose ("service field has invalid content \"%s\"\n",
04984                              _dbus_string_get_const_data (&field_data));
04985               return FALSE;
04986             }
04987           break;
04988 
04989         case DBUS_HEADER_FIELD_INTERFACE:
04990           if (!decode_string_field (data, field, &fields[field],
04991                                     &field_data, pos, type))
04992             return FALSE;
04993 
04994           if (!_dbus_string_validate_interface (&field_data, 0,
04995                                                 _dbus_string_get_length (&field_data)))
04996             {
04997               _dbus_verbose ("interface field has invalid content \"%s\"\n",
04998                              _dbus_string_get_const_data (&field_data));
04999               return FALSE;
05000             }
05001       
05002           if (_dbus_string_equal_c_str (&field_data,
05003                                         DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
05004             {
05005               _dbus_verbose ("Message is on the local interface\n");
05006               return FALSE;
05007             }
05008           break;
05009 
05010         case DBUS_HEADER_FIELD_MEMBER:
05011           if (!decode_string_field (data, field, &fields[field],
05012                                     &field_data, pos, type))
05013             return FALSE;
05014           
05015           if (!_dbus_string_validate_member (&field_data, 0,
05016                                              _dbus_string_get_length (&field_data)))
05017             {
05018               _dbus_verbose ("member field has invalid content \"%s\"\n",
05019                              _dbus_string_get_const_data (&field_data));
05020               return FALSE;
05021             }
05022           break;
05023 
05024         case DBUS_HEADER_FIELD_ERROR_NAME:
05025           if (!decode_string_field (data, field, &fields[field],
05026                                     &field_data, pos, type))
05027             return FALSE;
05028           
05029           if (!_dbus_string_validate_error_name (&field_data, 0,
05030                                                  _dbus_string_get_length (&field_data)))
05031             {
05032               _dbus_verbose ("error-name field has invalid content \"%s\"\n",
05033                              _dbus_string_get_const_data (&field_data));
05034               return FALSE;
05035             }
05036           break;
05037           
05038         case DBUS_HEADER_FIELD_SENDER:
05039           if (!decode_string_field (data, field, &fields[field],
05040                                     &field_data, pos, type))
05041             return FALSE;
05042           
05043           if (!_dbus_string_validate_service (&field_data, 0,
05044                                               _dbus_string_get_length (&field_data)))
05045             {
05046               _dbus_verbose ("sender-service field has invalid content \"%s\"\n",
05047                              _dbus_string_get_const_data (&field_data));
05048               return FALSE;
05049             }
05050           break;
05051 
05052         case DBUS_HEADER_FIELD_PATH:
05053 
05054           /* Path was already validated as part of standard
05055            * type validation, since there's an OBJECT_PATH
05056            * type.
05057            */
05058           
05059           if (fields[field].name_offset >= 0)
05060             {
05061               _dbus_verbose ("path field provided twice\n");
05062               return FALSE;
05063             }
05064           if (type != DBUS_TYPE_OBJECT_PATH)
05065             {
05066               _dbus_verbose ("path field has wrong type\n");
05067               return FALSE;
05068             }
05069 
05070           fields[field].name_offset  = pos - 2;
05071           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05072 
05073           /* No forging signals from the local path */
05074           {
05075             const char *s;
05076             s = _dbus_string_get_const_data_len (data,
05077                                                  fields[field].value_offset,
05078                                                  _dbus_string_get_length (data) -
05079                                                  fields[field].value_offset);
05080             if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
05081               {
05082                 _dbus_verbose ("Message is on the local path\n");
05083                 return FALSE;
05084               }
05085           }
05086           
05087           _dbus_verbose ("Found path at offset %d\n",
05088                          fields[field].value_offset);
05089           break;
05090           
05091         case DBUS_HEADER_FIELD_REPLY_SERIAL:
05092           if (fields[field].name_offset >= 0)
05093             {
05094               _dbus_verbose ("reply field provided twice\n");
05095               return FALSE;
05096             }
05097 
05098           if (type != DBUS_TYPE_UINT32)
05099             {
05100               _dbus_verbose ("reply field has wrong type\n");
05101               return FALSE;
05102             }
05103           
05104           fields[field].name_offset  = pos - 2;
05105           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05106 
05107           _dbus_verbose ("Found reply serial %u at offset %d\n",
05108                          _dbus_demarshal_uint32 (data,
05109                                                  byte_order,
05110                                                  fields[field].value_offset,
05111                                                  NULL),
05112                          fields[field].value_offset);
05113           break;
05114 
05115         case DBUS_HEADER_FIELD_SIGNATURE:
05116           if (!decode_string_field (data, field, &fields[field],
05117                                     &field_data, pos, type))
05118             return FALSE;
05119 
05120 #if 0
05121           /* FIXME */
05122           if (!_dbus_string_validate_signature (&field_data, 0,
05123                                                 _dbus_string_get_length (&field_data)))
05124             {
05125               _dbus_verbose ("signature field has invalid content \"%s\"\n",
05126                              _dbus_string_get_const_data (&field_data));
05127               return FALSE;
05128             }
05129 #endif
05130           break;
05131           
05132         default:
05133           _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
05134                          field, pos);
05135         }
05136       
05137       pos = new_pos;
05138     }
05139 
05140   if (pos < header_len)
05141     {
05142       /* Alignment padding, verify that it's nul */
05143       if ((header_len - pos) >= 8)
05144         {
05145           _dbus_verbose ("too much header alignment padding\n");
05146           return FALSE;
05147         }
05148 
05149       if (!_dbus_string_validate_nul (data,
05150                                       pos, (header_len - pos)))
05151         {
05152           _dbus_verbose ("header alignment padding is not nul\n");
05153           return FALSE;
05154         }
05155     }
05156 
05157   /* Depending on message type, enforce presence of certain fields. */
05158   signature_required = TRUE;
05159   
05160   switch (message_type)
05161     {
05162     case DBUS_MESSAGE_TYPE_SIGNAL:
05163     case DBUS_MESSAGE_TYPE_METHOD_CALL:
05164       if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
05165         {
05166           _dbus_verbose ("No path field provided\n");
05167           return FALSE;
05168         }
05169       /* FIXME make this optional, only for method calls */
05170       if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
05171         {
05172           _dbus_verbose ("No interface field provided\n");
05173           return FALSE;
05174         }
05175       if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
05176         {
05177           _dbus_verbose ("No member field provided\n");
05178           return FALSE;
05179         }
05180       break;
05181     case DBUS_MESSAGE_TYPE_ERROR:
05182       if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
05183         {
05184           _dbus_verbose ("No error-name field provided\n");
05185           return FALSE;
05186         }
05187       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05188         {
05189           _dbus_verbose ("No reply serial field provided in error\n");
05190           return FALSE;
05191         }
05192       break;
05193     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
05194       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05195         {
05196           _dbus_verbose ("No reply serial field provided in method return\n");
05197           return FALSE;
05198         }
05199       break;
05200     default:
05201       /* An unknown type, spec requires us to ignore it */
05202       signature_required = FALSE;
05203       break;
05204     }
05205 
05206   /* FIXME allow omitting signature field for a message with no arguments? */
05207   if (signature_required)
05208     {
05209       if (fields[DBUS_HEADER_FIELD_SIGNATURE].value_offset < 0)
05210         {
05211           _dbus_verbose ("No signature field provided\n");
05212           return FALSE;
05213         }
05214     }
05215   
05216   if (message_padding)
05217     *message_padding = header_len - pos;  
05218   
05219   return TRUE;
05220 }
05221 
05232 void
05233 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
05234                                     DBusString         *buffer,
05235                                     int                 bytes_read)
05236 {
05237   _dbus_assert (loader->buffer_outstanding);
05238   _dbus_assert (buffer == &loader->data);
05239 
05240   loader->buffer_outstanding = FALSE;
05241 }
05242 
05243 static dbus_bool_t
05244 load_one_message (DBusMessageLoader *loader,
05245                   int                byte_order,
05246                   int                message_type,
05247                   int                header_len,
05248                   int                body_len)
05249 {
05250   DBusMessage *message;
05251   HeaderField fields[DBUS_HEADER_FIELD_LAST + 1];
05252   int i;
05253   int next_arg;
05254   dbus_bool_t oom;
05255   int header_padding;
05256   
05257   message = NULL;
05258   oom = FALSE;
05259   
05260 #if 0
05261   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
05262 #endif    
05263 
05264   if (!decode_header_data (&loader->data,
05265                            header_len, byte_order,
05266                            message_type,
05267                            fields, &header_padding))
05268     {
05269       _dbus_verbose ("Header was invalid\n");
05270       loader->corrupted = TRUE;
05271       goto failed;
05272     }
05273           
05274   next_arg = header_len;
05275   while (next_arg < (header_len + body_len))
05276     {
05277       int type;
05278       int prev = next_arg;
05279 
05280       if (!_dbus_marshal_validate_type (&loader->data, next_arg,
05281                                         &type, &next_arg))
05282         {
05283           _dbus_verbose ("invalid typecode at offset %d\n", prev);
05284           loader->corrupted = TRUE;
05285           goto failed;
05286         }
05287       
05288       if (!_dbus_marshal_validate_arg (&loader->data,
05289                                        byte_order,
05290                                        0,
05291                                        type, -1,
05292                                        next_arg,
05293                                        &next_arg))
05294         {
05295           _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
05296           loader->corrupted = TRUE;
05297           goto failed;
05298         }
05299 
05300       _dbus_assert (next_arg > prev);
05301     }
05302           
05303   if (next_arg > (header_len + body_len))
05304     {
05305       _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
05306                      next_arg, header_len, body_len,
05307                      header_len + body_len);
05308       loader->corrupted = TRUE;
05309       goto failed;
05310     }
05311 
05312   message = dbus_message_new_empty_header ();
05313   if (message == NULL)
05314     {
05315       _dbus_verbose ("Failed to allocate empty message\n");
05316       oom = TRUE;
05317       goto failed;
05318     }
05319 
05320   message->byte_order = byte_order;
05321   message->header_padding = header_padding;
05322           
05323   /* Copy in the offsets we found */
05324   i = 0;
05325   while (i <= DBUS_HEADER_FIELD_LAST)
05326     {
05327       message->header_fields[i] = fields[i];
05328       ++i;
05329     }
05330           
05331   if (!_dbus_list_append (&loader->messages, message))
05332     {
05333       _dbus_verbose ("Failed to append new message to loader queue\n");
05334       oom = TRUE;
05335       goto failed;
05336     }
05337 
05338   _dbus_assert (_dbus_string_get_length (&message->header) == 0);
05339   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
05340 
05341   _dbus_assert (_dbus_string_get_length (&loader->data) >=
05342                 (header_len + body_len));
05343           
05344   if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
05345     {
05346       _dbus_verbose ("Failed to move header into new message\n");
05347       oom = TRUE;
05348       goto failed;
05349     }
05350           
05351   if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
05352     {
05353       _dbus_verbose ("Failed to move body into new message\n");
05354       
05355       oom = TRUE;
05356       goto failed;
05357     }
05358 
05359   _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
05360   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
05361 
05362   /* Fill in caches (we checked the types of these fields
05363    * earlier)
05364    */
05365   message->reply_serial = get_uint_field (message,
05366                                           DBUS_HEADER_FIELD_REPLY_SERIAL);
05367   
05368   message->client_serial = _dbus_demarshal_uint32 (&message->header,
05369                                                    message->byte_order,
05370                                                    CLIENT_SERIAL_OFFSET,
05371                                                    NULL);
05372   if (message->client_serial == 0 ||
05373       (message->header_fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset >= 0 && message->reply_serial == 0))
05374     {
05375       _dbus_verbose ("client_serial = %d reply_serial = %d, one of these no good\n",
05376                      message->client_serial,
05377                      message->reply_serial);
05378       
05379       loader->corrupted = TRUE;
05380       goto failed;
05381     }
05382   
05383   _dbus_verbose ("Loaded message %p\n", message);
05384 
05385   _dbus_assert (!oom);
05386   _dbus_assert (!loader->corrupted);
05387 
05388   return TRUE;
05389 
05390  failed:
05391   
05392   /* Clean up */
05393   
05394   if (message != NULL)
05395     {
05396       /* Put the data back so we can try again later if it was an OOM issue */
05397       if (_dbus_string_get_length (&message->body) > 0)
05398         {
05399           dbus_bool_t result;
05400           
05401           result = _dbus_string_copy_len (&message->body, 0, body_len,
05402                                           &loader->data, 0);
05403           
05404           _dbus_assert (result); /* because DBusString never reallocs smaller */
05405         }
05406       
05407       if (_dbus_string_get_length (&message->header) > 0)
05408         {
05409           dbus_bool_t result;
05410           
05411           result = _dbus_string_copy_len (&message->header, 0, header_len,
05412                                           &loader->data, 0);
05413           
05414           _dbus_assert (result); /* because DBusString never reallocs smaller */
05415         }
05416 
05417       /* does nothing if the message isn't in the list */
05418       _dbus_list_remove_last (&loader->messages, message);
05419 
05420       dbus_message_unref (message);
05421     }
05422 
05423   
05424   return !oom;
05425 }
05426 
05440 dbus_bool_t
05441 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
05442 {
05443   while (!loader->corrupted && _dbus_string_get_length (&loader->data) >= 16)
05444     {
05445       const char *header_data;
05446       int byte_order, message_type, header_len, body_len;
05447       dbus_uint32_t header_len_unsigned, body_len_unsigned;
05448       
05449       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
05450 
05451       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
05452 
05453       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
05454         {
05455           _dbus_verbose ("Message has protocol version %d ours is %d\n",
05456                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
05457           loader->corrupted = TRUE;
05458           return TRUE;
05459         }
05460       
05461       byte_order = header_data[BYTE_ORDER_OFFSET];
05462 
05463       if (byte_order != DBUS_LITTLE_ENDIAN &&
05464           byte_order != DBUS_BIG_ENDIAN)
05465         {
05466           _dbus_verbose ("Message with bad byte order '%c' received\n",
05467                          byte_order);
05468           loader->corrupted = TRUE;
05469           return TRUE;
05470         }
05471 
05472       /* Unknown types are ignored, but INVALID is
05473        * disallowed
05474        */
05475       message_type = header_data[TYPE_OFFSET];
05476       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
05477         {
05478           _dbus_verbose ("Message with bad type '%d' received\n",
05479                          message_type);
05480           loader->corrupted = TRUE;
05481           return TRUE;
05482         }      
05483       
05484       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
05485       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
05486 
05487       if (header_len_unsigned < 16)
05488         {
05489           _dbus_verbose ("Message had broken too-small header length %u\n",
05490                          header_len_unsigned);
05491           loader->corrupted = TRUE;
05492           return TRUE;
05493         }
05494 
05495       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
05496           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
05497         {
05498           _dbus_verbose ("Header or body length too large (%u %u)\n",
05499                          header_len_unsigned,
05500                          body_len_unsigned);
05501           loader->corrupted = TRUE;
05502           return TRUE;
05503         }
05504 
05505       /* Now that we know the values are in signed range, get
05506        * rid of stupid unsigned, just causes bugs
05507        */
05508       header_len = header_len_unsigned;
05509       body_len = body_len_unsigned;
05510 
05511       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
05512         {
05513           
05514           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
05515                          header_len);
05516           loader->corrupted = TRUE;
05517           return TRUE;
05518         }
05519       
05520       if (header_len + body_len > loader->max_message_size)
05521         {
05522           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
05523                          header_len, body_len, loader->max_message_size);
05524           loader->corrupted = TRUE;
05525           return TRUE;
05526         }
05527 
05528       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
05529         {
05530           if (!load_one_message (loader, byte_order, message_type,
05531                                  header_len, body_len))
05532             return FALSE;
05533         }
05534       else
05535         return TRUE;
05536     }
05537 
05538   return TRUE;
05539 }
05540 
05548 DBusMessage*
05549 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
05550 {
05551   if (loader->messages)
05552     return loader->messages->data;
05553   else
05554     return NULL;
05555 }
05556 
05565 DBusMessage*
05566 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
05567 {
05568   return _dbus_list_pop_first (&loader->messages);
05569 }
05570 
05579 DBusList*
05580 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
05581 {
05582   return _dbus_list_pop_first_link (&loader->messages);
05583 }
05584 
05591 void
05592 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
05593                                            DBusList           *link)
05594 {
05595   _dbus_list_prepend_link (&loader->messages, link);
05596 }
05597 
05607 dbus_bool_t
05608 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
05609 {
05610   return loader->corrupted;
05611 }
05612 
05619 void
05620 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
05621                                            long                size)
05622 {
05623   if (size > MAX_SANE_MESSAGE_SIZE)
05624     {
05625       _dbus_verbose ("clamping requested max message size %ld to %d\n",
05626                      size, MAX_SANE_MESSAGE_SIZE);
05627       size = MAX_SANE_MESSAGE_SIZE;
05628     }
05629   loader->max_message_size = size;
05630 }
05631 
05638 long
05639 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
05640 {
05641   return loader->max_message_size;
05642 }
05643 
05644 static DBusDataSlotAllocator slot_allocator;
05645 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
05646 
05661 dbus_bool_t
05662 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
05663 {
05664   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05665                                           _DBUS_LOCK_NAME (message_slots),
05666                                           slot_p);
05667 }
05668 
05680 void
05681 dbus_message_free_data_slot (dbus_int32_t *slot_p)
05682 {
05683   _dbus_return_if_fail (*slot_p >= 0);
05684   
05685   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05686 }
05687 
05701 dbus_bool_t
05702 dbus_message_set_data (DBusMessage     *message,
05703                        dbus_int32_t     slot,
05704                        void            *data,
05705                        DBusFreeFunction free_data_func)
05706 {
05707   DBusFreeFunction old_free_func;
05708   void *old_data;
05709   dbus_bool_t retval;
05710 
05711   _dbus_return_val_if_fail (message != NULL, FALSE);
05712   _dbus_return_val_if_fail (slot >= 0, FALSE);
05713 
05714   retval = _dbus_data_slot_list_set (&slot_allocator,
05715                                      &message->slot_list,
05716                                      slot, data, free_data_func,
05717                                      &old_free_func, &old_data);
05718 
05719   if (retval)
05720     {
05721       /* Do the actual free outside the message lock */
05722       if (old_free_func)
05723         (* old_free_func) (old_data);
05724     }
05725 
05726   return retval;
05727 }
05728 
05737 void*
05738 dbus_message_get_data (DBusMessage   *message,
05739                        dbus_int32_t   slot)
05740 {
05741   void *res;
05742 
05743   _dbus_return_val_if_fail (message != NULL, NULL);
05744   
05745   res = _dbus_data_slot_list_get (&slot_allocator,
05746                                   &message->slot_list,
05747                                   slot);
05748 
05749   return res;
05750 }
05751 
05765 int
05766 dbus_message_type_from_string (const char *type_str)
05767 {
05768   if (strcmp (type_str, "method_call") == 0)
05769     return DBUS_MESSAGE_TYPE_METHOD_CALL;
05770   if (strcmp (type_str, "method_return") == 0)
05771     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
05772   else if (strcmp (type_str, "signal") == 0)
05773     return DBUS_MESSAGE_TYPE_SIGNAL;
05774   else if (strcmp (type_str, "error") == 0)
05775     return DBUS_MESSAGE_TYPE_ERROR;
05776   else
05777     return DBUS_MESSAGE_TYPE_INVALID;
05778 }
05779 
05781 #ifdef DBUS_BUILD_TESTS
05782 #include "dbus-test.h"
05783 #include <stdio.h>
05784 #include <stdlib.h>
05785 
05786 static void
05787 message_iter_test (DBusMessage *message)
05788 {
05789   DBusMessageIter iter, dict, dict2, array, array2;
05790   char *str;
05791   unsigned char *data;
05792   dbus_int32_t *our_int_array;
05793   int len;
05794   
05795   dbus_message_iter_init (message, &iter);
05796 
05797   /* String tests */
05798   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
05799     _dbus_assert_not_reached ("Argument type isn't string");
05800 
05801   str = dbus_message_iter_get_string (&iter);
05802   if (strcmp (str, "Test string") != 0)
05803     _dbus_assert_not_reached ("Strings differ");
05804   dbus_free (str);
05805 
05806   if (!dbus_message_iter_next (&iter))
05807     _dbus_assert_not_reached ("Reached end of arguments");
05808 
05809   /* Signed integer tests */
05810   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
05811     _dbus_assert_not_reached ("Argument type isn't int32");
05812 
05813   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
05814     _dbus_assert_not_reached ("Signed integers differ");
05815 
05816   if (!dbus_message_iter_next (&iter))
05817     _dbus_assert_not_reached ("Reached end of fields");
05818   
05819   /* Unsigned integer tests */
05820   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
05821     _dbus_assert_not_reached ("Argument type isn't int32");
05822 
05823   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
05824     _dbus_assert_not_reached ("Unsigned integers differ");
05825 
05826   if (!dbus_message_iter_next (&iter))
05827     _dbus_assert_not_reached ("Reached end of arguments");
05828 
05829   /* Double tests */
05830   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
05831     _dbus_assert_not_reached ("Argument type isn't double");
05832 
05833   if (dbus_message_iter_get_double (&iter) != 3.14159)
05834     _dbus_assert_not_reached ("Doubles differ");
05835 
05836   if (!dbus_message_iter_next (&iter))
05837     _dbus_assert_not_reached ("Reached end of arguments");
05838 
05839   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
05840     _dbus_assert_not_reached ("Argument type not an array");
05841 
05842   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
05843     _dbus_assert_not_reached ("Array type not double");
05844 
05845   
05846   dbus_message_iter_init_array_iterator (&iter, &array, NULL);
05847 
05848   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
05849     _dbus_assert_not_reached ("Argument type isn't double");
05850 
05851   if (dbus_message_iter_get_double (&array) != 1.5)
05852     _dbus_assert_not_reached ("Unsigned integers differ");
05853 
05854   if (!dbus_message_iter_next (&array))
05855     _dbus_assert_not_reached ("Reached end of arguments");
05856 
05857   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
05858     _dbus_assert_not_reached ("Argument type isn't double");
05859 
05860   if (dbus_message_iter_get_double (&array) != 2.5)
05861     _dbus_assert_not_reached ("Unsigned integers differ");
05862 
05863   if (dbus_message_iter_next (&array))
05864     _dbus_assert_not_reached ("Didn't reach end of arguments");
05865   
05866   if (!dbus_message_iter_next (&iter))
05867     _dbus_assert_not_reached ("Reached end of arguments");
05868   
05869 
05870   /* dict */
05871 
05872   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
05873     _dbus_assert_not_reached ("not dict type");
05874      
05875   dbus_message_iter_init_dict_iterator (&iter, &dict);
05876 
05877   str = dbus_message_iter_get_dict_key (&dict);
05878   if (str == NULL || strcmp (str, "test") != 0)
05879     _dbus_assert_not_reached ("wrong dict key");
05880   dbus_free (str);
05881 
05882   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
05883     _dbus_assert_not_reached ("wrong dict entry type");
05884 
05885   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
05886     _dbus_assert_not_reached ("wrong dict entry value");
05887 
05888   /* dict (in dict) */
05889 
05890   if (!dbus_message_iter_next (&dict))
05891     _dbus_assert_not_reached ("reached end of dict");
05892   
05893   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_DICT)
05894     _dbus_assert_not_reached ("not dict type");
05895     
05896   dbus_message_iter_init_dict_iterator (&dict, &dict2);
05897   
05898   str = dbus_message_iter_get_dict_key (&dict2);
05899   if (str == NULL || strcmp (str, "dictkey") != 0)
05900     _dbus_assert_not_reached ("wrong dict key");
05901   dbus_free (str);
05902   
05903   if (dbus_message_iter_get_arg_type (&dict2) != DBUS_TYPE_STRING)
05904     _dbus_assert_not_reached ("wrong dict entry type");
05905   
05906   str = dbus_message_iter_get_string (&dict2);
05907   if (str == NULL || strcmp (str, "dictvalue") != 0)
05908     _dbus_assert_not_reached ("wrong dict entry value");
05909   dbus_free (str);
05910   
05911   if (dbus_message_iter_next (&dict2))
05912     _dbus_assert_not_reached ("didn't reach end of dict");
05913 
05914   if (!dbus_message_iter_next (&dict))
05915     _dbus_assert_not_reached ("reached end of dict");
05916   
05917   /* array of array of int32 (in dict) */
05918 
05919   str = dbus_message_iter_get_dict_key (&dict);
05920   if (str == NULL || strcmp (str, "array") != 0)
05921     _dbus_assert_not_reached ("wrong dict key");
05922   dbus_free (str);
05923   
05924   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
05925     _dbus_assert_not_reached ("Argument type not an array");
05926 
05927   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
05928     _dbus_assert_not_reached ("Array type not array");
05929 
05930   dbus_message_iter_init_array_iterator (&dict, &array, NULL);
05931 
05932   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
05933     _dbus_assert_not_reached ("Argument type isn't array");
05934   
05935   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
05936     _dbus_assert_not_reached ("Array type not int32");
05937   
05938   dbus_message_iter_init_array_iterator (&array, &array2, NULL);
05939 
05940   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
05941     _dbus_assert_not_reached ("Argument type isn't int32");
05942 
05943   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
05944     _dbus_assert_not_reached ("Signed integers differ");
05945 
05946   if (!dbus_message_iter_next (&array2))
05947     _dbus_assert_not_reached ("Reached end of arguments");
05948 
05949   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
05950     _dbus_assert_not_reached ("Signed integers differ");
05951 
05952   if (dbus_message_iter_next (&array2))
05953     _dbus_assert_not_reached ("Didn't reached end of arguments");
05954 
05955   if (!dbus_message_iter_next (&array))
05956     _dbus_assert_not_reached ("Reached end of arguments");
05957 
05958   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
05959     _dbus_assert_not_reached ("Array type not int32");
05960 
05961   if (!dbus_message_iter_get_int32_array (&array,
05962                                           &our_int_array,
05963                                           &len))
05964     _dbus_assert_not_reached ("couldn't get int32 array");
05965 
05966   _dbus_assert (len == 3);
05967   _dbus_assert (our_int_array[0] == 0x34567812 &&
05968                 our_int_array[1] == 0x45678123 &&
05969                 our_int_array[2] == 0x56781234);
05970   dbus_free (our_int_array);
05971   
05972   if (dbus_message_iter_next (&array))
05973     _dbus_assert_not_reached ("Didn't reach end of array");
05974 
05975   if (dbus_message_iter_next (&dict))
05976     _dbus_assert_not_reached ("Didn't reach end of dict");
05977   
05978   if (!dbus_message_iter_next (&iter))
05979     _dbus_assert_not_reached ("Reached end of arguments");
05980   
05981   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
05982     {
05983       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
05984       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
05985     }
05986   
05987   if (dbus_message_iter_get_byte (&iter) != 0xF0)
05988     _dbus_assert_not_reached ("wrong value after dict");
05989 
05990 
05991   if (!dbus_message_iter_next (&iter))
05992     _dbus_assert_not_reached ("Reached end of arguments");
05993   
05994   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
05995     _dbus_assert_not_reached ("not a nil type");
05996   
05997   if (!dbus_message_iter_next (&iter))
05998     _dbus_assert_not_reached ("Reached end of arguments");
05999   
06000   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_CUSTOM)
06001     _dbus_assert_not_reached ("wrong type after dict");
06002 
06003   if (!dbus_message_iter_get_custom (&iter, &str, &data, &len))
06004     _dbus_assert_not_reached ("failed to get custom type");
06005 
06006   _dbus_assert (strcmp (str, "MyTypeName")==0);
06007   _dbus_assert (len == 5);
06008   _dbus_assert (strcmp (data, "data")==0);
06009   dbus_free (str);
06010   dbus_free (data);
06011   
06012   if (!dbus_message_iter_next (&iter))
06013     _dbus_assert_not_reached ("Reached end of arguments");
06014 
06015   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06016     _dbus_assert_not_reached ("wrong value after custom");
06017 
06018   if (!dbus_message_iter_next (&iter))
06019     _dbus_assert_not_reached ("Reached end of arguments");
06020 
06021   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
06022     _dbus_assert_not_reached ("no array");
06023 
06024   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_INT32)
06025     _dbus_assert_not_reached ("Array type not int32");
06026 
06027   if (dbus_message_iter_init_array_iterator (&iter, &array, NULL))
06028     _dbus_assert_not_reached ("non empty array");
06029   
06030   if (!dbus_message_iter_next (&iter))
06031     _dbus_assert_not_reached ("Reached end of arguments");
06032 
06033   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06034     _dbus_assert_not_reached ("wrong value after empty array");
06035 
06036   if (!dbus_message_iter_next (&iter))
06037     _dbus_assert_not_reached ("Reached end of arguments");
06038 
06039   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
06040     _dbus_assert_not_reached ("non dict");
06041 
06042   if (dbus_message_iter_init_dict_iterator (&iter, &dict))
06043     _dbus_assert_not_reached ("non empty dict");
06044 
06045   if (!dbus_message_iter_next (&iter))
06046     _dbus_assert_not_reached ("Reached end of arguments");
06047 
06048   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06049     _dbus_assert_not_reached ("wrong value after empty dict");
06050 
06051   if (dbus_message_iter_next (&iter))
06052     _dbus_assert_not_reached ("Didn't reach end of arguments");
06053 }
06054 
06055 
06056 static dbus_bool_t
06057 check_message_handling_type (DBusMessageIter *iter,
06058                              int type)
06059 {
06060   DBusMessageIter child_iter;
06061   
06062   switch (type)
06063     {
06064     case DBUS_TYPE_NIL:
06065       break;
06066     case DBUS_TYPE_BYTE:
06067       dbus_message_iter_get_byte (iter);
06068       break;
06069     case DBUS_TYPE_BOOLEAN:
06070       dbus_message_iter_get_boolean (iter);
06071       break;
06072     case DBUS_TYPE_INT32:
06073       dbus_message_iter_get_int32 (iter);
06074       break;
06075     case DBUS_TYPE_UINT32:
06076       dbus_message_iter_get_uint32 (iter);
06077       break;
06078     case DBUS_TYPE_INT64:
06079 #ifdef DBUS_HAVE_INT64
06080       dbus_message_iter_get_int64 (iter);
06081 #endif
06082       break;
06083     case DBUS_TYPE_UINT64:
06084 #ifdef DBUS_HAVE_INT64
06085       dbus_message_iter_get_uint64 (iter);
06086 #endif
06087       break;
06088     case DBUS_TYPE_DOUBLE:
06089       dbus_message_iter_get_double (iter);
06090       break;
06091     case DBUS_TYPE_STRING:
06092       {
06093         char *str;
06094         str = dbus_message_iter_get_string (iter);
06095         if (str == NULL)
06096           {
06097             _dbus_warn ("NULL string in message\n");
06098             return FALSE;
06099           }
06100         dbus_free (str);
06101       }
06102       break;
06103     case DBUS_TYPE_CUSTOM:
06104       {
06105         char *name;
06106         unsigned char *data;
06107         int len;
06108         
06109         if (!dbus_message_iter_get_custom (iter, &name, &data, &len))
06110           {
06111             _dbus_warn ("error reading name from custom type\n");
06112             return FALSE;
06113           }
06114         dbus_free (data);
06115         dbus_free (name);
06116       }
06117       break;
06118     case DBUS_TYPE_ARRAY:
06119       {
06120         int array_type;
06121 
06122         dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type);
06123 
06124         while (dbus_message_iter_has_next (&child_iter))
06125           {
06126             if (!check_message_handling_type (&child_iter, array_type))
06127               {
06128                 _dbus_warn ("error in array element\n");
06129                 return FALSE;
06130               }
06131             
06132             if (!dbus_message_iter_next (&child_iter))
06133               break;
06134           }
06135       }
06136       break;
06137     case DBUS_TYPE_DICT:
06138       {
06139         int entry_type;
06140         char *key;
06141         
06142         dbus_message_iter_init_dict_iterator (iter, &child_iter);
06143 
06144         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
06145           {
06146             key = dbus_message_iter_get_dict_key (&child_iter);
06147             if (key == NULL)
06148               {
06149                 _dbus_warn ("error reading dict key\n");
06150                 return FALSE;
06151               }
06152             dbus_free (key);
06153             
06154             if (!check_message_handling_type (&child_iter, entry_type))
06155               {
06156                 _dbus_warn ("error in dict value\n");
06157                 return FALSE;
06158               }
06159             
06160             if (!dbus_message_iter_next (&child_iter))
06161               break;
06162           }
06163       }
06164       break;
06165       
06166     default:
06167       _dbus_warn ("unknown type %d\n", type);
06168       return FALSE;
06169       break;
06170     }
06171   return TRUE;
06172 }
06173   
06174   
06175 static dbus_bool_t
06176 check_message_handling (DBusMessage *message)
06177 {
06178   DBusMessageIter iter;
06179   int type;
06180   dbus_bool_t retval;
06181   dbus_uint32_t client_serial;
06182   
06183   retval = FALSE;
06184   
06185   client_serial = dbus_message_get_serial (message);
06186 
06187   /* can't use set_serial due to the assertions at the start of it */
06188   _dbus_marshal_set_uint32 (&message->header,
06189                             message->byte_order,
06190                             CLIENT_SERIAL_OFFSET,
06191                             client_serial);
06192   
06193   if (client_serial != dbus_message_get_serial (message))
06194     {
06195       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
06196       goto failed;
06197     }
06198   
06199   /* If we implement message_set_arg (message, n, value)
06200    * then we would want to test it here
06201    */
06202 
06203   dbus_message_iter_init (message, &iter);
06204   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
06205     {
06206       if (!check_message_handling_type (&iter, type))
06207         goto failed;
06208 
06209       if (!dbus_message_iter_next (&iter))
06210         break;
06211     }
06212   
06213   retval = TRUE;
06214   
06215  failed:
06216   return retval;
06217 }
06218 
06219 static dbus_bool_t
06220 check_have_valid_message (DBusMessageLoader *loader)
06221 {
06222   DBusMessage *message;
06223   dbus_bool_t retval;
06224 
06225   message = NULL;
06226   retval = FALSE;
06227 
06228   if (!_dbus_message_loader_queue_messages (loader))
06229     _dbus_assert_not_reached ("no memory to queue messages");
06230   
06231   if (_dbus_message_loader_get_is_corrupted (loader))
06232     {
06233       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
06234       goto failed;
06235     }
06236   
06237   message = _dbus_message_loader_pop_message (loader);
06238   if (message == NULL)
06239     {
06240       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
06241       goto failed;
06242     }
06243   
06244   if (_dbus_string_get_length (&loader->data) > 0)
06245     {
06246       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
06247       goto failed;
06248     }
06249 
06250   /* Verify that we're able to properly deal with the message.
06251    * For example, this would detect improper handling of messages
06252    * in nonstandard byte order.
06253    */
06254   if (!check_message_handling (message))
06255     goto failed;  
06256   
06257   retval = TRUE;
06258 
06259  failed:
06260   if (message)
06261     dbus_message_unref (message);
06262 
06263   return retval;
06264 }
06265 
06266 static dbus_bool_t
06267 check_invalid_message (DBusMessageLoader *loader)
06268 {
06269   dbus_bool_t retval;
06270 
06271   retval = FALSE;
06272 
06273   if (!_dbus_message_loader_queue_messages (loader))
06274     _dbus_assert_not_reached ("no memory to queue messages");
06275   
06276   if (!_dbus_message_loader_get_is_corrupted (loader))
06277     {
06278       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
06279       goto failed;
06280     }
06281 
06282   retval = TRUE;
06283 
06284  failed:
06285   return retval;
06286 }
06287 
06288 static dbus_bool_t
06289 check_incomplete_message (DBusMessageLoader *loader)
06290 {
06291   DBusMessage *message;
06292   dbus_bool_t retval;
06293 
06294   message = NULL;
06295   retval = FALSE;
06296 
06297   if (!_dbus_message_loader_queue_messages (loader))
06298     _dbus_assert_not_reached ("no memory to queue messages");
06299   
06300   if (_dbus_message_loader_get_is_corrupted (loader))
06301     {
06302       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
06303       goto failed;
06304     }
06305   
06306   message = _dbus_message_loader_pop_message (loader);
06307   if (message != NULL)
06308     {
06309       _dbus_warn ("loaded message that was expected to be incomplete\n");
06310       goto failed;
06311     }
06312 
06313   retval = TRUE;
06314 
06315  failed:
06316   if (message)
06317     dbus_message_unref (message);
06318   return retval;
06319 }
06320 
06321 static dbus_bool_t
06322 check_loader_results (DBusMessageLoader      *loader,
06323                       DBusMessageValidity     validity)
06324 {
06325   if (!_dbus_message_loader_queue_messages (loader))
06326     _dbus_assert_not_reached ("no memory to queue messages");
06327   
06328   switch (validity)
06329     {
06330     case _DBUS_MESSAGE_VALID:
06331       return check_have_valid_message (loader);
06332     case _DBUS_MESSAGE_INVALID:
06333       return check_invalid_message (loader);
06334     case _DBUS_MESSAGE_INCOMPLETE:
06335       return check_incomplete_message (loader);
06336     case _DBUS_MESSAGE_UNKNOWN:
06337       return TRUE;
06338     }
06339 
06340   _dbus_assert_not_reached ("bad DBusMessageValidity");
06341   return FALSE;
06342 }
06343 
06344 
06353 dbus_bool_t
06354 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
06355                                             dbus_bool_t          is_raw,
06356                                             DBusString          *data)
06357 {
06358   dbus_bool_t retval;
06359 
06360   retval = FALSE;  
06361 
06362   if (is_raw)
06363     {
06364       DBusError error;
06365 
06366       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
06367       dbus_error_init (&error);
06368       if (!_dbus_file_get_contents (data, filename, &error))
06369         {
06370           _dbus_warn ("Could not load message file %s: %s\n",
06371                       _dbus_string_get_const_data (filename),
06372                       error.message);
06373           dbus_error_free (&error);
06374           goto failed;
06375         }
06376     }
06377   else
06378     {
06379       if (!_dbus_message_data_load (data, filename))
06380         {
06381           _dbus_warn ("Could not load message file %s\n",
06382                       _dbus_string_get_const_data (filename));
06383           goto failed;
06384         }
06385     }
06386 
06387   retval = TRUE;
06388   
06389  failed:
06390 
06391   return retval;
06392 }
06393 
06403 dbus_bool_t
06404 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
06405                                            dbus_bool_t          is_raw,
06406                                            DBusMessageValidity  expected_validity)
06407 {
06408   DBusString data;
06409   dbus_bool_t retval;
06410 
06411   retval = FALSE;
06412   
06413   if (!_dbus_string_init (&data))
06414     _dbus_assert_not_reached ("could not allocate string\n");
06415 
06416   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
06417                                                    &data))
06418     goto failed;
06419 
06420   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
06421 
06422  failed:
06423 
06424   if (!retval)
06425     {
06426       if (_dbus_string_get_length (&data) > 0)
06427         _dbus_verbose_bytes_of_string (&data, 0,
06428                                        _dbus_string_get_length (&data));
06429       
06430       _dbus_warn ("Failed message loader test on %s\n",
06431                   _dbus_string_get_const_data (filename));
06432     }
06433   
06434   _dbus_string_free (&data);
06435 
06436   return retval;
06437 }
06438 
06447 dbus_bool_t
06448 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
06449                                            DBusMessageValidity  expected_validity)
06450 {
06451   DBusMessageLoader *loader;
06452   dbus_bool_t retval;
06453   int len;
06454   int i;
06455 
06456   loader = NULL;
06457   retval = FALSE;
06458 
06459   /* Write the data one byte at a time */
06460   
06461   loader = _dbus_message_loader_new ();
06462 
06463   /* check some trivial loader functions */
06464   _dbus_message_loader_ref (loader);
06465   _dbus_message_loader_unref (loader);
06466   _dbus_message_loader_get_max_message_size (loader);
06467   
06468   len = _dbus_string_get_length (data);
06469   for (i = 0; i < len; i++)
06470     {
06471       DBusString *buffer;
06472 
06473       _dbus_message_loader_get_buffer (loader, &buffer);
06474       _dbus_string_append_byte (buffer,
06475                                 _dbus_string_get_byte (data, i));
06476       _dbus_message_loader_return_buffer (loader, buffer, 1);
06477     }
06478   
06479   if (!check_loader_results (loader, expected_validity))
06480     goto failed;
06481 
06482   _dbus_message_loader_unref (loader);
06483   loader = NULL;
06484 
06485   /* Write the data all at once */
06486   
06487   loader = _dbus_message_loader_new ();
06488 
06489   {
06490     DBusString *buffer;
06491     
06492     _dbus_message_loader_get_buffer (loader, &buffer);
06493     _dbus_string_copy (data, 0, buffer,
06494                        _dbus_string_get_length (buffer));
06495     _dbus_message_loader_return_buffer (loader, buffer, 1);
06496   }
06497   
06498   if (!check_loader_results (loader, expected_validity))
06499     goto failed;
06500 
06501   _dbus_message_loader_unref (loader);
06502   loader = NULL;  
06503 
06504   /* Write the data 2 bytes at a time */
06505   
06506   loader = _dbus_message_loader_new ();
06507 
06508   len = _dbus_string_get_length (data);
06509   for (i = 0; i < len; i += 2)
06510     {
06511       DBusString *buffer;
06512 
06513       _dbus_message_loader_get_buffer (loader, &buffer);
06514       _dbus_string_append_byte (buffer,
06515                                 _dbus_string_get_byte (data, i));
06516       if ((i+1) < len)
06517         _dbus_string_append_byte (buffer,
06518                                   _dbus_string_get_byte (data, i+1));
06519       _dbus_message_loader_return_buffer (loader, buffer, 1);
06520     }
06521   
06522   if (!check_loader_results (loader, expected_validity))
06523     goto failed;
06524 
06525   _dbus_message_loader_unref (loader);
06526   loader = NULL;
06527   
06528   retval = TRUE;
06529   
06530  failed:
06531   
06532   if (loader)
06533     _dbus_message_loader_unref (loader);
06534   
06535   return retval;
06536 }
06537 
06538 static dbus_bool_t
06539 process_test_subdir (const DBusString          *test_base_dir,
06540                      const char                *subdir,
06541                      DBusMessageValidity        validity,
06542                      DBusForeachMessageFileFunc function,
06543                      void                      *user_data)
06544 {
06545   DBusString test_directory;
06546   DBusString filename;
06547   DBusDirIter *dir;
06548   dbus_bool_t retval;
06549   DBusError error;
06550 
06551   retval = FALSE;
06552   dir = NULL;
06553   
06554   if (!_dbus_string_init (&test_directory))
06555     _dbus_assert_not_reached ("didn't allocate test_directory\n");
06556 
06557   _dbus_string_init_const (&filename, subdir);
06558   
06559   if (!_dbus_string_copy (test_base_dir, 0,
06560                           &test_directory, 0))
06561     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
06562   
06563   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
06564     _dbus_assert_not_reached ("couldn't allocate full path");
06565 
06566   _dbus_string_free (&filename);
06567   if (!_dbus_string_init (&filename))
06568     _dbus_assert_not_reached ("didn't allocate filename string\n");
06569 
06570   dbus_error_init (&error);
06571   dir = _dbus_directory_open (&test_directory, &error);
06572   if (dir == NULL)
06573     {
06574       _dbus_warn ("Could not open %s: %s\n",
06575                   _dbus_string_get_const_data (&test_directory),
06576                   error.message);
06577       dbus_error_free (&error);
06578       goto failed;
06579     }
06580 
06581   printf ("Testing %s:\n", subdir);
06582   
06583  next:
06584   while (_dbus_directory_get_next_file (dir, &filename, &error))
06585     {
06586       DBusString full_path;
06587       dbus_bool_t is_raw;
06588       
06589       if (!_dbus_string_init (&full_path))
06590         _dbus_assert_not_reached ("couldn't init string");
06591 
06592       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
06593         _dbus_assert_not_reached ("couldn't copy dir to full_path");
06594 
06595       if (!_dbus_concat_dir_and_file (&full_path, &filename))
06596         _dbus_assert_not_reached ("couldn't concat file to dir");
06597 
06598       if (_dbus_string_ends_with_c_str (&filename, ".message"))
06599         is_raw = FALSE;
06600       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
06601         is_raw = TRUE;
06602       else
06603         {
06604           _dbus_verbose ("Skipping non-.message file %s\n",
06605                          _dbus_string_get_const_data (&filename));
06606           _dbus_string_free (&full_path);
06607           goto next;
06608         }
06609 
06610       printf ("    %s\n",
06611               _dbus_string_get_const_data (&filename));
06612       
06613       _dbus_verbose (" expecting %s for %s\n",
06614                      validity == _DBUS_MESSAGE_VALID ? "valid" :
06615                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
06616                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
06617                      _dbus_string_get_const_data (&filename));
06618       
06619       if (! (*function) (&full_path, is_raw, validity, user_data))
06620         {
06621           _dbus_string_free (&full_path);
06622           goto failed;
06623         }
06624       else
06625         _dbus_string_free (&full_path);
06626     }
06627 
06628   if (dbus_error_is_set (&error))
06629     {
06630       _dbus_warn ("Could not get next file in %s: %s\n",
06631                   _dbus_string_get_const_data (&test_directory),
06632                   error.message);
06633       dbus_error_free (&error);
06634       goto failed;
06635     }
06636     
06637   retval = TRUE;
06638   
06639  failed:
06640 
06641   if (dir)
06642     _dbus_directory_close (dir);
06643   _dbus_string_free (&test_directory);
06644   _dbus_string_free (&filename);
06645 
06646   return retval;
06647 }
06648                      
06658 dbus_bool_t
06659 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
06660                                                DBusForeachMessageFileFunc func,
06661                                                void                      *user_data)
06662 {
06663   DBusString test_directory;
06664   dbus_bool_t retval;
06665 
06666   retval = FALSE;
06667   
06668   _dbus_string_init_const (&test_directory, test_data_dir);
06669 
06670   if (!process_test_subdir (&test_directory, "valid-messages",
06671                             _DBUS_MESSAGE_VALID, func, user_data))
06672     goto failed;
06673 
06674   if (!process_test_subdir (&test_directory, "invalid-messages",
06675                             _DBUS_MESSAGE_INVALID, func, user_data))
06676     goto failed;
06677   
06678   if (!process_test_subdir (&test_directory, "incomplete-messages",
06679                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
06680     goto failed;
06681 
06682   retval = TRUE;
06683   
06684  failed:
06685 
06686   _dbus_string_free (&test_directory);
06687   
06688   return retval;
06689 }
06690 
06691 static void
06692 verify_test_message (DBusMessage *message)
06693 {
06694   DBusMessageIter iter, dict;
06695   DBusError error;
06696   dbus_int32_t our_int;
06697   char *our_str;
06698   double our_double;
06699   dbus_bool_t our_bool;
06700   dbus_uint32_t our_uint32;
06701   dbus_int32_t *our_uint32_array;
06702   int our_uint32_array_len;
06703   dbus_int32_t *our_int32_array;
06704   int our_int32_array_len;
06705   char **our_string_array;
06706   int our_string_array_len;
06707 #ifdef DBUS_HAVE_INT64
06708   dbus_int64_t our_int64;
06709   dbus_uint64_t our_uint64;
06710   dbus_int64_t *our_uint64_array;
06711   int our_uint64_array_len;
06712   dbus_int64_t *our_int64_array;
06713   int our_int64_array_len;
06714 #endif
06715   double *our_double_array;
06716   int our_double_array_len;
06717   unsigned char *our_byte_array;
06718   int our_byte_array_len;
06719   unsigned char *our_boolean_array;
06720   int our_boolean_array_len;
06721   
06722   dbus_message_iter_init (message, &iter);
06723 
06724   dbus_error_init (&error);
06725   if (!dbus_message_iter_get_args (&iter, &error,
06726                                    DBUS_TYPE_INT32, &our_int,
06727 #ifdef DBUS_HAVE_INT64
06728                                    DBUS_TYPE_INT64, &our_int64,
06729                                    DBUS_TYPE_UINT64, &our_uint64,
06730 #endif
06731                                    DBUS_TYPE_STRING, &our_str,
06732                                    DBUS_TYPE_DOUBLE, &our_double,
06733                                    DBUS_TYPE_BOOLEAN, &our_bool,
06734                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
06735                                    &our_uint32_array, &our_uint32_array_len,
06736                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
06737                                    &our_int32_array, &our_int32_array_len,
06738 #ifdef DBUS_HAVE_INT64
06739                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
06740                                    &our_uint64_array, &our_uint64_array_len,
06741                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
06742                                    &our_int64_array, &our_int64_array_len,
06743 #endif
06744                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
06745                                    &our_string_array, &our_string_array_len,
06746                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
06747                                    &our_double_array, &our_double_array_len,
06748                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
06749                                    &our_byte_array, &our_byte_array_len,
06750                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
06751                                    &our_boolean_array, &our_boolean_array_len,
06752                                    0))
06753     {
06754       _dbus_warn ("error: %s - %s\n", error.name,
06755                   (error.message != NULL) ? error.message : "no message");
06756       _dbus_assert_not_reached ("Could not get arguments");
06757     }
06758 
06759   if (our_int != -0x12345678)
06760     _dbus_assert_not_reached ("integers differ!");
06761 
06762 #ifdef DBUS_HAVE_INT64
06763   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
06764     _dbus_assert_not_reached ("64-bit integers differ!");
06765   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
06766     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
06767 #endif
06768   
06769   if (our_double != 3.14159)
06770     _dbus_assert_not_reached ("doubles differ!");
06771 
06772   if (strcmp (our_str, "Test string") != 0)
06773     _dbus_assert_not_reached ("strings differ!");
06774   dbus_free (our_str);
06775 
06776   if (!our_bool)
06777     _dbus_assert_not_reached ("booleans differ");
06778 
06779   if (our_uint32_array_len != 4 ||
06780       our_uint32_array[0] != 0x12345678 ||
06781       our_uint32_array[1] != 0x23456781 ||
06782       our_uint32_array[2] != 0x34567812 ||
06783       our_uint32_array[3] != 0x45678123)
06784     _dbus_assert_not_reached ("uint array differs");
06785   dbus_free (our_uint32_array);
06786 
06787   if (our_int32_array_len != 4 ||
06788       our_int32_array[0] != 0x12345678 ||
06789       our_int32_array[1] != -0x23456781 ||
06790       our_int32_array[2] != 0x34567812 ||
06791       our_int32_array[3] != -0x45678123)
06792     _dbus_assert_not_reached ("int array differs");
06793   dbus_free (our_int32_array);
06794 
06795 #ifdef DBUS_HAVE_INT64
06796   if (our_uint64_array_len != 4 ||
06797       our_uint64_array[0] != 0x12345678 ||
06798       our_uint64_array[1] != 0x23456781 ||
06799       our_uint64_array[2] != 0x34567812 ||
06800       our_uint64_array[3] != 0x45678123)
06801     _dbus_assert_not_reached ("uint64 array differs");
06802   dbus_free (our_uint64_array);
06803   
06804   if (our_int64_array_len != 4 ||
06805       our_int64_array[0] != 0x12345678 ||
06806       our_int64_array[1] != -0x23456781 ||
06807       our_int64_array[2] != 0x34567812 ||
06808       our_int64_array[3] != -0x45678123)
06809     _dbus_assert_not_reached ("int64 array differs");
06810   dbus_free (our_int64_array);
06811 #endif /* DBUS_HAVE_INT64 */
06812   
06813   if (our_string_array_len != 4)
06814     _dbus_assert_not_reached ("string array has wrong length");
06815 
06816   if (strcmp (our_string_array[0], "Foo") != 0 ||
06817       strcmp (our_string_array[1], "bar") != 0 ||
06818       strcmp (our_string_array[2], "") != 0 ||
06819       strcmp (our_string_array[3], "woo woo woo woo") != 0)
06820     _dbus_assert_not_reached ("string array differs");
06821 
06822   dbus_free_string_array (our_string_array);
06823 
06824   if (our_double_array_len != 3)
06825     _dbus_assert_not_reached ("double array had wrong length");
06826 
06827   /* On all IEEE machines (i.e. everything sane) exact equality
06828    * should be preserved over the wire
06829    */
06830   if (our_double_array[0] != 0.1234 ||
06831       our_double_array[1] != 9876.54321 ||
06832       our_double_array[2] != -300.0)
06833     _dbus_assert_not_reached ("double array had wrong values");
06834 
06835   dbus_free (our_double_array);
06836 
06837   if (our_byte_array_len != 4)
06838     _dbus_assert_not_reached ("byte array had wrong length");
06839 
06840   if (our_byte_array[0] != 'a' ||
06841       our_byte_array[1] != 'b' ||
06842       our_byte_array[2] != 'c' ||
06843       our_byte_array[3] != 234)
06844     _dbus_assert_not_reached ("byte array had wrong values");
06845 
06846   dbus_free (our_byte_array);
06847 
06848   if (our_boolean_array_len != 5)
06849     _dbus_assert_not_reached ("bool array had wrong length");
06850 
06851   if (our_boolean_array[0] != TRUE ||
06852       our_boolean_array[1] != FALSE ||
06853       our_boolean_array[2] != TRUE ||
06854       our_boolean_array[3] != TRUE ||
06855       our_boolean_array[4] != FALSE)
06856     _dbus_assert_not_reached ("bool array had wrong values");
06857 
06858   dbus_free (our_boolean_array);
06859 
06860   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
06861     _dbus_assert_not_reached ("not dict type");
06862      
06863   dbus_message_iter_init_dict_iterator (&iter, &dict);
06864 
06865   our_str = dbus_message_iter_get_dict_key (&dict);
06866   if (our_str == NULL || strcmp (our_str, "test") != 0)
06867     _dbus_assert_not_reached ("wrong dict key");
06868   dbus_free (our_str);
06869 
06870   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
06871     {
06872       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
06873       _dbus_assert_not_reached ("wrong dict entry type");
06874     }
06875 
06876   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
06877     {
06878       _dbus_verbose ("dict entry val: %x\n", our_uint32);
06879       _dbus_assert_not_reached ("wrong dict entry value");
06880     }
06881 
06882   if (dbus_message_iter_next (&dict))
06883     _dbus_assert_not_reached ("Didn't reach end of dict");
06884   
06885   if (!dbus_message_iter_next (&iter))
06886     _dbus_assert_not_reached ("Reached end of arguments");
06887   
06888   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
06889     _dbus_assert_not_reached ("wrong type after dict");
06890   
06891   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
06892     _dbus_assert_not_reached ("wrong value after dict");
06893 
06894   if (dbus_message_iter_next (&iter))
06895     _dbus_assert_not_reached ("Didn't reach end of arguments");
06896 }
06897 
06904 dbus_bool_t
06905 _dbus_message_test (const char *test_data_dir)
06906 {
06907   DBusMessage *message;
06908   DBusMessageLoader *loader;
06909   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
06910   int i;
06911   const char *data;
06912   DBusMessage *copy;
06913   const char *name1;
06914   const char *name2;
06915   const dbus_uint32_t our_uint32_array[] =
06916     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
06917   const dbus_uint32_t our_int32_array[] =
06918     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
06919 #ifdef DBUS_HAVE_INT64
06920   const dbus_uint64_t our_uint64_array[] =
06921     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
06922   const dbus_uint64_t our_int64_array[] =
06923     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
06924 #endif
06925   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
06926   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
06927   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
06928   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
06929   char sig[64];
06930   const char *s;
06931   char *t;
06932   DBusError error;
06933   
06934   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
06935 
06936   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
06937                                           "/org/freedesktop/TestPath",
06938                                           "Foo.TestInterface",
06939                                           "TestMethod");
06940   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
06941   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
06942                                              "TestMethod"));
06943   _dbus_assert (strcmp (dbus_message_get_path (message),
06944                         "/org/freedesktop/TestPath") == 0);
06945   _dbus_message_set_serial (message, 1234);
06946   /* string length including nul byte not a multiple of 4 */
06947   if (!dbus_message_set_sender (message, "org.foo.bar1"))
06948     _dbus_assert_not_reached ("out of memory");
06949   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
06950   dbus_message_set_reply_serial (message, 5678);
06951   if (!dbus_message_set_sender (message, NULL))
06952     _dbus_assert_not_reached ("out of memory");
06953   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
06954   _dbus_assert (dbus_message_get_serial (message) == 1234);
06955   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
06956   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
06957 
06958   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
06959   dbus_message_set_no_reply (message, TRUE);
06960   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
06961   dbus_message_set_no_reply (message, FALSE);
06962   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
06963 
06964   /* Set/get some header fields */
06965   
06966   if (!dbus_message_set_path (message, "/foo"))
06967     _dbus_assert_not_reached ("out of memory");
06968   _dbus_assert (strcmp (dbus_message_get_path (message),
06969                         "/foo") == 0);
06970 
06971   if (!dbus_message_set_interface (message, "org.Foo"))
06972     _dbus_assert_not_reached ("out of memory");
06973   _dbus_assert (strcmp (dbus_message_get_interface (message),
06974                         "org.Foo") == 0);
06975   
06976   if (!dbus_message_set_member (message, "Bar"))
06977     _dbus_assert_not_reached ("out of memory");
06978   _dbus_assert (strcmp (dbus_message_get_member (message),
06979                         "Bar") == 0);
06980 
06981   /* Set/get them with longer values */
06982   if (!dbus_message_set_path (message, "/foo/bar"))
06983     _dbus_assert_not_reached ("out of memory");
06984   _dbus_assert (strcmp (dbus_message_get_path (message),
06985                         "/foo/bar") == 0);
06986 
06987   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
06988     _dbus_assert_not_reached ("out of memory");
06989   _dbus_assert (strcmp (dbus_message_get_interface (message),
06990                         "org.Foo.Bar") == 0);
06991   
06992   if (!dbus_message_set_member (message, "BarFoo"))
06993     _dbus_assert_not_reached ("out of memory");
06994   _dbus_assert (strcmp (dbus_message_get_member (message),
06995                         "BarFoo") == 0);
06996 
06997   /* Realloc shorter again */
06998   
06999   if (!dbus_message_set_path (message, "/foo"))
07000     _dbus_assert_not_reached ("out of memory");
07001   _dbus_assert (strcmp (dbus_message_get_path (message),
07002                         "/foo") == 0);
07003 
07004   if (!dbus_message_set_interface (message, "org.Foo"))
07005     _dbus_assert_not_reached ("out of memory");
07006   _dbus_assert (strcmp (dbus_message_get_interface (message),
07007                         "org.Foo") == 0);
07008   
07009   if (!dbus_message_set_member (message, "Bar"))
07010     _dbus_assert_not_reached ("out of memory");
07011   _dbus_assert (strcmp (dbus_message_get_member (message),
07012                         "Bar") == 0);
07013   
07014   dbus_message_unref (message);
07015   
07016   /* Test the vararg functions */
07017   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07018                                           "/org/freedesktop/TestPath",
07019                                           "Foo.TestInterface",
07020                                           "TestMethod");
07021   _dbus_message_set_serial (message, 1);
07022   dbus_message_append_args (message,
07023                             DBUS_TYPE_INT32, -0x12345678,
07024 #ifdef DBUS_HAVE_INT64
07025                             DBUS_TYPE_INT64, DBUS_INT64_CONSTANT (-0x123456789abcd),
07026                             DBUS_TYPE_UINT64, DBUS_UINT64_CONSTANT (0x123456789abcd),
07027 #endif
07028                             DBUS_TYPE_STRING, "Test string",
07029                             DBUS_TYPE_DOUBLE, 3.14159,
07030                             DBUS_TYPE_BOOLEAN, TRUE,
07031                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
07032                             _DBUS_N_ELEMENTS (our_uint32_array),
07033                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
07034                             _DBUS_N_ELEMENTS (our_int32_array),
07035 #ifdef DBUS_HAVE_INT64
07036                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
07037                             _DBUS_N_ELEMENTS (our_uint64_array),
07038                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
07039                             _DBUS_N_ELEMENTS (our_int64_array),
07040 #endif
07041                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
07042                             _DBUS_N_ELEMENTS (our_string_array),
07043                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
07044                             _DBUS_N_ELEMENTS (our_double_array),
07045                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
07046                             _DBUS_N_ELEMENTS (our_byte_array),
07047                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
07048                             _DBUS_N_ELEMENTS (our_boolean_array),
07049                             0);
07050   
07051   dbus_message_append_iter_init (message, &iter);
07052   dbus_message_iter_append_dict (&iter, &child_iter);
07053   dbus_message_iter_append_dict_key (&child_iter, "test");
07054   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07055   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
07056 
07057   i = 0;
07058   sig[i++] = DBUS_TYPE_INT32;
07059 #ifdef DBUS_HAVE_INT64
07060   sig[i++] = DBUS_TYPE_INT64;
07061   sig[i++] = DBUS_TYPE_UINT64;
07062 #endif
07063   sig[i++] = DBUS_TYPE_STRING;
07064   sig[i++] = DBUS_TYPE_DOUBLE;
07065   sig[i++] = DBUS_TYPE_BOOLEAN;
07066   sig[i++] = DBUS_TYPE_ARRAY;
07067   sig[i++] = DBUS_TYPE_UINT32;
07068   sig[i++] = DBUS_TYPE_ARRAY;
07069   sig[i++] = DBUS_TYPE_INT32;
07070 #ifdef DBUS_HAVE_INT64
07071   sig[i++] = DBUS_TYPE_ARRAY;
07072   sig[i++] = DBUS_TYPE_UINT64;
07073   sig[i++] = DBUS_TYPE_ARRAY;
07074   sig[i++] = DBUS_TYPE_INT64;
07075 #endif
07076   sig[i++] = DBUS_TYPE_ARRAY;
07077   sig[i++] = DBUS_TYPE_STRING;
07078   sig[i++] = DBUS_TYPE_ARRAY;
07079   sig[i++] = DBUS_TYPE_DOUBLE;
07080   sig[i++] = DBUS_TYPE_ARRAY;
07081   sig[i++] = DBUS_TYPE_BYTE;
07082   sig[i++] = DBUS_TYPE_ARRAY;
07083   sig[i++] = DBUS_TYPE_BOOLEAN;
07084   sig[i++] = DBUS_TYPE_DICT;
07085   sig[i++] = DBUS_TYPE_UINT32;
07086   sig[i++] = DBUS_TYPE_INVALID;
07087 
07088   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
07089   
07090   _dbus_verbose_bytes_of_string (&message->header, 0,
07091                                  _dbus_string_get_length (&message->header));
07092   _dbus_verbose_bytes_of_string (&message->body, 0,
07093                                  _dbus_string_get_length (&message->body));
07094   
07095   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
07096                  sig, dbus_message_get_signature (message));
07097   
07098   s = dbus_message_get_signature (message);
07099   
07100   _dbus_assert (dbus_message_has_signature (message, sig));
07101   _dbus_assert (strcmp (s, sig) == 0);
07102   
07103   verify_test_message (message);
07104 
07105   copy = dbus_message_copy (message);
07106   
07107   _dbus_assert (message->client_serial == copy->client_serial);
07108   _dbus_assert (message->reply_serial == copy->reply_serial);
07109   _dbus_assert (message->header_padding == copy->header_padding);
07110   
07111   _dbus_assert (_dbus_string_get_length (&message->header) ==
07112                 _dbus_string_get_length (&copy->header));
07113 
07114   _dbus_assert (_dbus_string_get_length (&message->body) ==
07115                 _dbus_string_get_length (&copy->body));
07116   
07117   verify_test_message (copy);
07118 
07119   name1 = dbus_message_get_interface (message);
07120   name2 = dbus_message_get_interface (copy);
07121 
07122   _dbus_assert (strcmp (name1, name2) == 0);
07123 
07124   name1 = dbus_message_get_member (message);
07125   name2 = dbus_message_get_member (copy);
07126 
07127   _dbus_assert (strcmp (name1, name2) == 0);
07128   
07129   dbus_message_unref (message);  
07130   dbus_message_unref (copy);
07131 
07132   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07133                                           "/org/freedesktop/TestPath",
07134                                           "Foo.TestInterface",
07135                                           "TestMethod");
07136 
07137   _dbus_message_set_serial (message, 1);
07138   dbus_message_set_reply_serial (message, 0x12345678);
07139 
07140   dbus_message_append_iter_init (message, &iter);
07141   dbus_message_iter_append_string (&iter, "Test string");
07142   dbus_message_iter_append_int32 (&iter, -0x12345678);
07143   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
07144   dbus_message_iter_append_double (&iter, 3.14159);
07145 
07146   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
07147   dbus_message_iter_append_double (&child_iter, 1.5);
07148   dbus_message_iter_append_double (&child_iter, 2.5);
07149 
07150   /* dict */
07151   dbus_message_iter_append_dict (&iter, &child_iter);
07152   dbus_message_iter_append_dict_key (&child_iter, "test");
07153   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07154 
07155   /* dict (in dict) */
07156   dbus_message_iter_append_dict_key (&child_iter, "testdict");
07157   dbus_message_iter_append_dict (&child_iter, &child_iter2);
07158 
07159   dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
07160   dbus_message_iter_append_string (&child_iter2, "dictvalue");
07161 
07162   /* array of array of int32  (in dict) */
07163   dbus_message_iter_append_dict_key (&child_iter, "array");
07164   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
07165   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07166   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
07167   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
07168   _dbus_warn ("next call expected to fail with wrong array type\n");
07169   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
07170   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07171   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
07172   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
07173   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
07174   
07175   dbus_message_iter_append_byte (&iter, 0xF0);
07176 
07177   dbus_message_iter_append_nil (&iter);
07178 
07179   dbus_message_iter_append_custom (&iter, "MyTypeName",
07180                                    "data", 5);
07181   
07182   dbus_message_iter_append_byte (&iter, 0xF0);
07183 
07184   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_INT32);
07185 
07186   dbus_message_iter_append_byte (&iter, 0xF0);
07187 
07188   dbus_message_iter_append_dict (&iter, &child_iter);
07189 
07190   dbus_message_iter_append_byte (&iter, 0xF0);
07191 
07192   message_iter_test (message);
07193   
07194   /* Message loader test */
07195   _dbus_message_lock (message);
07196   loader = _dbus_message_loader_new ();
07197 
07198   /* check ref/unref */
07199   _dbus_message_loader_ref (loader);
07200   _dbus_message_loader_unref (loader);
07201   
07202   /* Write the header data one byte at a time */
07203   data = _dbus_string_get_const_data (&message->header);
07204   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
07205     {
07206       DBusString *buffer;
07207 
07208       _dbus_message_loader_get_buffer (loader, &buffer);
07209       _dbus_string_append_byte (buffer, data[i]);
07210       _dbus_message_loader_return_buffer (loader, buffer, 1);
07211     }
07212 
07213   /* Write the body data one byte at a time */
07214   data = _dbus_string_get_const_data (&message->body);
07215   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
07216     {
07217       DBusString *buffer;
07218 
07219       _dbus_message_loader_get_buffer (loader, &buffer);
07220       _dbus_string_append_byte (buffer, data[i]);
07221       _dbus_message_loader_return_buffer (loader, buffer, 1);
07222     }
07223 
07224   copy = dbus_message_copy (message); /* save for tests below */
07225   dbus_message_unref (message);
07226 
07227   /* Now pop back the message */
07228   if (!_dbus_message_loader_queue_messages (loader))
07229     _dbus_assert_not_reached ("no memory to queue messages");
07230   
07231   if (_dbus_message_loader_get_is_corrupted (loader))
07232     _dbus_assert_not_reached ("message loader corrupted");
07233   
07234   message = _dbus_message_loader_pop_message (loader);
07235   if (!message)
07236     _dbus_assert_not_reached ("received a NULL message");
07237 
07238   if (dbus_message_get_reply_serial (message) != 0x12345678)
07239     _dbus_assert_not_reached ("reply serial fields differ");
07240   
07241   message_iter_test (message);
07242   
07243   dbus_message_unref (message);
07244   _dbus_message_loader_unref (loader);
07245 
07246   message = dbus_message_new_method_return (copy);
07247   if (message == NULL)
07248     _dbus_assert_not_reached ("out of memory\n");
07249   dbus_message_unref (copy);
07250 
07251   if (!dbus_message_append_args (message,
07252                                  DBUS_TYPE_STRING, "hello",
07253                                  DBUS_TYPE_INVALID))
07254     _dbus_assert_not_reached ("no memory");
07255 
07256   if (!dbus_message_has_signature (message, "s"))
07257     _dbus_assert_not_reached ("method return has wrong signature");
07258 
07259   dbus_error_init (&error);
07260   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
07261                               &t, DBUS_TYPE_INVALID))
07262     
07263     {
07264       _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
07265       exit (1);
07266     }
07267   dbus_free (t);
07268   
07269   dbus_message_unref (message);
07270   
07271   /* Now load every message in test_data_dir if we have one */
07272   if (test_data_dir == NULL)
07273     return TRUE;
07274 
07275   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
07276                                                         (DBusForeachMessageFileFunc)
07277                                                         dbus_internal_do_not_use_try_message_file,
07278                                                         NULL);
07279 }
07280 
07281 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Jun 9 05:01:26 2004 for D-BUS by doxygen1.2.15