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

dbus-message.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-message.c  DBusMessage object
00003  *
00004  * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
00005  * Copyright (C) 2002, 2003  CodeFactory AB
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dbus-internals.h"
00026 #include "dbus-marshal.h"
00027 #include "dbus-message.h"
00028 #include "dbus-message-internal.h"
00029 #include "dbus-memory.h"
00030 #include "dbus-list.h"
00031 #include "dbus-message-builder.h"
00032 #include "dbus-dataslot.h"
00033 #include <string.h>
00034 
00048 typedef struct
00049 {
00050   int name_offset;  
00051   int value_offset; 
00052 } HeaderField;
00053 
00055 #define BYTE_ORDER_OFFSET    0
00056 
00057 #define TYPE_OFFSET          1
00058 
00059 #define FLAGS_OFFSET         2
00060 
00061 #define VERSION_OFFSET       3
00062 
00063 #define HEADER_LENGTH_OFFSET 4
00064 
00065 #define BODY_LENGTH_OFFSET   8
00066 
00067 #define CLIENT_SERIAL_OFFSET 12
00068 
00069 
00077 struct DBusMessage
00078 {
00079   DBusAtomic refcount; 
00081   DBusString header; 
00086   HeaderField header_fields[DBUS_HEADER_FIELD_LAST + 1]; 
00090   dbus_uint32_t client_serial; 
00091   dbus_uint32_t reply_serial;  
00093   int header_padding; 
00095   DBusString body;   
00097   char byte_order; 
00099   unsigned int locked : 1; 
00101   DBusList *size_counters;   
00102   long size_counter_delta;   
00104   dbus_uint32_t changed_stamp; 
00106   DBusDataSlotList slot_list;   
00108 #ifndef DBUS_DISABLE_CHECKS
00109   int generation; 
00110 #endif
00111 };
00112 
00113 enum {
00114   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
00115   DBUS_MESSAGE_ITER_TYPE_ARRAY,
00116   DBUS_MESSAGE_ITER_TYPE_DICT
00117 };
00118 
00120 typedef struct DBusMessageRealIter DBusMessageRealIter;
00121 
00127 struct DBusMessageRealIter
00128 {
00129   DBusMessageRealIter *parent_iter; 
00130   DBusMessage *message; 
00131   dbus_uint32_t changed_stamp; 
00133   /* This is an int instead of an enum to get a guaranteed size for the dummy: */
00134   int type; 
00136   int pos; 
00137   int end; 
00138   int container_start; 
00139   int container_length_pos; 
00141   int wrote_dict_key; 
00143   int array_type_pos; 
00144   int array_type_done; 
00145 };
00146 
00157 void
00158 _dbus_message_get_network_data (DBusMessage          *message,
00159                                 const DBusString    **header,
00160                                 const DBusString    **body)
00161 {
00162   _dbus_assert (message->locked);
00163   
00164   *header = &message->header;
00165   *body = &message->body;
00166 }
00167 
00168 static void
00169 clear_header_padding (DBusMessage *message)
00170 {
00171   _dbus_string_shorten (&message->header,
00172                         message->header_padding);
00173   message->header_padding = 0;
00174 }              
00175 
00176 #ifdef DBUS_DISABLE_CHECKS
00177 #define is_valid_error_name(x) TRUE
00178 #else
00179 static dbus_bool_t
00180 is_valid_error_name (const char *error_name)                                          
00181 {
00182   DBusString the_error_name;
00183 
00184   if (error_name == NULL)
00185     return FALSE;
00186   
00187   _dbus_string_init_const (&the_error_name, error_name);
00188   return _dbus_string_validate_error_name (&the_error_name, 0,   
00189                                            _dbus_string_get_length (&the_error_name));
00190 }
00191 #endif
00192 
00193 static dbus_bool_t
00194 append_header_padding (DBusMessage *message)
00195 {
00196   int old_len;
00197   old_len = _dbus_string_get_length (&message->header);
00198   if (!_dbus_string_align_length (&message->header, 8))
00199     return FALSE;
00200 
00201   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
00202 
00203   return TRUE;
00204 }
00205 
00206 #ifdef DBUS_BUILD_TESTS
00207 /* tests-only until it's actually used */
00208 static dbus_int32_t
00209 get_int_field (DBusMessage *message,
00210                int          field)
00211 {
00212   int offset;
00213 
00214   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00215   
00216   offset = message->header_fields[field].value_offset;
00217   
00218   if (offset < 0)
00219     return -1; /* useless if -1 is a valid value of course */
00220   
00221   return _dbus_demarshal_int32 (&message->header,
00222                                 message->byte_order,
00223                                 offset,
00224                                 NULL);
00225 }
00226 #endif
00227 
00228 static dbus_uint32_t
00229 get_uint_field (DBusMessage *message,
00230                 int          field)
00231 {
00232   int offset;
00233   
00234   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00235   
00236   offset = message->header_fields[field].value_offset;
00237   
00238   if (offset < 0)
00239     return 0; /* useless if 0 is a valid value of course */
00240   
00241   return _dbus_demarshal_uint32 (&message->header,
00242                                  message->byte_order,
00243                                  offset,
00244                                  NULL);
00245 }
00246 
00247 static const char*
00248 get_string_field (DBusMessage *message,
00249                   int          field,
00250                   int         *len)
00251 {
00252   int offset;
00253   const char *data;
00254 
00255   _dbus_return_val_if_fail (message->generation == _dbus_current_generation,
00256                             NULL);
00257   
00258   offset = message->header_fields[field].value_offset;
00259 
00260   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00261   
00262   if (offset < 0)
00263     return NULL;
00264 
00265   /* offset points to string length, string data follows it */
00266   /* FIXME _dbus_demarshal_const_string() that returned
00267    * a reference to the string plus its len might be nice.
00268    */
00269   
00270   if (len)
00271     *len = _dbus_demarshal_uint32 (&message->header,
00272                                    message->byte_order,
00273                                    offset,
00274                                    NULL);
00275 
00276   data = _dbus_string_get_const_data (&message->header);
00277   
00278   return data + (offset + 4); 
00279 }
00280 
00281 /* returns FALSE if no memory, TRUE with NULL path if no field */
00282 static dbus_bool_t
00283 get_path_field_decomposed (DBusMessage  *message,
00284                            int           field,
00285                            char       ***path)
00286 {
00287   int offset;
00288 
00289   offset = message->header_fields[field].value_offset;
00290 
00291   _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
00292   
00293   if (offset < 0)
00294     {
00295       *path = NULL;
00296       return TRUE;
00297     }
00298 
00299   return _dbus_demarshal_object_path (&message->header,
00300                                       message->byte_order,
00301                                       offset,
00302                                       NULL,
00303                                       path, NULL);
00304 }
00305 
00306 #ifdef DBUS_BUILD_TESTS
00307 static dbus_bool_t
00308 append_int_field (DBusMessage *message,
00309                   int          field,
00310                   int          value)
00311 {
00312   _dbus_assert (!message->locked);
00313 
00314   clear_header_padding (message);
00315   
00316   message->header_fields[field].name_offset =
00317     _dbus_string_get_length (&message->header);
00318   
00319   if (!_dbus_string_append_byte (&message->header, field))
00320     goto failed;
00321 
00322   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
00323     goto failed;
00324 
00325   if (!_dbus_string_align_length (&message->header, 4))
00326     goto failed;
00327   
00328   message->header_fields[field].value_offset =
00329     _dbus_string_get_length (&message->header);
00330   
00331   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
00332                             value))
00333     goto failed;
00334 
00335   if (!append_header_padding (message))
00336     goto failed;
00337   
00338   return TRUE;
00339   
00340  failed:
00341   _dbus_string_set_length (&message->header,
00342                            message->header_fields[field].name_offset);
00343   message->header_fields[field].name_offset  = -1;
00344   message->header_fields[field].value_offset = -1;
00345 
00346   /* this must succeed because it was allocated on function entry and
00347    * DBusString doesn't ever realloc smaller
00348    */
00349   if (!append_header_padding (message))
00350     _dbus_assert_not_reached ("failed to reappend header padding");
00351   return FALSE;
00352 }
00353 #endif
00354 
00355 static dbus_bool_t
00356 append_uint_field (DBusMessage *message,
00357                    int          field,
00358                    int          value)
00359 {
00360   _dbus_assert (!message->locked);
00361 
00362   clear_header_padding (message);
00363   
00364   message->header_fields[field].name_offset =
00365     _dbus_string_get_length (&message->header);
00366   
00367   if (!_dbus_string_append_byte (&message->header, field))
00368     goto failed;
00369 
00370   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_UINT32))
00371     goto failed;
00372 
00373   if (!_dbus_string_align_length (&message->header, 4))
00374     goto failed;
00375   
00376   message->header_fields[field].value_offset =
00377     _dbus_string_get_length (&message->header);
00378   
00379   if (!_dbus_marshal_uint32 (&message->header, message->byte_order,
00380                              value))
00381     goto failed;
00382 
00383   if (!append_header_padding (message))
00384     goto failed;
00385   
00386   return TRUE;
00387   
00388  failed:
00389   _dbus_string_set_length (&message->header,
00390                            message->header_fields[field].name_offset);
00391   message->header_fields[field].name_offset  = -1;
00392   message->header_fields[field].value_offset = -1;
00393 
00394   /* this must succeed because it was allocated on function entry and
00395    * DBusString doesn't ever realloc smaller
00396    */
00397   if (!append_header_padding (message))
00398     _dbus_assert_not_reached ("failed to reappend header padding");
00399   return FALSE;
00400 }
00401 
00405 #define MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING (1 + 1 + 3 + 4 + 1 + 8)
00406 
00407 static dbus_bool_t
00408 append_string_field_len (DBusMessage *message,
00409                          int          field,
00410                          int          type,
00411                          const char  *value,
00412                          int          value_len)
00413 {
00414   _dbus_assert (!message->locked);
00415 
00416   clear_header_padding (message);
00417   
00418   message->header_fields[field].name_offset =
00419     _dbus_string_get_length (&message->header);
00420   
00421   if (!_dbus_string_append_byte (&message->header, field))
00422     goto failed;
00423   
00424   if (!_dbus_string_append_byte (&message->header, type))
00425     goto failed;
00426 
00427   if (!_dbus_string_align_length (&message->header, 4))
00428     goto failed;
00429   
00430   message->header_fields[field].value_offset =
00431     _dbus_string_get_length (&message->header);
00432   
00433   if (!_dbus_marshal_string_len (&message->header, message->byte_order,
00434                                  value, value_len))
00435     goto failed;
00436 
00437   if (!append_header_padding (message))
00438     goto failed;
00439   
00440   return TRUE;
00441   
00442  failed:
00443   _dbus_string_set_length (&message->header,
00444                            message->header_fields[field].name_offset);
00445   message->header_fields[field].name_offset  = -1;
00446   message->header_fields[field].value_offset = -1;
00447 
00448   /* this must succeed because it was allocated on function entry and
00449    * DBusString doesn't ever realloc smaller
00450    */
00451   if (!append_header_padding (message))
00452     _dbus_assert_not_reached ("failed to reappend header padding");
00453   
00454   return FALSE;
00455 }
00456 
00457 static dbus_bool_t
00458 append_string_field (DBusMessage *message,
00459                      int          field,
00460                      int          type,
00461                      const char  *value)
00462 {
00463   int value_len;
00464 
00465   value_len = strlen (value);
00466 
00467   return append_string_field_len (message, field, type, value, value_len);
00468 }
00469 
00470 static int
00471 get_type_alignment (int type)
00472 {
00473   int alignment;
00474   
00475   switch (type)
00476     {
00477     case DBUS_TYPE_NIL:
00478     case DBUS_TYPE_BYTE:
00479     case DBUS_TYPE_BOOLEAN:
00480       alignment = 0;
00481       break;
00482 
00483     case DBUS_TYPE_INT32:
00484     case DBUS_TYPE_UINT32:
00485     case DBUS_TYPE_STRING:
00486     case DBUS_TYPE_OBJECT_PATH:
00487       /* These are aligned 4 because they have a length as the
00488        * first field;
00489        */
00490     case DBUS_TYPE_CUSTOM:
00491     case DBUS_TYPE_DICT:
00492       alignment = 4;
00493       break;
00494 
00495     case DBUS_TYPE_INT64:
00496     case DBUS_TYPE_UINT64:
00497     case DBUS_TYPE_DOUBLE:
00498       alignment = 8;
00499       break;
00500 
00501     case DBUS_TYPE_ARRAY:
00502       _dbus_assert_not_reached ("passed an ARRAY type to get_type_alignment()");
00503       alignment = 0; /* quiet gcc */
00504       break;
00505 
00506     case DBUS_TYPE_INVALID:
00507     default:
00508       _dbus_assert_not_reached ("passed an invalid or unknown type to get_type_alignment()");
00509       alignment = 0; /* quiet gcc */
00510       break;
00511     }
00512 
00513   return alignment;
00514 }
00515 
00516 static dbus_bool_t
00517 iterate_one_field (const DBusString *str,
00518                    int               byte_order,
00519                    int               name_offset,
00520                    int              *next_offset_p,
00521                    int              *field_name_p,
00522                    DBusString       *append_copy_to,
00523                    int              *copy_name_offset_p,
00524                    int              *copy_value_offset_p)
00525 {
00526   int name, type, array_type;
00527   int alignment;
00528   int type_len;
00529   int type_pos;
00530   int value_pos;
00531   int value_len;
00532   int value_end;
00533   int pos;
00534 
00535 #if 0
00536   _dbus_verbose ("%s: name_offset=%d, append to %p\n",
00537                  _DBUS_FUNCTION_NAME, name_offset, append_copy_to);
00538 #endif
00539   
00540   pos = name_offset;
00541   
00542   name = _dbus_string_get_byte (str, name_offset);
00543   pos++;
00544 
00545   type_pos = pos;
00546   type = _dbus_string_get_byte (str, type_pos);
00547   pos++;
00548   type_len = 1;
00549 
00550   array_type = type;
00551   /* find out the type of our array */
00552   while (array_type == DBUS_TYPE_ARRAY)
00553     {
00554       pos++;
00555       type_len++;
00556       array_type = _dbus_string_get_byte (str, pos);
00557     }
00558 
00559 #if 0
00560   _dbus_verbose ("%s: name %s, type '%c' %d at %d len %d, array type '%c' %d\n",
00561                  _DBUS_FUNCTION_NAME,
00562                  _dbus_header_field_to_string (name),
00563                  type, type, type_pos, type_len, array_type, array_type);
00564 #endif
00565   
00566 #ifndef DBUS_DISABLE_ASSERT
00567   if (!_dbus_type_is_valid (array_type))
00568     {
00569       _dbus_warn ("type '%c' %d is not valid in %s\n",
00570                   array_type, array_type, _DBUS_FUNCTION_NAME);
00571       _dbus_assert_not_reached ("invalid type");
00572     }
00573 #endif
00574       
00575   alignment = get_type_alignment (array_type);
00576       
00577   if (alignment > 0)
00578     pos = _DBUS_ALIGN_VALUE (pos, alignment);
00579 
00580   _dbus_verbose ("%s: alignment %d value at pos %d\n",
00581                  _DBUS_FUNCTION_NAME, alignment, pos);
00582   
00583   /* pos now points to our value */
00584   if (!_dbus_marshal_get_arg_end_pos (str, byte_order,
00585                                       type, pos, &value_end))
00586     _dbus_assert_not_reached ("failed to get the byte after this header");
00587 
00588   value_pos = pos;
00589   value_len = value_end - value_pos;
00590 
00591   _dbus_verbose ("%s: value_pos %d value_len %d value_end %d\n",
00592                  _DBUS_FUNCTION_NAME, value_pos, value_len, value_end);
00593   
00594   if (next_offset_p)
00595     *next_offset_p = pos + value_len;
00596 
00597   if (field_name_p)
00598     *field_name_p = name;
00599 
00600   if (append_copy_to)
00601     {
00602       int orig_len;
00603 
00604       orig_len = _dbus_string_get_length (append_copy_to);
00605 
00606       if (copy_name_offset_p)
00607         *copy_name_offset_p = orig_len;
00608       
00609       if (!_dbus_string_append_byte (append_copy_to, name))
00610         goto failed_copy;
00611 
00612       if (!_dbus_string_copy_len (str, type_pos, type_len,
00613                                   append_copy_to,
00614                                   _dbus_string_get_length (append_copy_to)))
00615         goto failed_copy;
00616 
00617       if (!_dbus_string_align_length (append_copy_to, alignment))
00618         goto failed_copy;
00619 
00620       if (copy_value_offset_p)
00621         *copy_value_offset_p = _dbus_string_get_length (append_copy_to);
00622       
00623       if (!_dbus_string_copy_len (str, value_pos, value_len,
00624                                   append_copy_to,
00625                                   _dbus_string_get_length (append_copy_to)))
00626         goto failed_copy;
00627       
00628       return TRUE;
00629 
00630     failed_copy:
00631       _dbus_verbose ("%s: Failed copying old fields to new string\n",
00632                      _DBUS_FUNCTION_NAME);
00633       _dbus_string_set_length (append_copy_to, orig_len);
00634       return FALSE;
00635     }
00636   else
00637     return TRUE;
00638 }
00639 
00640 #ifndef DBUS_DISABLE_ASSERT
00641 static void
00642 verify_header_fields (DBusMessage *message)
00643 {
00644   int i;
00645   i = 0;
00646   while (i <= DBUS_HEADER_FIELD_LAST)
00647     {
00648       if (message->header_fields[i].name_offset >= 0)
00649         _dbus_assert (_dbus_string_get_byte (&message->header,
00650                                              message->header_fields[i].name_offset) ==
00651                       i);
00652       ++i;
00653     }
00654 }
00655 #else /* DBUS_DISABLE_ASSERT */
00656 #define verify_header_fields(x)
00657 #endif /* DBUS_DISABLE_ASSERT */
00658 
00659 /* In this function we delete one field and re-align all the fields
00660  * following it.
00661  */
00662 static dbus_bool_t
00663 delete_one_and_re_align (DBusMessage *message,
00664                          int          name_offset_to_delete)
00665 {
00666   DBusString copy;
00667   int new_fields_front_padding;
00668   int next_offset;
00669   int field_name;
00670   dbus_bool_t retval;
00671   HeaderField new_header_fields[DBUS_HEADER_FIELD_LAST+1];
00672   
00673   _dbus_assert (name_offset_to_delete < _dbus_string_get_length (&message->header));
00674   verify_header_fields (message);
00675 
00676   _dbus_verbose ("%s: Deleting one field at offset %d\n",
00677                  _DBUS_FUNCTION_NAME,
00678                  name_offset_to_delete);
00679   
00680   retval = FALSE;
00681 
00682   clear_header_padding (message);
00683   
00684   if (!_dbus_string_init_preallocated (&copy,
00685                                        _dbus_string_get_length (&message->header) -
00686                                        name_offset_to_delete + 8))
00687     {
00688       _dbus_verbose ("%s: Failed to init string to hold copy of fields\n",
00689                      _DBUS_FUNCTION_NAME);
00690       goto out_0;
00691     }
00692   
00693   /* Align the name offset of the first field in the same way it's
00694    * aligned in the real header
00695    */
00696   new_fields_front_padding = name_offset_to_delete % 8;
00697 
00698   if (!_dbus_string_insert_bytes (&copy, 0, new_fields_front_padding,
00699                                   '\0'))
00700     _dbus_assert_not_reached ("Should not have failed to insert bytes into preallocated string\n");
00701 
00702   memcpy (new_header_fields, message->header_fields,
00703           sizeof (new_header_fields));
00704   
00705   /* Now just re-marshal each field in the header to our temporary
00706    * buffer, skipping the first one. The tricky part is that the
00707    * fields are padded as if for previous_name_offset, but are in fact
00708    * at unaligned_name_offset
00709    */
00710 
00711   if (!iterate_one_field (&message->header,
00712                           message->byte_order,
00713                           name_offset_to_delete,
00714                           &next_offset,
00715                           &field_name, NULL, NULL, NULL))
00716     _dbus_assert_not_reached ("shouldn't have failed to alloc memory to skip the deleted field");
00717 
00718   _dbus_verbose ("  Skipping %s field which will be deleted; next_offset = %d\n",
00719                  _dbus_header_field_to_string (field_name), next_offset);
00720   
00721   /* This field no longer exists */
00722   if (field_name <= DBUS_HEADER_FIELD_LAST)
00723     {
00724       new_header_fields[field_name].name_offset = -1;
00725       new_header_fields[field_name].value_offset = -1;
00726     }
00727   
00728   while (next_offset < _dbus_string_get_length (&message->header))
00729     {
00730       int copy_name_offset;
00731       int copy_value_offset;
00732 
00733       if (!iterate_one_field (&message->header,
00734                               message->byte_order,
00735                               next_offset,
00736                               &next_offset,
00737                               &field_name,
00738                               &copy,
00739                               &copy_name_offset,
00740                               &copy_value_offset))
00741         {
00742           _dbus_verbose ("%s: OOM iterating one field\n",
00743                          _DBUS_FUNCTION_NAME);
00744           goto out_1;
00745         }
00746       
00747       if (field_name <= DBUS_HEADER_FIELD_LAST)
00748         {
00749           new_header_fields[field_name].name_offset = copy_name_offset - new_fields_front_padding + name_offset_to_delete;
00750           new_header_fields[field_name].value_offset = copy_value_offset - new_fields_front_padding + name_offset_to_delete;
00751           
00752           _dbus_verbose ("  Re-adding %s field at name_offset = %d value_offset = %d; next_offset = %d\n",
00753                          _dbus_header_field_to_string (field_name),
00754                          new_header_fields[field_name].name_offset,
00755                          new_header_fields[field_name].value_offset,
00756                          next_offset);
00757         }
00758     }
00759 
00760   if (!_dbus_string_replace_len (&copy,
00761                                  new_fields_front_padding,
00762                                  _dbus_string_get_length (&copy) - new_fields_front_padding,
00763                                  &message->header,
00764                                  name_offset_to_delete,
00765                                  _dbus_string_get_length (&message->header) - name_offset_to_delete))
00766     {
00767       _dbus_verbose ("%s: OOM moving copy back into header\n",
00768                      _DBUS_FUNCTION_NAME);
00769       goto out_1;
00770     }
00771   
00772   memcpy (message->header_fields, new_header_fields,
00773           sizeof (new_header_fields));
00774   verify_header_fields (message);
00775   
00776   retval = TRUE;
00777   
00778  out_1:
00779   _dbus_string_free (&copy);
00780   
00781  out_0:
00782   if (!append_header_padding (message))
00783     _dbus_assert_not_reached ("Failed to re-append header padding in re_align_field_recurse()");
00784   
00785   return retval;
00786 }
00787 
00788 static dbus_bool_t
00789 delete_field (DBusMessage *message,
00790               int          field,
00791               int          prealloc_header_space)
00792 {
00793   int offset;
00794 
00795   _dbus_assert (!message->locked);
00796 
00797   /* Prealloc */
00798   if (!_dbus_string_lengthen (&message->header, prealloc_header_space))
00799     {
00800       _dbus_verbose ("failed to prealloc %d bytes header space\n",
00801                      prealloc_header_space);
00802       return FALSE;
00803     }
00804   _dbus_string_shorten (&message->header, prealloc_header_space);
00805 
00806   /* Delete */
00807   offset = message->header_fields[field].name_offset;
00808   if (offset < 0)
00809     {
00810       _dbus_verbose ("header field didn't exist, no need to delete\n");
00811       return TRUE; /* field didn't exist */
00812     }
00813 
00814   return delete_one_and_re_align (message, offset);
00815 }
00816 
00817 #ifdef DBUS_BUILD_TESTS
00818 static dbus_bool_t
00819 set_int_field (DBusMessage *message,
00820                int          field,
00821                int          value)
00822 {
00823   int offset = message->header_fields[field].value_offset;
00824 
00825   _dbus_assert (!message->locked);
00826 
00827   _dbus_verbose ("set_int_field() field %d value '%d'\n",
00828                  field, value);
00829   
00830   if (offset < 0)
00831     {
00832       /* need to append the field */
00833       return append_int_field (message, field, value);
00834     }
00835   else
00836     {
00837       _dbus_marshal_set_int32 (&message->header,
00838                                message->byte_order,
00839                                offset, value);
00840 
00841       return TRUE;
00842     }
00843 }
00844 #endif
00845 
00846 static dbus_bool_t
00847 set_uint_field (DBusMessage  *message,
00848                 int           field,
00849                 dbus_uint32_t value)
00850 {
00851   int offset = message->header_fields[field].value_offset;
00852 
00853   _dbus_assert (!message->locked);
00854 
00855   _dbus_verbose ("set_uint_field() field %d value '%u'\n",
00856                  field, value);
00857   
00858   if (offset < 0)
00859     {
00860       /* need to append the field */
00861       return append_uint_field (message, field, value);
00862     }
00863   else
00864     {
00865       _dbus_marshal_set_uint32 (&message->header,
00866                                 message->byte_order,
00867                                 offset, value);
00868 
00869       return TRUE;
00870     }
00871 }
00872 
00873 static dbus_bool_t
00874 set_string_field (DBusMessage *message,
00875                   int          field,
00876                   int          type,
00877                   const char  *value)
00878 {
00879   int prealloc;
00880   int value_len;
00881   
00882   _dbus_assert (!message->locked);
00883 
00884   value_len = value ? strlen (value) : 0;
00885   
00886   /* the prealloc is so the append_string_field()
00887    * below won't fail, leaving us in inconsistent state
00888    */
00889   prealloc = value_len + MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING;
00890 
00891   _dbus_verbose ("set_string_field() field %d prealloc %d value '%s'\n",
00892                  field, prealloc, value);
00893   
00894   if (!delete_field (message, field, prealloc))
00895     return FALSE;
00896 
00897   if (value != NULL)
00898     {
00899       /* need to append the field */
00900       if (!append_string_field_len (message, field, type, value, value_len))
00901         _dbus_assert_not_reached ("Appending string field shouldn't have failed, due to preallocation");
00902     }
00903   
00904   return TRUE;
00905 }
00906 
00914 void
00915 _dbus_message_set_serial (DBusMessage  *message,
00916                           dbus_int32_t  serial)
00917 {
00918   _dbus_assert (!message->locked);
00919   _dbus_assert (dbus_message_get_serial (message) == 0);
00920 
00921   _dbus_marshal_set_uint32 (&message->header,
00922                             message->byte_order,
00923                             CLIENT_SERIAL_OFFSET,
00924                             serial);
00925 
00926   message->client_serial = serial;
00927 }
00928 
00937 dbus_bool_t
00938 dbus_message_set_reply_serial (DBusMessage   *message,
00939                                dbus_uint32_t  reply_serial)
00940 {
00941   _dbus_assert (!message->locked);
00942 
00943   if (set_uint_field (message,
00944                       DBUS_HEADER_FIELD_REPLY_SERIAL,
00945                       reply_serial))
00946     {
00947       message->reply_serial = reply_serial;
00948       return TRUE;
00949     }
00950   else
00951     return FALSE;
00952 }
00953 
00964 dbus_uint32_t
00965 dbus_message_get_serial (DBusMessage *message)
00966 {
00967   return message->client_serial;
00968 }
00969 
00976 dbus_uint32_t
00977 dbus_message_get_reply_serial  (DBusMessage *message)
00978 {
00979   return message->reply_serial;
00980 }
00981 
00994 void
00995 _dbus_message_add_size_counter_link (DBusMessage  *message,
00996                                      DBusList     *link)
00997 {
00998   /* right now we don't recompute the delta when message
00999    * size changes, and that's OK for current purposes
01000    * I think, but could be important to change later.
01001    * Do recompute it whenever there are no outstanding counters,
01002    * since it's basically free.
01003    */
01004   if (message->size_counters == NULL)
01005     {
01006       message->size_counter_delta =
01007         _dbus_string_get_length (&message->header) +
01008         _dbus_string_get_length (&message->body);
01009       
01010 #if 0
01011       _dbus_verbose ("message has size %ld\n",
01012                      message->size_counter_delta);
01013 #endif
01014     }
01015   
01016   _dbus_list_append_link (&message->size_counters, link);
01017   
01018   _dbus_counter_adjust (link->data, message->size_counter_delta);
01019 }
01020 
01030 dbus_bool_t
01031 _dbus_message_add_size_counter (DBusMessage *message,
01032                                 DBusCounter *counter)
01033 {
01034   DBusList *link;
01035 
01036   link = _dbus_list_alloc_link (counter);
01037   if (link == NULL)
01038     return FALSE;
01039 
01040   _dbus_counter_ref (counter);
01041   _dbus_message_add_size_counter_link (message, link);
01042 
01043   return TRUE;
01044 }
01045 
01054 void
01055 _dbus_message_remove_size_counter (DBusMessage  *message,
01056                                    DBusCounter  *counter,
01057                                    DBusList    **link_return)
01058 {
01059   DBusList *link;
01060 
01061   link = _dbus_list_find_last (&message->size_counters,
01062                                counter);
01063   _dbus_assert (link != NULL);
01064 
01065   _dbus_list_unlink (&message->size_counters,
01066                      link);
01067   if (link_return)
01068     *link_return = link;
01069   else
01070     _dbus_list_free_link (link);
01071 
01072   _dbus_counter_adjust (counter, - message->size_counter_delta);
01073 
01074   _dbus_counter_unref (counter);
01075 }
01076 
01077 static dbus_bool_t
01078 dbus_message_create_header (DBusMessage *message,
01079                             int          type,
01080                             const char  *service,
01081                             const char  *path,
01082                             const char  *interface,
01083                             const char  *member,
01084                             const char  *error_name)
01085 {
01086   unsigned int flags;
01087 
01088   _dbus_assert ((interface && member) ||
01089                 (error_name) ||
01090                 !(interface || member || error_name));
01091   _dbus_assert (error_name == NULL || is_valid_error_name (error_name));
01092   
01093   if (!_dbus_string_append_byte (&message->header, message->byte_order))
01094     return FALSE;
01095 
01096   if (!_dbus_string_append_byte (&message->header, type))
01097     return FALSE;
01098   
01099   flags = 0;
01100   if (!_dbus_string_append_byte (&message->header, flags))
01101     return FALSE;
01102 
01103   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
01104     return FALSE;
01105 
01106   /* header length */
01107   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01108     return FALSE;
01109 
01110   /* body length */
01111   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01112     return FALSE;
01113 
01114   /* serial */
01115   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
01116     return FALSE;
01117   
01118   /* Marshal all the fields (Marshall Fields?) */
01119   
01120   if (path != NULL)
01121     {
01122       if (!append_string_field (message,
01123                                 DBUS_HEADER_FIELD_PATH,
01124                                 DBUS_TYPE_OBJECT_PATH,
01125                                 path))
01126         return FALSE;
01127     }
01128   
01129   if (service != NULL)
01130     {
01131       if (!append_string_field (message,
01132                                 DBUS_HEADER_FIELD_DESTINATION,
01133                                 DBUS_TYPE_STRING,
01134                                 service))
01135         return FALSE;
01136     }
01137 
01138   if (interface != NULL)
01139     {
01140       if (!append_string_field (message,
01141                                 DBUS_HEADER_FIELD_INTERFACE,
01142                                 DBUS_TYPE_STRING,
01143                                 interface))
01144         return FALSE;
01145     }
01146 
01147   if (member != NULL)
01148     {
01149       if (!append_string_field (message,
01150                                 DBUS_HEADER_FIELD_MEMBER,
01151                                 DBUS_TYPE_STRING,
01152                                 member))
01153         return FALSE;
01154     }
01155 
01156   if (error_name != NULL)
01157     {
01158       if (!append_string_field (message,
01159                                 DBUS_HEADER_FIELD_ERROR_NAME,
01160                                 DBUS_TYPE_STRING,
01161                                 error_name))
01162         return FALSE;
01163     }
01164 
01165   /* @todo if we make signature optional when body is empty, we don't
01166    * need to do this here.
01167    */
01168   if (!append_string_field (message,
01169                             DBUS_HEADER_FIELD_SIGNATURE,
01170                             DBUS_TYPE_STRING,
01171                             ""))
01172     return FALSE;
01173   
01174   return TRUE;
01175 }
01176 
01186 void
01187 _dbus_message_lock (DBusMessage  *message)
01188 {
01189   if (!message->locked)
01190     {
01191       /* Fill in our lengths */
01192       _dbus_marshal_set_uint32 (&message->header,
01193                                 message->byte_order,
01194                                 HEADER_LENGTH_OFFSET,
01195                                 _dbus_string_get_length (&message->header));
01196 
01197       _dbus_marshal_set_uint32 (&message->header,
01198                                 message->byte_order,
01199                                 BODY_LENGTH_OFFSET,
01200                                 _dbus_string_get_length (&message->body));
01201 
01202       message->locked = TRUE;
01203     }
01204 }
01205 
01237 static dbus_bool_t
01238 dbus_message_set_signature (DBusMessage *message,
01239                             const char  *signature)
01240 {
01241   _dbus_return_val_if_fail (message != NULL, FALSE);
01242   _dbus_return_val_if_fail (!message->locked, FALSE);
01243   
01244   return set_string_field (message,
01245                            DBUS_HEADER_FIELD_SIGNATURE,
01246                            DBUS_TYPE_STRING,
01247                            signature);
01248 }
01249 
01258 static dbus_bool_t
01259 dbus_message_append_to_signature (DBusMessage *message,
01260                                   const char  *append_bytes)
01261 {
01262   const char *signature;
01263   DBusString append_str;
01264   dbus_bool_t retval;
01265   
01266   _dbus_return_val_if_fail (append_bytes != NULL, FALSE);
01267   _dbus_return_val_if_fail (message != NULL, FALSE);
01268   _dbus_return_val_if_fail (!message->locked, FALSE);
01269 
01270   retval = FALSE;
01271   
01272   /* FIXME Just really inefficient for the moment; later we could
01273    * speed it up a lot by poking more directly at the header data
01274    */
01275   signature = dbus_message_get_signature (message);
01276 
01277   if (!_dbus_string_init (&append_str))
01278     return FALSE;
01279 
01280   if (signature && !_dbus_string_append (&append_str, signature))
01281     goto out;
01282 
01283   if (!_dbus_string_append (&append_str, append_bytes))
01284     goto out;
01285   
01286   if (!set_string_field (message,
01287                          DBUS_HEADER_FIELD_SIGNATURE,
01288                          DBUS_TYPE_STRING,
01289                          _dbus_string_get_const_data (&append_str)))
01290     goto out;
01291 
01292   retval = TRUE;
01293   
01294  out:
01295   
01296   _dbus_string_free (&append_str);
01297 
01298   return retval;
01299 }
01300 
01309 static dbus_bool_t
01310 _dbus_message_append_byte_to_signature (DBusMessage  *message,
01311                                         unsigned char append_byte)
01312 {
01313   char buf[2];
01314   
01315   _dbus_return_val_if_fail (message != NULL, FALSE);
01316   _dbus_return_val_if_fail (!message->locked, FALSE);
01317   
01318   buf[0] = append_byte;
01319   buf[1] = '\0';
01320 
01321   return dbus_message_append_to_signature (message, buf);
01322 }
01323 
01330 static void
01331 _dbus_message_remove_byte_from_signature (DBusMessage  *message)
01332 {
01333   const char *signature;
01334   
01335   _dbus_return_if_fail (message != NULL);
01336   _dbus_return_if_fail (!message->locked);
01337 
01338   signature = dbus_message_get_signature (message);
01339 
01340   _dbus_return_if_fail (signature != NULL);
01341   
01342   if (!delete_field (message,
01343                      DBUS_HEADER_FIELD_SIGNATURE,
01344                      0))
01345     _dbus_assert_not_reached ("failed to delete signature field");
01346 
01347   /* reappend one shorter (could this be any less efficient? the code will
01348    * go away later anyhow)
01349    */
01350   if (!append_string_field_len (message, DBUS_HEADER_FIELD_SIGNATURE,
01351                                 DBUS_TYPE_STRING, signature,
01352                                 strlen (signature) - 1))
01353     _dbus_assert_not_reached ("reappending shorter signature shouldn't have failed");
01354 }
01355 
01363 static void
01364 free_size_counter (void *element,
01365                    void *data)
01366 {
01367   DBusCounter *counter = element;
01368   DBusMessage *message = data;
01369   
01370   _dbus_counter_adjust (counter, - message->size_counter_delta);
01371 
01372   _dbus_counter_unref (counter);
01373 }
01374 
01375 static void
01376 dbus_message_finalize (DBusMessage *message)
01377 {
01378   _dbus_assert (message->refcount.value == 0);
01379   
01380   /* This calls application callbacks! */
01381   _dbus_data_slot_list_free (&message->slot_list);
01382   
01383   _dbus_list_foreach (&message->size_counters,
01384                       free_size_counter, message);
01385   _dbus_list_clear (&message->size_counters);
01386   
01387   _dbus_string_free (&message->header);
01388   _dbus_string_free (&message->body);
01389   
01390   dbus_free (message);
01391 }
01392 
01393 /* Message Cache
01394  * 
01395  * We cache some DBusMessage to reduce the overhead of allocating
01396  * them.  In my profiling this consistently made about an 8%
01397  * difference.  It avoids the malloc for the message, the malloc for
01398  * the slot list, the malloc for the header string and body string,
01399  * and the associated free() calls. It does introduce another global
01400  * lock which could be a performance issue in certain cases.
01401  *
01402  * For the echo client/server the round trip time goes from around
01403  * .000077 to .000069 with the message cache on my laptop. The sysprof
01404  * change is as follows (numbers are cumulative percentage):
01405  *
01406  *  with message cache implemented as array as it is now (0.000069 per):
01407  *    new_empty_header           1.46
01408  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
01409  *      mutex_unlock             0.25
01410  *      self                     0.41
01411  *    unref                      2.24
01412  *      self                     0.68
01413  *      list_clear               0.43
01414  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
01415  *      mutex_unlock             0.25
01416  *
01417  *  with message cache implemented as list (0.000070 per roundtrip):
01418  *    new_empty_header           2.72
01419  *      list_pop_first           1.88
01420  *    unref                      3.3
01421  *      list_prepend             1.63
01422  *
01423  * without cache (0.000077 per roundtrip):
01424  *    new_empty_header           6.7
01425  *      string_init_preallocated 3.43
01426  *        dbus_malloc            2.43
01427  *      dbus_malloc0             2.59
01428  * 
01429  *    unref                      4.02
01430  *      string_free              1.82
01431  *        dbus_free              1.63
01432  *      dbus_free                0.71
01433  *
01434  * If you implement the message_cache with a list, the primary reason
01435  * it's slower is that you add another thread lock (on the DBusList
01436  * mempool).
01437  */
01438 
01439 /* Avoid caching huge messages */
01440 #define MAX_MESSAGE_SIZE_TO_CACHE _DBUS_ONE_MEGABYTE
01441 /* Avoid caching too many messages */
01442 #define MAX_MESSAGE_CACHE_SIZE    5
01443 
01444 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
01445 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
01446 static int message_cache_count = 0;
01447 static dbus_bool_t message_cache_shutdown_registered = FALSE;
01448 
01449 static void
01450 dbus_message_cache_shutdown (void *data)
01451 {
01452   int i;
01453 
01454   _DBUS_LOCK (message_cache);
01455 
01456   i = 0;
01457   while (i < MAX_MESSAGE_CACHE_SIZE)
01458     {
01459       if (message_cache[i])
01460         dbus_message_finalize (message_cache[i]);
01461       
01462       ++i;
01463     }
01464 
01465   message_cache_count = 0;
01466   message_cache_shutdown_registered = FALSE;
01467   
01468   _DBUS_UNLOCK (message_cache);
01469 }
01470 
01478 static DBusMessage*
01479 dbus_message_get_cached (void)
01480 {
01481   DBusMessage *message;
01482   int i;
01483 
01484   message = NULL;
01485   
01486   _DBUS_LOCK (message_cache);
01487 
01488   _dbus_assert (message_cache_count >= 0);
01489   
01490   if (message_cache_count == 0)
01491     {
01492       _DBUS_UNLOCK (message_cache);
01493       return NULL;
01494     }
01495 
01496   /* This is not necessarily true unless count > 0, and
01497    * message_cache is uninitialized until the shutdown is
01498    * registered
01499    */
01500   _dbus_assert (message_cache_shutdown_registered);
01501   
01502   i = 0;
01503   while (i < MAX_MESSAGE_CACHE_SIZE)
01504     {
01505       if (message_cache[i])
01506         {
01507           message = message_cache[i];
01508           message_cache[i] = NULL;
01509           message_cache_count -= 1;
01510           break;
01511         }
01512       ++i;
01513     }
01514   _dbus_assert (message_cache_count >= 0);
01515   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
01516   _dbus_assert (message != NULL);
01517 
01518   _DBUS_UNLOCK (message_cache);
01519 
01520   _dbus_assert (message->refcount.value == 0);
01521   _dbus_assert (message->size_counters == NULL);
01522   
01523   return message;
01524 }
01525 
01531 static void
01532 dbus_message_cache_or_finalize (DBusMessage *message)
01533 {
01534   dbus_bool_t was_cached;
01535   int i;
01536 
01537   _dbus_assert (message->refcount.value == 0);
01538   
01539   /* This calls application code and has to be done first thing
01540    * without holding the lock
01541    */
01542   _dbus_data_slot_list_clear (&message->slot_list);
01543   
01544   _dbus_list_foreach (&message->size_counters,
01545                       free_size_counter, message);
01546   _dbus_list_clear (&message->size_counters);
01547   
01548   was_cached = FALSE;
01549 
01550   _DBUS_LOCK (message_cache);
01551 
01552   if (!message_cache_shutdown_registered)
01553     {
01554       _dbus_assert (message_cache_count == 0);
01555       
01556       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
01557         goto out;
01558 
01559       i = 0;
01560       while (i < MAX_MESSAGE_CACHE_SIZE)
01561         {
01562           message_cache[i] = NULL;
01563           ++i;
01564         }
01565       
01566       message_cache_shutdown_registered = TRUE;
01567     }
01568 
01569   _dbus_assert (message_cache_count >= 0);
01570   
01571   if ((_dbus_string_get_length (&message->header) +
01572        _dbus_string_get_length (&message->body)) >
01573       MAX_MESSAGE_SIZE_TO_CACHE)
01574     goto out;
01575   
01576   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
01577     goto out;
01578 
01579   /* Find empty slot */
01580   i = 0;
01581   while (message_cache[i] != NULL)
01582     ++i;
01583 
01584   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
01585 
01586   _dbus_assert (message_cache[i] == NULL);
01587   message_cache[i] = message;
01588   message_cache_count += 1;
01589   was_cached = TRUE;
01590   
01591  out:
01592   _DBUS_UNLOCK (message_cache);
01593 
01594   if (!was_cached)
01595     dbus_message_finalize (message);
01596 }
01597 
01598 static DBusMessage*
01599 dbus_message_new_empty_header (void)
01600 {
01601   DBusMessage *message;
01602   int i;
01603   dbus_bool_t from_cache;
01604 
01605   message = dbus_message_get_cached ();
01606 
01607   if (message != NULL)
01608     {
01609       from_cache = TRUE;
01610     }
01611   else
01612     {
01613       from_cache = FALSE;
01614       message = dbus_new (DBusMessage, 1);
01615       if (message == NULL)
01616         return NULL;
01617 #ifndef DBUS_DISABLE_CHECKS
01618       message->generation = _dbus_current_generation;
01619 #endif
01620     }
01621 
01622   message->refcount.value = 1;
01623   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
01624   message->client_serial = 0;
01625   message->reply_serial = 0;
01626   message->locked = FALSE;
01627   message->header_padding = 0;
01628   message->size_counters = NULL;
01629   message->size_counter_delta = 0;
01630   message->changed_stamp = 0;
01631 
01632   if (!from_cache)
01633     _dbus_data_slot_list_init (&message->slot_list);
01634   
01635   i = 0;
01636   while (i <= DBUS_HEADER_FIELD_LAST)
01637     {
01638       message->header_fields[i].name_offset  = -1;
01639       message->header_fields[i].value_offset = -1;
01640       ++i;
01641     }
01642 
01643   if (from_cache)
01644     {
01645       /* These can't fail since they shorten the string */
01646       _dbus_string_set_length (&message->header, 0);
01647       _dbus_string_set_length (&message->body, 0);
01648     }
01649   else
01650     {
01651       if (!_dbus_string_init_preallocated (&message->header, 32))
01652         {
01653           dbus_free (message);
01654           return NULL;
01655         }
01656       
01657       if (!_dbus_string_init_preallocated (&message->body, 32))
01658         {
01659           _dbus_string_free (&message->header);
01660           dbus_free (message);
01661           return NULL;
01662         }
01663     }
01664   
01665   return message;
01666 }
01667 
01676 DBusMessage*
01677 dbus_message_new (int message_type)
01678 {
01679   DBusMessage *message;
01680 
01681   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
01682   
01683   message = dbus_message_new_empty_header ();
01684   if (message == NULL)
01685     return NULL;
01686   
01687   if (!dbus_message_create_header (message,
01688                                    message_type,
01689                                    NULL, NULL, NULL, NULL, NULL))
01690     {
01691       dbus_message_unref (message);
01692       return NULL;
01693     }
01694   
01695   return message;
01696 }
01697 
01715 DBusMessage*
01716 dbus_message_new_method_call (const char *service,
01717                               const char *path,
01718                               const char *interface,
01719                               const char *method)
01720 {
01721   DBusMessage *message;
01722 
01723   _dbus_return_val_if_fail (path != NULL, NULL);
01724   _dbus_return_val_if_fail (method != NULL, NULL);
01725   
01726   message = dbus_message_new_empty_header ();
01727   if (message == NULL)
01728     return NULL;
01729   
01730   if (!dbus_message_create_header (message,
01731                                    DBUS_MESSAGE_TYPE_METHOD_CALL,
01732                                    service, path, interface, method, NULL))
01733     {
01734       dbus_message_unref (message);
01735       return NULL;
01736     }
01737   
01738   return message;
01739 }
01740 
01750 DBusMessage*
01751 dbus_message_new_method_return (DBusMessage *method_call)
01752 {
01753   DBusMessage *message;
01754   const char *sender;
01755 
01756   _dbus_return_val_if_fail (method_call != NULL, NULL);
01757   
01758   sender = get_string_field (method_call,
01759                              DBUS_HEADER_FIELD_SENDER,
01760                              NULL);
01761   
01762   /* sender is allowed to be null here in peer-to-peer case */
01763 
01764   message = dbus_message_new_empty_header ();
01765   if (message == NULL)
01766     return NULL;
01767   
01768   if (!dbus_message_create_header (message,
01769                                    DBUS_MESSAGE_TYPE_METHOD_RETURN,
01770                                    sender, NULL, NULL, NULL, NULL))
01771     {
01772       dbus_message_unref (message);
01773       return NULL;
01774     }
01775 
01776   dbus_message_set_no_reply (message, TRUE);
01777 
01778   if (!dbus_message_set_reply_serial (message,
01779                                       dbus_message_get_serial (method_call)))
01780     {
01781       dbus_message_unref (message);
01782       return NULL;
01783     }
01784 
01785   return message;
01786 }
01787 
01800 DBusMessage*
01801 dbus_message_new_signal (const char *path,
01802                          const char *interface,
01803                          const char *name)
01804 {
01805   DBusMessage *message;
01806 
01807   _dbus_return_val_if_fail (path != NULL, NULL);
01808   _dbus_return_val_if_fail (interface != NULL, NULL);
01809   _dbus_return_val_if_fail (name != NULL, NULL);
01810   
01811   message = dbus_message_new_empty_header ();
01812   if (message == NULL)
01813     return NULL;
01814   
01815   if (!dbus_message_create_header (message,
01816                                    DBUS_MESSAGE_TYPE_SIGNAL,
01817                                    NULL, path, interface, name, NULL))
01818     {
01819       dbus_message_unref (message);
01820       return NULL;
01821     }
01822 
01823   dbus_message_set_no_reply (message, TRUE);
01824   
01825   return message;
01826 }
01827 
01837 DBusMessage*
01838 dbus_message_new_error (DBusMessage *reply_to,
01839                         const char  *error_name,
01840                         const char  *error_message)
01841 {
01842   DBusMessage *message;
01843   const char *sender;
01844   DBusMessageIter iter;
01845 
01846   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01847   _dbus_return_val_if_fail (error_name != NULL, NULL);
01848   _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
01849   
01850   sender = get_string_field (reply_to,
01851                              DBUS_HEADER_FIELD_SENDER,
01852                              NULL);
01853 
01854   /* sender may be NULL for non-message-bus case or
01855    * when the message bus is dealing with an unregistered
01856    * connection.
01857    */
01858   message = dbus_message_new_empty_header ();
01859   if (message == NULL)
01860     return NULL;
01861   
01862   if (!dbus_message_create_header (message,
01863                                    DBUS_MESSAGE_TYPE_ERROR,
01864                                    sender, NULL, NULL, NULL, error_name))
01865     {
01866       dbus_message_unref (message);
01867       return NULL;
01868     }
01869 
01870   dbus_message_set_no_reply (message, TRUE);
01871   
01872   if (!dbus_message_set_reply_serial (message,
01873                                       dbus_message_get_serial (reply_to)))
01874     {
01875       dbus_message_unref (message);
01876       return NULL;
01877     }
01878 
01879   if (error_message != NULL)
01880     {
01881       dbus_message_append_iter_init (message, &iter);
01882       if (!dbus_message_iter_append_string (&iter, error_message))
01883         {
01884           dbus_message_unref (message);
01885           return NULL;
01886         }
01887     }
01888   
01889   return message;
01890 }
01891 
01902 DBusMessage*
01903 dbus_message_new_error_printf (DBusMessage *reply_to,
01904                                const char  *error_name,
01905                                const char  *error_format,
01906                                ...)
01907 {
01908   va_list args;
01909   DBusString str;
01910   DBusMessage *message;
01911 
01912   _dbus_return_val_if_fail (reply_to != NULL, NULL);
01913   _dbus_return_val_if_fail (error_name != NULL, NULL);
01914   _dbus_return_val_if_fail (is_valid_error_name (error_name), NULL);
01915   
01916   if (!_dbus_string_init (&str))
01917     return NULL;
01918 
01919   va_start (args, error_format);
01920 
01921   if (_dbus_string_append_printf_valist (&str, error_format, args))
01922     message = dbus_message_new_error (reply_to, error_name,
01923                                       _dbus_string_get_const_data (&str));
01924   else
01925     message = NULL;
01926   
01927   _dbus_string_free (&str);
01928 
01929   va_end (args);
01930 
01931   return message;
01932 }
01933 
01934 
01942 DBusMessage *
01943 dbus_message_copy (const DBusMessage *message)
01944 {
01945   DBusMessage *retval;
01946   int i;
01947 
01948   _dbus_return_val_if_fail (message != NULL, NULL);
01949   
01950   retval = dbus_new0 (DBusMessage, 1);
01951   if (retval == NULL)
01952     return NULL;
01953   
01954   retval->refcount.value = 1;
01955   retval->byte_order = message->byte_order;
01956   retval->client_serial = message->client_serial;
01957   retval->reply_serial = message->reply_serial;
01958   retval->header_padding = message->header_padding;
01959   retval->locked = FALSE;
01960 #ifndef DBUS_DISABLE_CHECKS
01961   retval->generation = message->generation;
01962 #endif
01963   
01964   if (!_dbus_string_init_preallocated (&retval->header,
01965                                        _dbus_string_get_length (&message->header)))
01966     {
01967       dbus_free (retval);
01968       return NULL;
01969     }
01970   
01971   if (!_dbus_string_init_preallocated (&retval->body,
01972                                        _dbus_string_get_length (&message->body)))
01973     {
01974       _dbus_string_free (&retval->header);
01975       dbus_free (retval);
01976       return NULL;
01977     }
01978   
01979   if (!_dbus_string_copy (&message->header, 0,
01980                           &retval->header, 0))
01981     goto failed_copy;
01982 
01983   if (!_dbus_string_copy (&message->body, 0,
01984                           &retval->body, 0))
01985     goto failed_copy;
01986   
01987   for (i = 0; i <= DBUS_HEADER_FIELD_LAST; i++)
01988     {
01989       retval->header_fields[i] = message->header_fields[i];
01990     }
01991   
01992   return retval;
01993 
01994  failed_copy:
01995   _dbus_string_free (&retval->header);
01996   _dbus_string_free (&retval->body);
01997   dbus_free (retval);
01998   
01999   return NULL;  
02000 }
02001 
02002 
02010 DBusMessage *
02011 dbus_message_ref (DBusMessage *message)
02012 {
02013   dbus_int32_t old_refcount;
02014 
02015   _dbus_return_val_if_fail (message != NULL, NULL);
02016   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
02017   
02018   old_refcount = _dbus_atomic_inc (&message->refcount);
02019   _dbus_assert (old_refcount >= 1);
02020 
02021   return message;
02022 }
02023 
02030 void
02031 dbus_message_unref (DBusMessage *message)
02032 {
02033  dbus_int32_t old_refcount;
02034 
02035   _dbus_return_if_fail (message != NULL);
02036   _dbus_return_if_fail (message->generation == _dbus_current_generation);
02037   
02038   old_refcount = _dbus_atomic_dec (&message->refcount);
02039   
02040   _dbus_assert (old_refcount >= 0);
02041 
02042   if (old_refcount == 1)
02043     {
02044       /* Calls application callbacks! */
02045       dbus_message_cache_or_finalize (message);
02046     }
02047 }
02048 
02060 int
02061 dbus_message_get_type (DBusMessage *message)
02062 {
02063   int type;
02064 
02065   type = _dbus_string_get_byte (&message->header, 1);
02066   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
02067 
02068   return type;
02069 }
02070 
02080 dbus_bool_t
02081 dbus_message_set_path (DBusMessage   *message,
02082                        const char    *object_path)
02083 {
02084   _dbus_return_val_if_fail (message != NULL, FALSE);
02085   _dbus_return_val_if_fail (!message->locked, FALSE);
02086 
02087   return set_string_field (message,
02088                            DBUS_HEADER_FIELD_PATH,
02089                            DBUS_TYPE_OBJECT_PATH,
02090                            object_path);
02091 }
02092 
02101 const char*
02102 dbus_message_get_path (DBusMessage   *message)
02103 {
02104   _dbus_return_val_if_fail (message != NULL, NULL);
02105   
02106   return get_string_field (message, DBUS_HEADER_FIELD_PATH, NULL);
02107 }
02108 
02124 dbus_bool_t
02125 dbus_message_get_path_decomposed (DBusMessage   *message,
02126                                   char        ***path)
02127 {
02128   _dbus_return_val_if_fail (message != NULL, FALSE);
02129   _dbus_return_val_if_fail (path != NULL, FALSE);
02130 
02131   return get_path_field_decomposed (message,
02132                                     DBUS_HEADER_FIELD_PATH,
02133                                     path);
02134 }
02135 
02146 dbus_bool_t
02147 dbus_message_set_interface (DBusMessage  *message,
02148                             const char   *interface)
02149 {
02150   _dbus_return_val_if_fail (message != NULL, FALSE);
02151   _dbus_return_val_if_fail (!message->locked, FALSE);
02152 
02153   return set_string_field (message,
02154                            DBUS_HEADER_FIELD_INTERFACE,
02155                            DBUS_TYPE_STRING,
02156                            interface);
02157 }
02158 
02168 const char*
02169 dbus_message_get_interface (DBusMessage *message)
02170 {
02171   _dbus_return_val_if_fail (message != NULL, NULL);
02172   
02173   return get_string_field (message, DBUS_HEADER_FIELD_INTERFACE, NULL);
02174 }
02175 
02186 dbus_bool_t
02187 dbus_message_set_member (DBusMessage  *message,
02188                        const char   *member)
02189 {
02190   _dbus_return_val_if_fail (message != NULL, FALSE);
02191   _dbus_return_val_if_fail (!message->locked, FALSE);
02192 
02193   return set_string_field (message,
02194                            DBUS_HEADER_FIELD_MEMBER,
02195                            DBUS_TYPE_STRING,
02196                            member);
02197 }
02198 
02207 const char*
02208 dbus_message_get_member (DBusMessage *message)
02209 {
02210   _dbus_return_val_if_fail (message != NULL, NULL);
02211   
02212   return get_string_field (message,
02213                            DBUS_HEADER_FIELD_MEMBER,
02214                            NULL);
02215 }
02216 
02225 dbus_bool_t
02226 dbus_message_set_error_name (DBusMessage  *message,
02227                              const char   *error_name)
02228 {
02229   _dbus_return_val_if_fail (message != NULL, FALSE);
02230   _dbus_return_val_if_fail (!message->locked, FALSE);
02231   _dbus_return_val_if_fail (error_name == NULL || is_valid_error_name (error_name), FALSE);
02232   
02233   return set_string_field (message,
02234                            DBUS_HEADER_FIELD_ERROR_NAME,
02235                            DBUS_TYPE_STRING,
02236                            error_name);
02237 }
02238 
02245 const char*
02246 dbus_message_get_error_name (DBusMessage *message)
02247 {
02248   _dbus_return_val_if_fail (message != NULL, NULL);
02249   
02250   return get_string_field (message,
02251                            DBUS_HEADER_FIELD_ERROR_NAME,
02252                            NULL);
02253 }
02254 
02262 dbus_bool_t
02263 dbus_message_set_destination (DBusMessage  *message,
02264                               const char   *destination)
02265 {
02266   _dbus_return_val_if_fail (message != NULL, FALSE);
02267   _dbus_return_val_if_fail (!message->locked, FALSE);
02268 
02269   return set_string_field (message,
02270                            DBUS_HEADER_FIELD_DESTINATION,
02271                            DBUS_TYPE_STRING,
02272                            destination);
02273 }
02274 
02281 const char*
02282 dbus_message_get_destination (DBusMessage *message)
02283 {
02284   _dbus_return_val_if_fail (message != NULL, NULL);
02285   
02286   return get_string_field (message,
02287                            DBUS_HEADER_FIELD_DESTINATION,
02288                            NULL);
02289 }
02290 
02309 dbus_bool_t
02310 dbus_message_append_args (DBusMessage *message,
02311                           int first_arg_type,
02312                           ...)
02313 {
02314   dbus_bool_t retval;
02315   va_list var_args;
02316 
02317   _dbus_return_val_if_fail (message != NULL, FALSE);
02318   
02319   va_start (var_args, first_arg_type);
02320   retval = dbus_message_append_args_valist (message,
02321                                             first_arg_type,
02322                                             var_args);
02323   va_end (var_args);
02324 
02325   return retval;
02326 }
02327 
02328 /* Swap into our byte order if message isn't already.
02329  * Done only when required, which allows the bus to avoid
02330  * ever doing this as it routes messages.
02331  */
02332 static void
02333 _dbus_message_ensure_our_byte_order (DBusMessage *message)
02334 {
02335   if (message->byte_order == DBUS_COMPILER_BYTE_ORDER)
02336     return;
02337 
02338   
02339 
02340 
02341 }
02342 
02355 dbus_bool_t
02356 dbus_message_get_args (DBusMessage     *message,
02357                        DBusError       *error,
02358                        int              first_arg_type,
02359                        ...)
02360 {
02361   dbus_bool_t retval;
02362   va_list var_args;
02363 
02364   _dbus_return_val_if_fail (message != NULL, FALSE);
02365   _dbus_return_val_if_error_is_set (error, FALSE);
02366   
02367   va_start (var_args, first_arg_type);
02368   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
02369   va_end (var_args);
02370 
02371   return retval;
02372 }
02373 
02386 dbus_bool_t
02387 dbus_message_get_args_valist (DBusMessage     *message,
02388                               DBusError       *error,
02389                               int              first_arg_type,
02390                               va_list          var_args)
02391 {
02392   DBusMessageIter iter;
02393 
02394   _dbus_return_val_if_fail (message != NULL, FALSE);
02395   _dbus_return_val_if_error_is_set (error, FALSE);
02396   
02397   dbus_message_iter_init (message, &iter);
02398   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
02399 }
02400 
02413 dbus_bool_t
02414 dbus_message_iter_get_args (DBusMessageIter *iter,
02415                             DBusError       *error,
02416                             int              first_arg_type,
02417                             ...)
02418 {
02419   dbus_bool_t retval;
02420   va_list var_args;
02421 
02422   _dbus_return_val_if_fail (iter != NULL, FALSE);
02423   _dbus_return_val_if_error_is_set (error, FALSE);
02424   
02425   va_start (var_args, first_arg_type);
02426   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
02427   va_end (var_args);
02428 
02429   return retval;
02430 }
02431 
02440 dbus_bool_t
02441 dbus_message_iter_init (DBusMessage     *message,
02442                         DBusMessageIter *iter)
02443 {
02444   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02445 
02446   _dbus_return_val_if_fail (message != NULL, FALSE);
02447   _dbus_return_val_if_fail (iter != NULL, FALSE);
02448   
02449   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
02450   
02451   real->message = message;
02452   real->parent_iter = NULL;
02453   real->changed_stamp = message->changed_stamp;
02454   
02455   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
02456   real->pos = 0;
02457   real->end = _dbus_string_get_length (&message->body);
02458   
02459   real->container_start = 0;
02460   real->container_length_pos = 0;
02461   real->wrote_dict_key = 0;
02462   real->array_type_pos = 0;
02463 
02464   return real->end > real->pos;
02465 }
02466 
02467 #ifndef DBUS_DISABLE_CHECKS
02468 static dbus_bool_t
02469 dbus_message_iter_check (DBusMessageRealIter *iter)
02470 {
02471   if (iter == NULL)
02472     {
02473       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
02474       return FALSE;
02475     }
02476   
02477   if (iter->changed_stamp != iter->message->changed_stamp)
02478     {
02479       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
02480       return FALSE;
02481     }
02482   
02483   if (iter->pos < 0 || iter->pos > iter->end)
02484     {
02485       _dbus_warn ("dbus iterator check failed: invalid position\n");
02486       return FALSE;
02487     }
02488 
02489   return TRUE;
02490 }
02491 #endif /* DBUS_DISABLE_CHECKS */
02492 
02493 static int
02494 skip_array_type (DBusMessageRealIter *iter, int pos)
02495 {
02496   const char *data;
02497 
02498   do
02499     {
02500       data = _dbus_string_get_const_data_len (&iter->message->body,
02501                                               pos++, 1);
02502     }
02503   while (*data == DBUS_TYPE_ARRAY);
02504   
02505   return pos;
02506 }
02507 
02508 /* FIXME what are these _dbus_type_is_valid() checks for?
02509  * haven't we validated the message?
02510  */
02511 static int
02512 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
02513 {
02514   const char *data;
02515   int pos, len;
02516   
02517   switch (iter->type)
02518     {
02519     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02520       data = _dbus_string_get_const_data_len (&iter->message->body,
02521                                               iter->pos, 1);
02522       if (_dbus_type_is_valid (*data))
02523         *type = *data;
02524       else
02525         *type = DBUS_TYPE_INVALID;
02526       
02527       return skip_array_type (iter, iter->pos);
02528       
02529     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02530       data = _dbus_string_get_const_data_len (&iter->message->body,
02531                                               iter->array_type_pos, 1);
02532       if (_dbus_type_is_valid (*data))
02533         *type = *data;
02534       else
02535         *type = DBUS_TYPE_INVALID;
02536       
02537       return iter->pos;
02538       
02539     case DBUS_MESSAGE_ITER_TYPE_DICT:
02540       /* Get the length of the string */
02541       len = _dbus_demarshal_uint32 (&iter->message->body,
02542                                     iter->message->byte_order,
02543                                     iter->pos, &pos);
02544       pos = pos + len + 1;
02545 
02546       data = _dbus_string_get_const_data_len (&iter->message->body,
02547                                               pos, 1);
02548       if (_dbus_type_is_valid (*data))
02549         *type = *data;
02550       else
02551         *type = DBUS_TYPE_INVALID;
02552 
02553       return skip_array_type (iter, pos);
02554       
02555     default:
02556       _dbus_assert_not_reached ("Invalid iter type");
02557       break;
02558     }
02559   *type = DBUS_TYPE_INVALID;
02560   return iter->pos;
02561 }
02562 
02563 
02571 dbus_bool_t
02572 dbus_message_iter_has_next (DBusMessageIter *iter)
02573 {
02574   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02575   int end_pos;
02576   int type, pos;
02577 
02578   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02579 
02580   if (real->pos >= real->end)
02581     return FALSE;
02582   
02583   pos = dbus_message_iter_get_data_start (real, &type);
02584   
02585   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02586                                       real->message->byte_order,
02587                                       type, pos, &end_pos))
02588     return FALSE;
02589   
02590   if (end_pos >= real->end)
02591     return FALSE;
02592 
02593   return TRUE;  
02594 }
02595 
02602 dbus_bool_t
02603 dbus_message_iter_next (DBusMessageIter *iter)
02604 {
02605   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02606   int end_pos;
02607   int type, pos;
02608 
02609   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02610 
02611   pos = dbus_message_iter_get_data_start (real, &type);
02612   
02613   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
02614                                       real->message->byte_order,
02615                                       type, pos, &end_pos))
02616     return FALSE;
02617 
02618   if (end_pos >= real->end)
02619     return FALSE;
02620 
02621   real->pos = end_pos;
02622 
02623   return TRUE;
02624 }
02625 
02633 int
02634 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
02635 {
02636   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02637   int type, pos;
02638 
02639   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02640 
02641   if (real->pos >= real->end)
02642     {
02643       _dbus_verbose ("  iterator at or beyond end of message\n");
02644       return DBUS_TYPE_INVALID;
02645     }
02646 
02647   pos = dbus_message_iter_get_data_start (real, &type);
02648   
02649   return type;
02650 }
02651 
02652 /* FIXME why do we validate the typecode in here, hasn't the message
02653  * already been verified?
02654  */
02655 static int
02656 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
02657 {
02658   const char *data;
02659   int _array_type_pos;
02660   int len, pos;
02661   
02662   switch (iter->type)
02663     {
02664     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
02665       _array_type_pos = iter->pos + 1;
02666       break;
02667     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
02668       _array_type_pos = iter->array_type_pos + 1;
02669       break;
02670     case DBUS_MESSAGE_ITER_TYPE_DICT:
02671       /* Get the length of the string */
02672       len = _dbus_demarshal_uint32 (&iter->message->body,
02673                                     iter->message->byte_order,
02674                                     iter->pos, &pos);
02675       pos = pos + len + 1;
02676       data = _dbus_string_get_const_data_len (&iter->message->body,
02677                                               pos + 1, 1);
02678       _array_type_pos = pos + 1;
02679       break;
02680     default:
02681       _dbus_assert_not_reached ("wrong iter type");
02682       return DBUS_TYPE_INVALID;
02683     }
02684 
02685   if (array_type_pos != NULL)
02686     *array_type_pos = _array_type_pos;
02687   
02688   data = _dbus_string_get_const_data_len (&iter->message->body,
02689                                           _array_type_pos, 1);
02690   if (_dbus_type_is_valid (*data))
02691     return  *data;
02692   
02693   return DBUS_TYPE_INVALID;
02694 }
02695 
02696 
02706 int
02707 dbus_message_iter_get_array_type (DBusMessageIter *iter)
02708 {
02709   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02710   int type, pos;
02711 
02712   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
02713 
02714   if (real->pos >= real->end)
02715     return DBUS_TYPE_INVALID;
02716 
02717   pos = dbus_message_iter_get_data_start (real, &type);
02718 
02719   _dbus_assert (type == DBUS_TYPE_ARRAY);
02720 
02721   return iter_get_array_type (real, NULL);
02722 }
02723 
02724 
02734 char *
02735 dbus_message_iter_get_string (DBusMessageIter *iter)
02736 {
02737   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02738   int type, pos;
02739 
02740   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02741   pos = dbus_message_iter_get_data_start (real, &type);
02742   
02743   _dbus_assert (type == DBUS_TYPE_STRING);
02744 
02745   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02746                                  pos, NULL);
02747 }
02748 
02758 char *
02759 dbus_message_iter_get_object_path (DBusMessageIter  *iter)
02760 {
02761   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02762   int type, pos;
02763 
02764   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
02765 
02766   pos = dbus_message_iter_get_data_start (real, &type);
02767   
02768   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
02769 
02770   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02771                                  pos, NULL);
02772 }
02773 
02787 dbus_bool_t
02788 dbus_message_iter_get_custom (DBusMessageIter   *iter,
02789                               char             **name,
02790                               unsigned char    **value,
02791                               int               *len)
02792 {
02793   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02794   int type, pos;
02795   char *_name;
02796 
02797   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
02798 
02799   pos = dbus_message_iter_get_data_start (real, &type);
02800   
02801   _dbus_assert (type == DBUS_TYPE_CUSTOM);
02802   
02803   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
02804                                   pos, &pos);
02805 
02806   if (_name == NULL)
02807     return FALSE;
02808   
02809   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
02810                                    pos, NULL, value, len))
02811     {
02812       dbus_free (_name);
02813       return FALSE;
02814     }
02815 
02816   *name = _name;
02817   
02818   return TRUE;
02819 }
02820 
02821 static void
02822 _dbus_message_iter_get_basic_type (DBusMessageIter *iter,
02823                                    char             type,
02824                                    void            *value)
02825 {
02826   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
02827   int item_type, pos;
02828 
02829   _dbus_return_if_fail (dbus_message_iter_check (real));
02830 
02831   pos = dbus_message_iter_get_data_start (real, &item_type);
02832   
02833   _dbus_assert (type == item_type);
02834   
02835   _dbus_demarshal_basic_type (&real->message->body,
02836                               type, value,
02837                               real->message->byte_order,
02838                               &pos);
02839 }
02840 
02841 
02864 dbus_bool_t
02865 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
02866                                    DBusError       *error,
02867                                    int              first_arg_type,
02868                                    va_list          var_args)
02869 {
02870   int spec_type, msg_type, i;
02871   dbus_bool_t retval;
02872 
02873   _dbus_return_val_if_fail (iter != NULL, FALSE);
02874   _dbus_return_val_if_error_is_set (error, FALSE);
02875 
02876   retval = FALSE;
02877   
02878   spec_type = first_arg_type;
02879   i = 0;
02880   
02881   while (spec_type != DBUS_TYPE_INVALID)
02882     {
02883       msg_type = dbus_message_iter_get_arg_type (iter);      
02884       
02885       if (msg_type != spec_type)
02886         {
02887           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02888                           "Argument %d is specified to be of type \"%s\", but "
02889                           "is actually of type \"%s\"\n", i,
02890                           _dbus_type_to_string (spec_type),
02891                           _dbus_type_to_string (msg_type));
02892 
02893           goto out;
02894         }
02895 
02896       switch (spec_type)
02897         {
02898         case DBUS_TYPE_NIL:
02899           break;
02900         case DBUS_TYPE_BOOLEAN:
02901           {
02902             dbus_bool_t *ptr;
02903 
02904             ptr = va_arg (var_args, dbus_bool_t *);
02905 
02906             *ptr = dbus_message_iter_get_boolean (iter);
02907             break;
02908           }
02909         case DBUS_TYPE_BYTE:
02910         case DBUS_TYPE_INT32:
02911         case DBUS_TYPE_UINT32:
02912 #ifdef DBUS_HAVE_INT64
02913         case DBUS_TYPE_INT64:
02914         case DBUS_TYPE_UINT64:
02915 #endif /* DBUS_HAVE_INT64 */
02916         case DBUS_TYPE_DOUBLE:
02917           {
02918             void *ptr = va_arg (var_args, double *);
02919             _dbus_message_iter_get_basic_type (iter, spec_type, ptr);
02920             break;
02921           }
02922 
02923         case DBUS_TYPE_STRING:
02924           {
02925             char **ptr;
02926 
02927             ptr = va_arg (var_args, char **);
02928 
02929             *ptr = dbus_message_iter_get_string (iter);
02930 
02931             if (!*ptr)
02932               {
02933                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02934                 goto out;
02935               }
02936             
02937             break;
02938           }
02939 
02940           case DBUS_TYPE_OBJECT_PATH:
02941           {
02942             char **ptr;
02943 
02944             ptr = va_arg (var_args, char **);
02945 
02946             *ptr = dbus_message_iter_get_object_path (iter);
02947 
02948             if (!*ptr)
02949               {
02950                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02951                 goto out;
02952               }
02953 
02954             break;
02955           }
02956 
02957         case DBUS_TYPE_CUSTOM:
02958           {
02959             char **name;
02960             unsigned char **data;
02961             int *len;
02962  
02963             name = va_arg (var_args, char **);
02964             data = va_arg (var_args, unsigned char **);
02965             len = va_arg (var_args, int *);
02966 
02967             if (!dbus_message_iter_get_custom (iter, name, data, len))
02968               {
02969                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
02970                 goto out;
02971               }
02972           }
02973           break;
02974         case DBUS_TYPE_ARRAY:
02975           {
02976             void **data;
02977             int *len, type;
02978             dbus_bool_t err = FALSE;
02979  
02980             type = va_arg (var_args, int);
02981             data = va_arg (var_args, void *);
02982             len = va_arg (var_args, int *);
02983 
02984             _dbus_return_val_if_fail (data != NULL, FALSE);
02985             _dbus_return_val_if_fail (len != NULL, FALSE);
02986             
02987             if (dbus_message_iter_get_array_type (iter) != type)
02988               {
02989                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
02990                                 "Argument %d is specified to be of type \"array of %s\", but "
02991                                 "is actually of type \"array of %s\"\n", i,
02992                                 _dbus_type_to_string (type),
02993                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
02994                 goto out;
02995               }
02996             
02997             switch (type)
02998               {
02999               case DBUS_TYPE_BYTE:
03000                 err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
03001                 break;
03002               case DBUS_TYPE_BOOLEAN:
03003                 err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
03004                 break;
03005               case DBUS_TYPE_INT32:
03006                 err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
03007                 break;
03008               case DBUS_TYPE_UINT32:
03009                 err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
03010                 break;
03011 #ifdef DBUS_HAVE_INT64
03012               case DBUS_TYPE_INT64:
03013                 err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
03014                 break;
03015               case DBUS_TYPE_UINT64:
03016                 err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
03017                 break;
03018 #endif /* DBUS_HAVE_INT64 */
03019               case DBUS_TYPE_DOUBLE:
03020                 err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
03021                 break;
03022               case DBUS_TYPE_STRING:
03023                 err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
03024                 break;
03025               case DBUS_TYPE_OBJECT_PATH:
03026                 err = !dbus_message_iter_get_object_path_array (iter, (char ***)data, len);
03027                 break;
03028 
03029               case DBUS_TYPE_NIL:
03030               case DBUS_TYPE_ARRAY:
03031               case DBUS_TYPE_CUSTOM:
03032               case DBUS_TYPE_DICT:
03033                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
03034                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
03035                 goto out;
03036               default:
03037                 _dbus_warn ("Unknown field type %d\n", type);
03038                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
03039                 goto out;
03040               }
03041             if (err)
03042               {
03043                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
03044                 goto out;
03045               }
03046           }
03047           break;
03048         case DBUS_TYPE_DICT:
03049           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
03050           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
03051           goto out;
03052         default:          
03053           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
03054           _dbus_warn ("Unknown field type %d\n", spec_type);
03055           goto out;
03056         }
03057 
03058       spec_type = va_arg (var_args, int);
03059       if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
03060         {
03061           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
03062                           "Message has only %d arguments, but more were expected", i);
03063           goto out;
03064         }
03065 
03066       i++;
03067     }
03068   
03069   retval = TRUE;
03070   
03071  out:
03072   
03073   return retval;
03074 }
03075 
03085 unsigned char
03086 dbus_message_iter_get_byte (DBusMessageIter *iter)
03087 {
03088   unsigned char value = 0;
03089 
03090   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BYTE, &value);
03091 
03092   return value;
03093 }
03094 
03104 dbus_bool_t
03105 dbus_message_iter_get_boolean (DBusMessageIter *iter)
03106 {
03107   unsigned char value = 0;
03108 
03109   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BOOLEAN, &value);
03110 
03111   return (value != FALSE);
03112 }
03113 
03123 dbus_int32_t
03124 dbus_message_iter_get_int32 (DBusMessageIter *iter)
03125 {
03126   dbus_int32_t value = 0;
03127 
03128   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT32, &value);
03129 
03130   return value;
03131 }
03132 
03142 dbus_uint32_t
03143 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
03144 {
03145   dbus_int32_t value = 0;
03146 
03147   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT32, &value);
03148 
03149   return value;
03150 }
03151 
03152 #ifdef DBUS_HAVE_INT64
03153 
03165 dbus_int64_t
03166 dbus_message_iter_get_int64 (DBusMessageIter *iter)
03167 {
03168   dbus_int64_t value = 0;
03169 
03170   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT64, &value);
03171 
03172   return value;
03173 }
03174 
03186 dbus_uint64_t
03187 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
03188 {
03189   dbus_uint64_t value = 0;
03190 
03191   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT64, &value);
03192 
03193   return value;
03194 }
03195 
03196 #endif /* DBUS_HAVE_INT64 */
03197 
03207 double
03208 dbus_message_iter_get_double (DBusMessageIter *iter)
03209 {
03210   double value = 0.0;
03211 
03212   _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_DOUBLE, &value);
03213 
03214   return value;
03215 }
03216 
03230 dbus_bool_t
03231 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
03232                                        DBusMessageIter *array_iter,
03233                                        int             *array_type)
03234 {
03235   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03236   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
03237   int type, pos, len_pos, len, array_type_pos;
03238   int _array_type;
03239 
03240   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03241 
03242   pos = dbus_message_iter_get_data_start (real, &type);
03243   
03244   _dbus_assert (type == DBUS_TYPE_ARRAY);
03245 
03246   _array_type = iter_get_array_type (real, &array_type_pos);
03247   
03248   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
03249   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
03250                                 pos, &pos);
03251   
03252   array_real->parent_iter = real;
03253   array_real->message = real->message;
03254   array_real->changed_stamp = real->message->changed_stamp;
03255   
03256   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
03257   array_real->pos = pos;
03258   array_real->end = pos + len;
03259   
03260   array_real->container_start = pos;
03261   array_real->container_length_pos = len_pos;
03262   array_real->wrote_dict_key = 0;
03263   array_real->array_type_pos = array_type_pos;
03264   array_real->array_type_done = TRUE;
03265   
03266   if (array_type != NULL)
03267     *array_type = _array_type;
03268 
03269   return len > 0;
03270 }
03271 
03272 
03282 dbus_bool_t
03283 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
03284                                       DBusMessageIter *dict_iter)
03285 {
03286   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03287   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
03288   int type, pos, len_pos, len;
03289 
03290   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03291 
03292   pos = dbus_message_iter_get_data_start (real, &type);
03293   
03294   _dbus_assert (type == DBUS_TYPE_DICT);
03295 
03296   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
03297   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
03298                                 pos, &pos);
03299   
03300   dict_real->parent_iter = real;
03301   dict_real->message = real->message;
03302   dict_real->changed_stamp = real->message->changed_stamp;
03303   
03304   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
03305   dict_real->pos = pos;
03306   dict_real->end = pos + len;
03307   
03308   dict_real->container_start = pos;
03309   dict_real->container_length_pos = len_pos;
03310   dict_real->wrote_dict_key = 0;
03311 
03312   return len > 0;
03313 }
03314 
03315 static dbus_bool_t
03316 _dbus_message_iter_get_basic_type_array  (DBusMessageIter *iter,
03317                                           char             type,
03318                                           void           **array,
03319                                           int             *array_len)
03320 {
03321   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03322   int item_type, pos;
03323 
03324   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03325 
03326   pos = dbus_message_iter_get_data_start (real, &item_type);
03327   
03328   _dbus_assert (item_type == DBUS_TYPE_ARRAY);
03329 
03330   item_type = iter_get_array_type (real, NULL);
03331   
03332   _dbus_assert (type == item_type);
03333 
03334   return _dbus_demarshal_basic_type_array (&real->message->body,
03335                                            item_type, array, array_len,
03336                                            real->message->byte_order, &pos);
03337 }
03338 
03349 dbus_bool_t
03350 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
03351                                   unsigned char   **value,
03352                                   int              *len)
03353 {
03354   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BYTE,
03355                                                   (void **) value, len);
03356 }
03357 
03368 dbus_bool_t
03369 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
03370                                      unsigned char    **value,
03371                                      int               *len)
03372 {
03373   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BOOLEAN,
03374                                                   (void **) value, len);
03375 }
03376 
03387 dbus_bool_t
03388 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
03389                                     dbus_int32_t   **value,
03390                                     int             *len)
03391 {
03392   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT32,
03393                                                   (void **) value, len);
03394 }
03395 
03406 dbus_bool_t
03407 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
03408                                      dbus_uint32_t  **value,
03409                                      int             *len)
03410 {
03411   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT32,
03412                                                   (void **) value, len);
03413 }
03414 
03415 #ifdef DBUS_HAVE_INT64
03416 
03429 dbus_bool_t
03430 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
03431                                     dbus_int64_t   **value,
03432                                     int             *len)
03433 {
03434   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT64,
03435                                                   (void **) value, len);
03436 }
03437 
03450 dbus_bool_t
03451 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
03452                                      dbus_uint64_t  **value,
03453                                      int             *len)
03454 {
03455   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT64,
03456                                                   (void **) value, len);
03457 }
03458 
03459 #endif /* DBUS_HAVE_INT64 */
03460 
03471 dbus_bool_t
03472 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
03473                                      double         **value,
03474                                      int             *len)
03475 {
03476   return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_DOUBLE,
03477                                                   (void **) value, len);
03478 }
03479 
03495 dbus_bool_t
03496 dbus_message_iter_get_string_array (DBusMessageIter *iter,
03497                                     char          ***value,
03498                                     int             *len)
03499 {
03500   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03501   int type, pos;
03502 
03503   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03504 
03505   pos = dbus_message_iter_get_data_start (real, &type);
03506   
03507   _dbus_assert (type == DBUS_TYPE_ARRAY);
03508 
03509   type = iter_get_array_type (real, NULL);
03510   _dbus_assert (type == DBUS_TYPE_STRING);
03511 
03512   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
03513                                      pos, NULL, value, len))
03514     return FALSE;
03515   else
03516     return TRUE;
03517 }
03518 
03534 dbus_bool_t
03535 dbus_message_iter_get_object_path_array (DBusMessageIter *iter,
03536                                          char          ***value,
03537                                          int             *len)
03538 {
03539   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03540   int type, pos;
03541 
03542   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
03543 
03544   pos = dbus_message_iter_get_data_start (real, &type);
03545   
03546   _dbus_assert (type == DBUS_TYPE_ARRAY);
03547 
03548   type = iter_get_array_type (real, NULL);
03549   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
03550 
03551   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
03552                                      pos, NULL, value, len))
03553     return FALSE;
03554   else
03555     return TRUE;
03556 }
03557 
03567 char *
03568 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
03569 {
03570   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03571 
03572   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
03573 
03574   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03575 
03576   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
03577                                  real->pos, NULL);
03578 }
03579 
03588 void
03589 dbus_message_append_iter_init (DBusMessage     *message,
03590                                DBusMessageIter *iter)
03591 {
03592   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03593 
03594   _dbus_return_if_fail (message != NULL);
03595   _dbus_return_if_fail (iter != NULL);
03596   
03597   real->message = message;
03598   real->parent_iter = NULL;
03599   real->changed_stamp = message->changed_stamp;
03600   
03601   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
03602   real->end = _dbus_string_get_length (&real->message->body);
03603   real->pos = real->end;
03604   
03605   real->container_length_pos = 0;
03606   real->wrote_dict_key = 0;
03607 }
03608 
03609 #ifndef DBUS_DISABLE_CHECKS
03610 static dbus_bool_t
03611 dbus_message_iter_append_check (DBusMessageRealIter *iter)
03612 {
03613   if (iter == NULL)
03614     {
03615       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
03616       return FALSE;
03617     }
03618   
03619   if (iter->message->locked)
03620     {
03621       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
03622       return FALSE;
03623     }
03624       
03625   if (iter->changed_stamp != iter->message->changed_stamp)
03626     {
03627       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
03628       return FALSE;
03629     }
03630   
03631   if (iter->pos != iter->end)
03632     {
03633       _dbus_warn ("dbus iterator check failed: can only append at end of message");
03634       return FALSE;
03635     }
03636   
03637   if (iter->pos != _dbus_string_get_length (&iter->message->body))
03638     {
03639       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
03640       return FALSE;
03641     }
03642 
03643   return TRUE;
03644 }
03645 #endif /* DBUS_DISABLE_CHECKS */
03646 
03647 static dbus_bool_t
03648 dbus_message_iter_append_type (DBusMessageRealIter *iter,
03649                                int                  type)
03650 {
03651   const char *data;
03652 
03653   switch (iter->type)
03654     {
03655     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
03656       if (!_dbus_string_append_byte (&iter->message->body, type))
03657         return FALSE;
03658 
03659       if (!_dbus_message_append_byte_to_signature (iter->message, type))
03660         {
03661           _dbus_string_shorten (&iter->message->body, 1);
03662           return FALSE;
03663         }
03664       break;
03665       
03666     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
03667       data = _dbus_string_get_const_data_len (&iter->message->body,
03668                                               iter->array_type_pos, 1);
03669       if (type != *data)
03670         {
03671           _dbus_warn ("Appended element of wrong type for array\n");
03672           return FALSE;
03673         }
03674       break;
03675       
03676     case DBUS_MESSAGE_ITER_TYPE_DICT:
03677       if (!iter->wrote_dict_key)
03678         {
03679           _dbus_warn ("Appending dict data before key name\n");
03680           return FALSE;
03681         }
03682       
03683       if (!_dbus_string_append_byte (&iter->message->body, type))
03684         return FALSE;
03685       
03686       break;
03687       
03688     default:
03689       _dbus_assert_not_reached ("Invalid iter type");
03690       break;
03691     }
03692   
03693   return TRUE;
03694 }
03695 
03696 static void
03697 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
03698 {
03699   iter->changed_stamp = iter->message->changed_stamp;
03700   
03701   /* Set new end of iter */
03702   iter->end = _dbus_string_get_length (&iter->message->body);
03703   iter->pos = iter->end;
03704 
03705   /* Set container length */
03706   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
03707       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
03708     _dbus_marshal_set_uint32 (&iter->message->body,
03709                               iter->message->byte_order,
03710                               iter->container_length_pos,
03711                               iter->end - iter->container_start);
03712   
03713   if (iter->parent_iter)
03714     dbus_message_iter_update_after_change (iter->parent_iter);
03715 }
03716 
03717 static void
03718 dbus_message_iter_append_done (DBusMessageRealIter *iter)
03719 {
03720   iter->message->changed_stamp++;
03721   dbus_message_iter_update_after_change (iter);
03722   iter->wrote_dict_key = FALSE;
03723 }
03724 
03731 dbus_bool_t
03732 dbus_message_iter_append_nil (DBusMessageIter *iter)
03733 {
03734   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03735 
03736   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03737 
03738   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
03739     return FALSE;
03740   
03741   dbus_message_iter_append_done (real);
03742   
03743   return TRUE;
03744 }
03745 
03746 static dbus_bool_t
03747 dbus_message_iter_append_basic (DBusMessageIter *iter,
03748                                 char             type,
03749                                 void            *value)
03750 {
03751   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03752 
03753   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03754 
03755   if (!dbus_message_iter_append_type (real, type))
03756     return FALSE;
03757 
03758   if (!_dbus_marshal_basic_type (&real->message->body,
03759                                  type, value,
03760                                  real->message->byte_order))
03761     {
03762       _dbus_string_set_length (&real->message->body, real->pos);
03763       return FALSE;
03764     }
03765 
03766   dbus_message_iter_append_done (real);
03767   
03768   return TRUE;  
03769 }
03770 
03778 dbus_bool_t
03779 dbus_message_iter_append_boolean (DBusMessageIter *iter,
03780                                   dbus_bool_t     value)
03781 {
03782   unsigned char val = (value != FALSE);
03783   return dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &val);
03784 }
03785 
03793 dbus_bool_t
03794 dbus_message_iter_append_byte (DBusMessageIter *iter,
03795                                unsigned char    value)
03796 {
03797   return dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &value);
03798 }
03799 
03807 dbus_bool_t
03808 dbus_message_iter_append_int32   (DBusMessageIter *iter,
03809                                   dbus_int32_t  value)
03810 {
03811   return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &value);
03812 }
03813 
03821 dbus_bool_t
03822 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
03823                                  dbus_uint32_t    value)
03824 {
03825   return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &value);
03826 }
03827 
03828 #ifdef DBUS_HAVE_INT64
03829 
03839 dbus_bool_t
03840 dbus_message_iter_append_int64   (DBusMessageIter *iter,
03841                                   dbus_int64_t  value)
03842 {
03843   return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &value);
03844 }
03845 
03855 dbus_bool_t
03856 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
03857                                  dbus_uint64_t    value)
03858 {
03859   return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &value);
03860 }
03861 
03862 #endif /* DBUS_HAVE_INT64 */
03863 
03871 dbus_bool_t
03872 dbus_message_iter_append_double (DBusMessageIter *iter,
03873                                  double           value)
03874 {
03875   return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &value);
03876 }
03877 
03887 dbus_bool_t
03888 dbus_message_iter_append_string (DBusMessageIter *iter,
03889                                  const char      *value)
03890 {
03891   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03892 
03893   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03894   
03895   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
03896     return FALSE;
03897   
03898   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03899     {
03900       _dbus_string_set_length (&real->message->body, real->pos);
03901       return FALSE;
03902     }
03903 
03904   dbus_message_iter_append_done (real);
03905   
03906   return TRUE;
03907 }
03908 
03918 dbus_bool_t
03919 dbus_message_iter_append_object_path (DBusMessageIter *iter,
03920                                       const char      *value)
03921 {
03922   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03923 
03924   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03925   
03926   if (!dbus_message_iter_append_type (real, DBUS_TYPE_OBJECT_PATH))
03927     return FALSE;
03928   
03929   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
03930     {
03931       _dbus_string_set_length (&real->message->body, real->pos);
03932       return FALSE;
03933     }
03934 
03935   dbus_message_iter_append_done (real);
03936   
03937   return TRUE;
03938 }
03939 
03952 dbus_bool_t
03953 dbus_message_iter_append_custom (DBusMessageIter      *iter,
03954                                  const char           *name,
03955                                  const unsigned char  *data,
03956                                  int                   len)
03957 {
03958   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03959 
03960   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03961 
03962   if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
03963     return FALSE;
03964   
03965    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
03966     {
03967       _dbus_string_set_length (&real->message->body, real->pos);
03968       return FALSE;
03969     }
03970    
03971   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
03972     {
03973       _dbus_string_set_length (&real->message->body, real->pos);
03974       return FALSE;
03975     }
03976 
03977   dbus_message_iter_append_done (real);
03978   
03979   return TRUE;
03980 }
03981 
03982 
03991 dbus_bool_t
03992 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
03993                                    const char      *value)
03994 {
03995   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
03996 
03997   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
03998   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
03999   
04000   if (real->wrote_dict_key)
04001     {
04002       _dbus_warn ("Appending multiple dict key names\n");
04003       return FALSE;
04004     }
04005   
04006   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
04007     {
04008       return FALSE;
04009     }
04010 
04011   dbus_message_iter_append_done (real);
04012   real->wrote_dict_key = TRUE;
04013   
04014   return TRUE;
04015 }
04016 
04017 static dbus_bool_t
04018 array_iter_type_mark_done (DBusMessageRealIter *iter)
04019 {
04020   int len_pos;
04021   
04022   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
04023     array_iter_type_mark_done (iter->parent_iter);
04024   else
04025     return TRUE;
04026 
04027   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
04028                                sizeof (dbus_uint32_t));
04029 
04030   /* Empty length for now, backfill later */
04031   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
04032     {
04033       _dbus_string_set_length (&iter->message->body, iter->pos);
04034       return FALSE;
04035     }
04036 
04037   iter->container_start = _dbus_string_get_length (&iter->message->body);
04038   iter->container_length_pos = len_pos;
04039   iter->array_type_done = TRUE;
04040 
04041   return TRUE;
04042 }
04043 
04044 static dbus_bool_t
04045 append_array_type (DBusMessageRealIter *real,
04046                    int                  element_type,
04047                    dbus_bool_t         *array_type_done,
04048                    int                 *array_type_pos)
04049 {
04050   int existing_element_type;
04051   
04052   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
04053     return FALSE;
04054   
04055   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
04056       real->array_type_done)
04057     {
04058       existing_element_type = iter_get_array_type (real, array_type_pos);
04059       if (existing_element_type != element_type)
04060         {
04061           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
04062                       _dbus_type_to_string (element_type),
04063                       _dbus_type_to_string (existing_element_type));
04064           _dbus_string_set_length (&real->message->body, real->pos);
04065           return FALSE;
04066         }
04067       if (array_type_done != NULL)
04068           *array_type_done = TRUE;
04069     }
04070   else
04071     {
04072       if (array_type_pos != NULL)
04073         *array_type_pos = _dbus_string_get_length (&real->message->body);
04074 
04075 
04076       if (!_dbus_message_append_byte_to_signature (real->message, element_type))
04077         {
04078           _dbus_string_set_length (&real->message->body, real->pos);
04079           return FALSE;
04080         }
04081       
04082       /* Append element type */
04083       if (!_dbus_string_append_byte (&real->message->body, element_type))
04084         {
04085           _dbus_message_remove_byte_from_signature (real->message);
04086           _dbus_string_set_length (&real->message->body, real->pos);
04087           return FALSE;
04088         }
04089 
04090       if (array_type_done != NULL)
04091         *array_type_done = element_type != DBUS_TYPE_ARRAY;
04092       
04093       if (element_type != DBUS_TYPE_ARRAY &&
04094           !array_iter_type_mark_done (real))
04095         {
04096           _dbus_message_remove_byte_from_signature (real->message);
04097           return FALSE;
04098         }
04099     }
04100 
04101   return TRUE;
04102 }
04103 
04113 dbus_bool_t
04114 dbus_message_iter_append_array (DBusMessageIter      *iter,
04115                                 DBusMessageIter      *array_iter,
04116                                 int                   element_type)
04117 {
04118   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04119   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
04120   int len_pos;
04121   int array_type_pos;
04122   dbus_bool_t array_type_done;
04123 
04124   if (element_type == DBUS_TYPE_NIL)
04125     {
04126       _dbus_warn ("Can't create NIL arrays\n");
04127       return FALSE;
04128     }
04129   
04130   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04131 
04132   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
04133     return FALSE;
04134 
04135   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
04136 
04137   if (array_type_done)
04138     {
04139       /* Empty length for now, backfill later */
04140       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
04141         {
04142           _dbus_string_set_length (&real->message->body, real->pos);
04143           return FALSE;
04144         }
04145     }
04146   
04147   array_real->parent_iter = real;
04148   array_real->message = real->message;
04149   array_real->changed_stamp = real->message->changed_stamp;
04150   
04151   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
04152   array_real->pos = _dbus_string_get_length (&real->message->body);
04153   array_real->end = array_real->end;
04154   
04155   array_real->container_start = array_real->pos;
04156   array_real->container_length_pos = len_pos;
04157   array_real->wrote_dict_key = 0;
04158   array_real->array_type_done = array_type_done;
04159   array_real->array_type_pos = array_type_pos;
04160 
04161   dbus_message_iter_append_done (array_real);
04162   
04163   return TRUE;
04164 }
04165 
04174 dbus_bool_t
04175 dbus_message_iter_append_dict (DBusMessageIter      *iter,
04176                                DBusMessageIter      *dict_iter)
04177 {
04178   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04179   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
04180   int len_pos;
04181 
04182   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04183   
04184   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
04185     return FALSE;  
04186   
04187   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
04188 
04189   /* Empty length for now, backfill later */
04190   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
04191     {
04192       _dbus_string_set_length (&real->message->body, real->pos);
04193       return FALSE;
04194     }
04195   
04196   dict_real->parent_iter = real;
04197   dict_real->message = real->message;
04198   dict_real->changed_stamp = real->message->changed_stamp;
04199   
04200   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
04201   dict_real->pos = _dbus_string_get_length (&real->message->body);
04202   dict_real->end = dict_real->end;
04203   
04204   dict_real->container_start = dict_real->pos;
04205   dict_real->container_length_pos = len_pos;
04206   dict_real->wrote_dict_key = 0;
04207 
04208   dbus_message_iter_append_done (dict_real);
04209   
04210   real->wrote_dict_key = FALSE;
04211   
04212   return TRUE;
04213 }
04214 
04215 static dbus_bool_t
04216 _dbus_message_iter_append_basic_array (DBusMessageIter *iter,
04217                                        char             type,
04218                                        const void      *value,
04219                                        int              len)
04220 {
04221   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04222 
04223   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04224 
04225   if (!append_array_type (real, type, NULL, NULL))
04226     return FALSE;
04227   
04228   if (!_dbus_marshal_basic_type_array (&real->message->body,
04229                                        type, value, len,
04230                                        real->message->byte_order))
04231     {
04232       _dbus_string_set_length (&real->message->body, real->pos);
04233       return FALSE;
04234     }
04235 
04236   dbus_message_iter_append_done (real);
04237   
04238   return TRUE;
04239 }
04240 
04241 
04255 dbus_bool_t
04256 dbus_message_append_args_valist (DBusMessage *message,
04257                                  int          first_arg_type,
04258                                  va_list      var_args)
04259 {
04260   int type, old_len;
04261   DBusMessageIter iter;
04262 
04263   _dbus_return_val_if_fail (message != NULL, FALSE);
04264   
04265   old_len = _dbus_string_get_length (&message->body);
04266   
04267   type = first_arg_type;
04268 
04269   dbus_message_append_iter_init (message, &iter);
04270   
04271   while (type != DBUS_TYPE_INVALID)
04272     {
04273       switch (type)
04274         {
04275         case DBUS_TYPE_NIL:
04276           if (!dbus_message_iter_append_nil (&iter))
04277             goto errorout;
04278           break;
04279         case DBUS_TYPE_BYTE:
04280           /* Read an int from varargs, because the original unsigned
04281            * char has been promoted to int. */
04282           if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, int)))
04283             goto errorout;
04284           break;
04285         case DBUS_TYPE_BOOLEAN:
04286           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
04287             goto errorout;
04288           break;
04289         case DBUS_TYPE_INT32:
04290           /* FIXME this is probably wrong, because an int passed in probably gets
04291            * converted to plain "int" not necessarily 32-bit.
04292            */
04293           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
04294             goto errorout;
04295           break;
04296         case DBUS_TYPE_UINT32:
04297           /* FIXME this is probably wrong, because an int passed in probably gets
04298            * converted to plain "int" not necessarily 32-bit.
04299            */
04300           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
04301             goto errorout;          
04302           break;
04303 #ifdef DBUS_HAVE_INT64
04304         case DBUS_TYPE_INT64:
04305           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
04306             goto errorout;
04307           break;
04308         case DBUS_TYPE_UINT64:
04309           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
04310             goto errorout;          
04311           break;
04312 #endif /* DBUS_HAVE_INT64 */
04313         case DBUS_TYPE_DOUBLE:
04314           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
04315             goto errorout;
04316           break;
04317         case DBUS_TYPE_STRING:
04318           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
04319             goto errorout;
04320           break;
04321         case DBUS_TYPE_OBJECT_PATH:
04322           if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
04323             goto errorout;
04324           break;
04325         case DBUS_TYPE_CUSTOM:
04326           {
04327             const char *name;
04328             unsigned char *data;
04329             int len;
04330  
04331             name = va_arg (var_args, const char *);
04332             data = va_arg (var_args, unsigned char *);
04333             len = va_arg (var_args, int);
04334 
04335             if (!dbus_message_iter_append_custom (&iter, name, data, len))
04336               goto errorout;
04337             break;
04338           }
04339         case DBUS_TYPE_ARRAY:
04340           {
04341             void *data;
04342             int len, type;
04343  
04344             type = va_arg (var_args, int);
04345             data = va_arg (var_args, void *);
04346             len = va_arg (var_args, int);
04347 
04348             switch (type)
04349               {
04350               case DBUS_TYPE_BYTE:
04351               case DBUS_TYPE_BOOLEAN:
04352               case DBUS_TYPE_INT32:
04353               case DBUS_TYPE_UINT32:
04354 #ifdef DBUS_HAVE_INT64
04355               case DBUS_TYPE_INT64:
04356               case DBUS_TYPE_UINT64:
04357 #endif /* DBUS_HAVE_INT64 */
04358               case DBUS_TYPE_DOUBLE:
04359                 if (!_dbus_message_iter_append_basic_array (&iter, type, data, len))
04360                   goto errorout;
04361                 break;
04362               case DBUS_TYPE_STRING:
04363                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
04364                   goto errorout;
04365                 break;
04366               case DBUS_TYPE_OBJECT_PATH:
04367                 if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
04368                   goto errorout;
04369                 break;
04370               case DBUS_TYPE_NIL:
04371               case DBUS_TYPE_ARRAY:
04372               case DBUS_TYPE_CUSTOM:
04373               case DBUS_TYPE_DICT:
04374                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
04375                 goto errorout;
04376               default:
04377                 _dbus_warn ("Unknown field type %d\n", type);
04378                 goto errorout;
04379               }
04380           }
04381           break;
04382           
04383         case DBUS_TYPE_DICT:
04384           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
04385           goto errorout;
04386         default:
04387           _dbus_warn ("Unknown field type %d\n", type);
04388           goto errorout;
04389         }
04390 
04391       type = va_arg (var_args, int);
04392     }
04393 
04394   return TRUE;
04395 
04396  errorout:
04397   return FALSE;
04398 }
04399 
04408 dbus_bool_t
04409 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
04410                                         unsigned const char *value,
04411                                         int                  len)
04412 {
04413   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BOOLEAN,
04414                                                 value, len);
04415 }
04416 
04425 dbus_bool_t
04426 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
04427                                       const dbus_int32_t *value,
04428                                       int                 len)
04429 {
04430   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT32,
04431                                                 value, len);
04432 }
04433 
04442 dbus_bool_t
04443 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
04444                                        const dbus_uint32_t *value,
04445                                        int                  len)
04446 {
04447   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT32,
04448                                                 value, len);
04449 }
04450 
04451 #ifdef DBUS_HAVE_INT64
04452 
04463 dbus_bool_t
04464 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
04465                                       const dbus_int64_t *value,
04466                                       int                 len)
04467 {
04468   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT64,
04469                                                 value, len);
04470 }
04471 
04482 dbus_bool_t
04483 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
04484                                        const dbus_uint64_t *value,
04485                                        int                  len)
04486 {
04487   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT64,
04488                                                 value, len);
04489 }
04490 #endif /* DBUS_HAVE_INT64 */
04491 
04500 dbus_bool_t
04501 dbus_message_iter_append_double_array (DBusMessageIter *iter,
04502                                        const double    *value,
04503                                        int              len)
04504 {
04505   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_DOUBLE,
04506                                                 value, len);
04507 }
04508 
04517 dbus_bool_t
04518 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
04519                                      unsigned const char *value,
04520                                      int                  len)
04521 {
04522   return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BYTE,
04523                                                 value, len);
04524 }
04525 
04534 dbus_bool_t
04535 dbus_message_iter_append_string_array (DBusMessageIter *iter,
04536                                        const char     **value,
04537                                        int              len)
04538 {
04539   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04540 
04541   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04542 
04543   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
04544     return FALSE;
04545   
04546   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04547     {
04548       _dbus_string_set_length (&real->message->body, real->pos);
04549       return FALSE;
04550     }
04551 
04552   dbus_message_iter_append_done (real);
04553   
04554   return TRUE;
04555 }
04556 
04565 dbus_bool_t
04566 dbus_message_iter_append_object_path_array (DBusMessageIter *iter,
04567                                             const char     **value,
04568                                             int              len)
04569 {
04570   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
04571 
04572   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
04573 
04574   if (!append_array_type (real, DBUS_TYPE_OBJECT_PATH, NULL, NULL))
04575     return FALSE;
04576   
04577   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
04578     {
04579       _dbus_string_set_length (&real->message->body, real->pos);
04580       return FALSE;
04581     }
04582 
04583   dbus_message_iter_append_done (real);
04584   
04585   return TRUE;
04586 }
04587 
04595 dbus_bool_t
04596 dbus_message_set_sender (DBusMessage  *message,
04597                          const char   *sender)
04598 {
04599   _dbus_return_val_if_fail (message != NULL, FALSE);
04600   _dbus_return_val_if_fail (!message->locked, FALSE);
04601 
04602   return set_string_field (message,
04603                            DBUS_HEADER_FIELD_SENDER,
04604                            DBUS_TYPE_STRING,
04605                            sender);
04606 }
04607 
04618 void
04619 dbus_message_set_no_reply (DBusMessage *message,
04620                            dbus_bool_t  no_reply)
04621 {
04622   char *header;
04623 
04624   _dbus_return_if_fail (message != NULL);
04625   _dbus_return_if_fail (!message->locked);
04626   
04627   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04628   
04629   if (no_reply)
04630     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
04631   else
04632     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
04633 }
04634 
04642 dbus_bool_t
04643 dbus_message_get_no_reply (DBusMessage *message)
04644 {
04645   const char *header;
04646 
04647   _dbus_return_val_if_fail (message != NULL, FALSE);
04648   
04649   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04650 
04651   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
04652 }
04653 
04654 
04664 void
04665 dbus_message_set_auto_activation (DBusMessage *message,
04666                                   dbus_bool_t  auto_activation)
04667 {
04668   char *header;
04669 
04670   _dbus_return_if_fail (message != NULL);
04671   _dbus_return_if_fail (!message->locked);
04672   
04673   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
04674   
04675   if (auto_activation)
04676     *header |= DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04677   else
04678     *header &= ~DBUS_HEADER_FLAG_AUTO_ACTIVATION;
04679 }
04680 
04688 dbus_bool_t
04689 dbus_message_get_auto_activation (DBusMessage *message)
04690 {
04691   const char *header;
04692 
04693   _dbus_return_val_if_fail (message != NULL, FALSE);
04694   
04695   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
04696 
04697   return (*header & DBUS_HEADER_FLAG_AUTO_ACTIVATION) != 0;
04698 }
04699 
04707 const char*
04708 dbus_message_get_sender (DBusMessage *message)
04709 {
04710   _dbus_return_val_if_fail (message != NULL, NULL);
04711   
04712   return get_string_field (message, 
04713                            DBUS_HEADER_FIELD_SENDER,
04714                            NULL);
04715 }
04716 
04732 const char*
04733 dbus_message_get_signature (DBusMessage *message)
04734 {
04735   _dbus_return_val_if_fail (message != NULL, NULL);
04736 
04737   return get_string_field (message, 
04738                            DBUS_HEADER_FIELD_SIGNATURE,
04739                            NULL);
04740 }
04741 
04742 static dbus_bool_t
04743 _dbus_message_has_type_interface_member (DBusMessage *message,
04744                                          int          type,
04745                                          const char  *interface,
04746                                          const char  *method)
04747 {
04748   const char *n;
04749 
04750   _dbus_assert (message != NULL);
04751   _dbus_assert (interface != NULL);
04752   _dbus_assert (method != NULL);
04753 
04754   if (dbus_message_get_type (message) != type)
04755     return FALSE;
04756 
04757   /* Optimize by checking the short method name first
04758    * instead of the longer interface name
04759    */  
04760 
04761   n = dbus_message_get_member (message);
04762 
04763   if (n && strcmp (n, method) == 0)
04764     {
04765       n = dbus_message_get_interface (message);
04766       
04767       if (n && strcmp (n, interface) == 0)
04768         return TRUE;
04769     }
04770 
04771   return FALSE;
04772 }
04773 
04786 dbus_bool_t
04787 dbus_message_is_method_call (DBusMessage *message,
04788                              const char  *interface,
04789                              const char  *method)
04790 {
04791   _dbus_return_val_if_fail (message != NULL, FALSE);
04792   _dbus_return_val_if_fail (interface != NULL, FALSE);
04793   _dbus_return_val_if_fail (method != NULL, FALSE);
04794 
04795   return _dbus_message_has_type_interface_member (message,
04796                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
04797                                                   interface, method);
04798 }
04799 
04812 dbus_bool_t
04813 dbus_message_is_signal (DBusMessage *message,
04814                         const char  *interface,
04815                         const char  *signal_name)
04816 {
04817   _dbus_return_val_if_fail (message != NULL, FALSE);
04818   _dbus_return_val_if_fail (interface != NULL, FALSE);
04819   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
04820 
04821   return _dbus_message_has_type_interface_member (message,
04822                                                   DBUS_MESSAGE_TYPE_SIGNAL,
04823                                                   interface, signal_name);
04824 }
04825 
04836 dbus_bool_t
04837 dbus_message_is_error (DBusMessage *message,
04838                        const char  *error_name)
04839 {
04840   const char *n;
04841   
04842   _dbus_return_val_if_fail (message != NULL, FALSE);
04843   _dbus_return_val_if_fail (error_name != NULL, FALSE);
04844   _dbus_return_val_if_fail (is_valid_error_name (error_name), FALSE);
04845   
04846   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04847     return FALSE;
04848 
04849   n = dbus_message_get_error_name (message);
04850 
04851   if (n && strcmp (n, error_name) == 0)
04852     return TRUE;
04853   else
04854     return FALSE;
04855 }
04856 
04867 dbus_bool_t
04868 dbus_message_has_destination (DBusMessage  *message,
04869                               const char   *service)
04870 {
04871   const char *s;
04872 
04873   _dbus_return_val_if_fail (message != NULL, FALSE);
04874   _dbus_return_val_if_fail (service != NULL, FALSE);
04875   
04876   s = dbus_message_get_destination (message);
04877 
04878   if (s && strcmp (s, service) == 0)
04879     return TRUE;
04880   else
04881     return FALSE;
04882 }
04883 
04898 dbus_bool_t
04899 dbus_message_has_sender (DBusMessage  *message,
04900                          const char   *service)
04901 {
04902   const char *s;
04903 
04904   _dbus_return_val_if_fail (message != NULL, FALSE);
04905   _dbus_return_val_if_fail (service != NULL, FALSE);
04906   
04907   s = dbus_message_get_sender (message);
04908 
04909   if (s && strcmp (s, service) == 0)
04910     return TRUE;
04911   else
04912     return FALSE;
04913 }
04914 
04924 dbus_bool_t
04925 dbus_message_has_signature (DBusMessage   *message,
04926                             const char    *signature)
04927 {
04928   const char *s;
04929 
04930   _dbus_return_val_if_fail (message != NULL, FALSE);
04931   _dbus_return_val_if_fail (signature != NULL, FALSE);
04932   
04933   s = dbus_message_get_signature (message);
04934 
04935   if (s && strcmp (s, signature) == 0)
04936     return TRUE;
04937   else
04938     return FALSE;
04939 }
04940 
04958 dbus_bool_t
04959 dbus_set_error_from_message (DBusError   *error,
04960                              DBusMessage *message)
04961 {
04962   char *str;
04963 
04964   _dbus_return_val_if_fail (message != NULL, FALSE);
04965   _dbus_return_val_if_error_is_set (error, FALSE);
04966   
04967   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
04968     return FALSE;
04969 
04970   str = NULL;
04971   dbus_message_get_args (message, NULL,
04972                          DBUS_TYPE_STRING, &str,
04973                          DBUS_TYPE_INVALID);
04974 
04975   dbus_set_error (error, dbus_message_get_error_name (message),
04976                   str ? "%s" : NULL, str);
04977 
04978   dbus_free (str);
04979   
04980   return TRUE;
04981 }
04982 
05007 /* we definitely use signed ints for sizes, so don't exceed
05008  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
05009  * over 128M is pretty nuts anyhow.
05010  */
05011 
05015 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
05016 
05021 struct DBusMessageLoader
05022 {
05023   int refcount;        
05025   DBusString data;     
05027   DBusList *messages;  
05029   long max_message_size; 
05031   unsigned int buffer_outstanding : 1; 
05033   unsigned int corrupted : 1; 
05034 };
05035 
05046 #define INITIAL_LOADER_DATA_LEN 32
05047 
05054 DBusMessageLoader*
05055 _dbus_message_loader_new (void)
05056 {
05057   DBusMessageLoader *loader;
05058 
05059   loader = dbus_new0 (DBusMessageLoader, 1);
05060   if (loader == NULL)
05061     return NULL;
05062   
05063   loader->refcount = 1;
05064 
05065   /* Try to cap message size at something that won't *totally* hose
05066    * the system if we have a couple of them.
05067    */
05068   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
05069   
05070   if (!_dbus_string_init (&loader->data))
05071     {
05072       dbus_free (loader);
05073       return NULL;
05074     }
05075 
05076   /* preallocate the buffer for speed, ignore failure */
05077   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
05078   _dbus_string_set_length (&loader->data, 0);
05079   
05080   return loader;
05081 }
05082 
05089 DBusMessageLoader *
05090 _dbus_message_loader_ref (DBusMessageLoader *loader)
05091 {
05092   loader->refcount += 1;
05093 
05094   return loader;
05095 }
05096 
05103 void
05104 _dbus_message_loader_unref (DBusMessageLoader *loader)
05105 {
05106   loader->refcount -= 1;
05107   if (loader->refcount == 0)
05108     {
05109       _dbus_list_foreach (&loader->messages,
05110                           (DBusForeachFunction) dbus_message_unref,
05111                           NULL);
05112       _dbus_list_clear (&loader->messages);
05113       _dbus_string_free (&loader->data);
05114       dbus_free (loader);
05115     }
05116 }
05117 
05136 void
05137 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
05138                                  DBusString        **buffer)
05139 {
05140   _dbus_assert (!loader->buffer_outstanding);
05141 
05142   *buffer = &loader->data;
05143   
05144   loader->buffer_outstanding = TRUE;
05145 }
05146 
05151 #define DBUS_MINIMUM_HEADER_SIZE 16
05152 
05153 static dbus_bool_t
05154 decode_string_field (const DBusString   *data,
05155                      int                 field,
05156                      HeaderField        *header_field,
05157                      DBusString         *field_data,
05158                      int                 pos,
05159                      int                 type)
05160 {
05161   int string_data_pos;
05162 
05163   _dbus_assert (header_field != NULL);
05164   _dbus_assert (field_data != NULL);
05165   
05166   if (header_field->name_offset >= 0)
05167     {
05168       _dbus_verbose ("%s field provided twice\n",
05169                      _dbus_header_field_to_string (field));
05170       return FALSE;
05171     }
05172 
05173   if (type != DBUS_TYPE_STRING)
05174     {
05175       _dbus_verbose ("%s field has wrong type %s\n",
05176                      _dbus_header_field_to_string (field),
05177                      _dbus_type_to_string (type));
05178       return FALSE;
05179     }
05180 
05181   /* skip padding after typecode, skip string length;
05182    * we assume that the string arg has already been validated
05183    * for sanity and UTF-8
05184    */
05185   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
05186   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
05187   
05188   _dbus_string_init_const (field_data,
05189                            _dbus_string_get_const_data (data) + string_data_pos);
05190 
05191   header_field->name_offset  = pos - 2;
05192   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05193   
05194 #if 0
05195   _dbus_verbose ("Found field %s at offset %d\n",
05196                  _dbus_header_field_to_string (field),
05197                  header_field->value_offset);
05198 #endif
05199 
05200   return TRUE;
05201 }
05202 
05203 /* FIXME because the service/interface/member/error names are already
05204  * validated to be in the particular ASCII subset, UTF-8 validating
05205  * them could be skipped as a probably-interesting optimization.
05206  * The UTF-8 validation shows up in callgrind-type profiles but
05207  * not so much in sample/time-based profiles.
05208  */
05209 static dbus_bool_t
05210 decode_header_data (const DBusString   *data,
05211                     int                 header_len,
05212                     int                 byte_order,
05213                     int                 message_type,
05214                     HeaderField         fields[DBUS_HEADER_FIELD_LAST + 1],
05215                     int                *message_padding)
05216 {
05217   DBusString field_data;
05218   int pos, new_pos;
05219   int i;
05220   int field;
05221   int type;
05222   dbus_bool_t signature_required;
05223   
05224   if (header_len < 16)
05225     {
05226       _dbus_verbose ("Header length %d is too short\n", header_len);
05227       return FALSE;
05228     }
05229   
05230   i = 0;
05231   while (i <= DBUS_HEADER_FIELD_LAST)
05232     {
05233       fields[i].name_offset  = -1;
05234       fields[i].value_offset = -1;
05235       ++i;
05236     }
05237   
05238   pos = 16;
05239   while (pos < header_len)
05240     {
05241       field = _dbus_string_get_byte (data, pos);
05242       if (field == DBUS_HEADER_FIELD_INVALID)
05243         break; /* Must be padding */
05244       pos++;
05245 
05246       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
05247         {
05248           _dbus_verbose ("Failed to validate type of named header field pos = %d\n",
05249                          pos);
05250           return FALSE;
05251         }
05252       
05253       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
05254         {
05255           _dbus_verbose ("Failed to validate argument to named header field pos = %d\n",
05256                          pos);
05257           return FALSE;
05258         }
05259 
05260       if (new_pos > header_len)
05261         {
05262           _dbus_verbose ("Named header field tries to extend beyond header length\n");
05263           return FALSE;
05264         }
05265       
05266       switch (field)
05267         {
05268         case DBUS_HEADER_FIELD_DESTINATION:
05269           if (!decode_string_field (data, field, &fields[field],
05270                                     &field_data, pos, type))
05271             return FALSE;
05272 
05273           if (!_dbus_string_validate_service (&field_data, 0,
05274                                               _dbus_string_get_length (&field_data)))
05275             {
05276               _dbus_verbose ("service field has invalid content \"%s\"\n",
05277                              _dbus_string_get_const_data (&field_data));
05278               return FALSE;
05279             }
05280           break;
05281 
05282         case DBUS_HEADER_FIELD_INTERFACE:
05283           if (!decode_string_field (data, field, &fields[field],
05284                                     &field_data, pos, type))
05285             return FALSE;
05286 
05287           if (!_dbus_string_validate_interface (&field_data, 0,
05288                                                 _dbus_string_get_length (&field_data)))
05289             {
05290               _dbus_verbose ("interface field has invalid content \"%s\"\n",
05291                              _dbus_string_get_const_data (&field_data));
05292               return FALSE;
05293             }
05294       
05295           if (_dbus_string_equal_c_str (&field_data,
05296                                         DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
05297             {
05298               _dbus_verbose ("Message is on the local interface\n");
05299               return FALSE;
05300             }
05301           break;
05302 
05303         case DBUS_HEADER_FIELD_MEMBER:
05304           if (!decode_string_field (data, field, &fields[field],
05305                                     &field_data, pos, type))
05306             return FALSE;
05307           
05308           if (!_dbus_string_validate_member (&field_data, 0,
05309                                              _dbus_string_get_length (&field_data)))
05310             {
05311               _dbus_verbose ("member field has invalid content \"%s\"\n",
05312                              _dbus_string_get_const_data (&field_data));
05313               return FALSE;
05314             }
05315           break;
05316 
05317         case DBUS_HEADER_FIELD_ERROR_NAME:
05318           if (!decode_string_field (data, field, &fields[field],
05319                                     &field_data, pos, type))
05320             return FALSE;
05321           
05322           if (!_dbus_string_validate_error_name (&field_data, 0,
05323                                                  _dbus_string_get_length (&field_data)))
05324             {
05325               _dbus_verbose ("error-name field has invalid content \"%s\"\n",
05326                              _dbus_string_get_const_data (&field_data));
05327               return FALSE;
05328             }
05329           break;
05330           
05331         case DBUS_HEADER_FIELD_SENDER:
05332           if (!decode_string_field (data, field, &fields[field],
05333                                     &field_data, pos, type))
05334             return FALSE;
05335           
05336           if (!_dbus_string_validate_service (&field_data, 0,
05337                                               _dbus_string_get_length (&field_data)))
05338             {
05339               _dbus_verbose ("sender-service field has invalid content \"%s\"\n",
05340                              _dbus_string_get_const_data (&field_data));
05341               return FALSE;
05342             }
05343           break;
05344 
05345         case DBUS_HEADER_FIELD_PATH:
05346 
05347           /* Path was already validated as part of standard
05348            * type validation, since there's an OBJECT_PATH
05349            * type.
05350            */
05351           
05352           if (fields[field].name_offset >= 0)
05353             {
05354               _dbus_verbose ("path field provided twice\n");
05355               return FALSE;
05356             }
05357           if (type != DBUS_TYPE_OBJECT_PATH)
05358             {
05359               _dbus_verbose ("path field has wrong type\n");
05360               return FALSE;
05361             }
05362 
05363           fields[field].name_offset  = pos - 2;
05364           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05365 
05366           /* No forging signals from the local path */
05367           {
05368             const char *s;
05369             s = _dbus_string_get_const_data_len (data,
05370                                                  fields[field].value_offset,
05371                                                  _dbus_string_get_length (data) -
05372                                                  fields[field].value_offset);
05373             if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
05374               {
05375                 _dbus_verbose ("Message is on the local path\n");
05376                 return FALSE;
05377               }
05378           }
05379           
05380           _dbus_verbose ("Found path at offset %d\n",
05381                          fields[field].value_offset);
05382           break;
05383           
05384         case DBUS_HEADER_FIELD_REPLY_SERIAL:
05385           if (fields[field].name_offset >= 0)
05386             {
05387               _dbus_verbose ("reply field provided twice\n");
05388               return FALSE;
05389             }
05390 
05391           if (type != DBUS_TYPE_UINT32)
05392             {
05393               _dbus_verbose ("reply field has wrong type\n");
05394               return FALSE;
05395             }
05396           
05397           fields[field].name_offset  = pos - 2;
05398           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
05399 
05400           _dbus_verbose ("Found reply serial %u at offset %d\n",
05401                          _dbus_demarshal_uint32 (data,
05402                                                  byte_order,
05403                                                  fields[field].value_offset,
05404                                                  NULL),
05405                          fields[field].value_offset);
05406           break;
05407 
05408         case DBUS_HEADER_FIELD_SIGNATURE:
05409           if (!decode_string_field (data, field, &fields[field],
05410                                     &field_data, pos, type))
05411             return FALSE;
05412 
05413           if (!_dbus_string_validate_signature (&field_data, 0,
05414                                                 _dbus_string_get_length (&field_data)))
05415             {
05416               _dbus_verbose ("signature field has invalid content \"%s\"\n",
05417                              _dbus_string_get_const_data (&field_data));
05418               return FALSE;
05419             }
05420           break;
05421           
05422         default:
05423           _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
05424                          field, pos);
05425         }
05426       
05427       pos = new_pos;
05428     }
05429 
05430   if (pos < header_len)
05431     {
05432       /* Alignment padding, verify that it's nul */
05433       if ((header_len - pos) >= 8)
05434         {
05435           _dbus_verbose ("too much header alignment padding\n");
05436           return FALSE;
05437         }
05438 
05439       if (!_dbus_string_validate_nul (data,
05440                                       pos, (header_len - pos)))
05441         {
05442           _dbus_verbose ("header alignment padding is not nul\n");
05443           return FALSE;
05444         }
05445     }
05446 
05447   /* Depending on message type, enforce presence of certain fields. */
05448   signature_required = TRUE;
05449   
05450   switch (message_type)
05451     {
05452     case DBUS_MESSAGE_TYPE_SIGNAL:
05453     case DBUS_MESSAGE_TYPE_METHOD_CALL:
05454       if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
05455         {
05456           _dbus_verbose ("No path field provided\n");
05457           return FALSE;
05458         }
05459       /* FIXME make this optional, only for method calls */
05460       if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
05461         {
05462           _dbus_verbose ("No interface field provided\n");
05463           return FALSE;
05464         }
05465       if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
05466         {
05467           _dbus_verbose ("No member field provided\n");
05468           return FALSE;
05469         }
05470       break;
05471     case DBUS_MESSAGE_TYPE_ERROR:
05472       if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
05473         {
05474           _dbus_verbose ("No error-name field provided\n");
05475           return FALSE;
05476         }
05477       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05478         {
05479           _dbus_verbose ("No reply serial field provided in error\n");
05480           return FALSE;
05481         }
05482       break;
05483     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
05484       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
05485         {
05486           _dbus_verbose ("No reply serial field provided in method return\n");
05487           return FALSE;
05488         }
05489       break;
05490     default:
05491       /* An unknown type, spec requires us to ignore it */
05492       signature_required = FALSE;
05493       break;
05494     }
05495 
05496   /* FIXME allow omitting signature field for a message with no arguments? */
05497   if (signature_required)
05498     {
05499       if (fields[DBUS_HEADER_FIELD_SIGNATURE].value_offset < 0)
05500         {
05501           _dbus_verbose ("No signature field provided\n");
05502           return FALSE;
05503         }
05504     }
05505   
05506   if (message_padding)
05507     *message_padding = header_len - pos;  
05508   
05509   return TRUE;
05510 }
05511 
05522 void
05523 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
05524                                     DBusString         *buffer,
05525                                     int                 bytes_read)
05526 {
05527   _dbus_assert (loader->buffer_outstanding);
05528   _dbus_assert (buffer == &loader->data);
05529 
05530   loader->buffer_outstanding = FALSE;
05531 }
05532 
05533 static dbus_bool_t
05534 load_one_message (DBusMessageLoader *loader,
05535                   int                byte_order,
05536                   int                message_type,
05537                   int                header_len,
05538                   int                body_len)
05539 {
05540   DBusMessage *message;
05541   HeaderField fields[DBUS_HEADER_FIELD_LAST + 1];
05542   int i;
05543   int next_arg;
05544   dbus_bool_t oom;
05545   int header_padding;
05546   
05547   message = NULL;
05548   oom = FALSE;
05549   
05550 #if 0
05551   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
05552 #endif    
05553 
05554   if (!decode_header_data (&loader->data,
05555                            header_len, byte_order,
05556                            message_type,
05557                            fields, &header_padding))
05558     {
05559       _dbus_verbose ("Header was invalid\n");
05560       loader->corrupted = TRUE;
05561       goto failed;
05562     }
05563           
05564   next_arg = header_len;
05565   while (next_arg < (header_len + body_len))
05566     {
05567       int type;
05568       int prev = next_arg;
05569 
05570       if (!_dbus_marshal_validate_type (&loader->data, next_arg,
05571                                         &type, &next_arg))
05572         {
05573           _dbus_verbose ("invalid typecode at offset %d\n", prev);
05574           loader->corrupted = TRUE;
05575           goto failed;
05576         }
05577       
05578       if (!_dbus_marshal_validate_arg (&loader->data,
05579                                        byte_order,
05580                                        0,
05581                                        type, -1,
05582                                        next_arg,
05583                                        &next_arg))
05584         {
05585           _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
05586           loader->corrupted = TRUE;
05587           goto failed;
05588         }
05589 
05590       _dbus_assert (next_arg > prev);
05591     }
05592           
05593   if (next_arg > (header_len + body_len))
05594     {
05595       _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
05596                      next_arg, header_len, body_len,
05597                      header_len + body_len);
05598       loader->corrupted = TRUE;
05599       goto failed;
05600     }
05601 
05602   message = dbus_message_new_empty_header ();
05603   if (message == NULL)
05604     {
05605       _dbus_verbose ("Failed to allocate empty message\n");
05606       oom = TRUE;
05607       goto failed;
05608     }
05609 
05610   message->byte_order = byte_order;
05611   message->header_padding = header_padding;
05612           
05613   /* Copy in the offsets we found */
05614   i = 0;
05615   while (i <= DBUS_HEADER_FIELD_LAST)
05616     {
05617       message->header_fields[i] = fields[i];
05618       ++i;
05619     }
05620           
05621   if (!_dbus_list_append (&loader->messages, message))
05622     {
05623       _dbus_verbose ("Failed to append new message to loader queue\n");
05624       oom = TRUE;
05625       goto failed;
05626     }
05627 
05628   _dbus_assert (_dbus_string_get_length (&message->header) == 0);
05629   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
05630 
05631   _dbus_assert (_dbus_string_get_length (&loader->data) >=
05632                 (header_len + body_len));
05633           
05634   if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
05635     {
05636       _dbus_verbose ("Failed to move header into new message\n");
05637       oom = TRUE;
05638       goto failed;
05639     }
05640           
05641   if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
05642     {
05643       _dbus_verbose ("Failed to move body into new message\n");
05644       
05645       oom = TRUE;
05646       goto failed;
05647     }
05648 
05649   _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
05650   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
05651 
05652   /* Fill in caches (we checked the types of these fields
05653    * earlier)
05654    */
05655   message->reply_serial = get_uint_field (message,
05656                                           DBUS_HEADER_FIELD_REPLY_SERIAL);
05657   
05658   message->client_serial = _dbus_demarshal_uint32 (&message->header,
05659                                                    message->byte_order,
05660                                                    CLIENT_SERIAL_OFFSET,
05661                                                    NULL);
05662   if (message->client_serial == 0 ||
05663       (message->header_fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset >= 0 && message->reply_serial == 0))
05664     {
05665       _dbus_verbose ("client_serial = %d reply_serial = %d, one of these no good\n",
05666                      message->client_serial,
05667                      message->reply_serial);
05668       
05669       loader->corrupted = TRUE;
05670       goto failed;
05671     }
05672   
05673   _dbus_verbose ("Loaded message %p\n", message);
05674 
05675   _dbus_assert (!oom);
05676   _dbus_assert (!loader->corrupted);
05677 
05678   return TRUE;
05679 
05680  failed:
05681   
05682   /* Clean up */
05683   
05684   if (message != NULL)
05685     {
05686       /* Put the data back so we can try again later if it was an OOM issue */
05687       if (_dbus_string_get_length (&message->body) > 0)
05688         {
05689           dbus_bool_t result;
05690           
05691           result = _dbus_string_copy_len (&message->body, 0, body_len,
05692                                           &loader->data, 0);
05693           
05694           _dbus_assert (result); /* because DBusString never reallocs smaller */
05695         }
05696       
05697       if (_dbus_string_get_length (&message->header) > 0)
05698         {
05699           dbus_bool_t result;
05700           
05701           result = _dbus_string_copy_len (&message->header, 0, header_len,
05702                                           &loader->data, 0);
05703           
05704           _dbus_assert (result); /* because DBusString never reallocs smaller */
05705         }
05706 
05707       /* does nothing if the message isn't in the list */
05708       _dbus_list_remove_last (&loader->messages, message);
05709 
05710       dbus_message_unref (message);
05711     }
05712 
05713   
05714   return !oom;
05715 }
05716 
05730 dbus_bool_t
05731 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
05732 {
05733   while (!loader->corrupted && _dbus_string_get_length (&loader->data) >= 16)
05734     {
05735       const char *header_data;
05736       int byte_order, message_type, header_len, body_len;
05737       dbus_uint32_t header_len_unsigned, body_len_unsigned;
05738       
05739       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
05740 
05741       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
05742 
05743       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
05744         {
05745           _dbus_verbose ("Message has protocol version %d ours is %d\n",
05746                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
05747           loader->corrupted = TRUE;
05748           return TRUE;
05749         }
05750       
05751       byte_order = header_data[BYTE_ORDER_OFFSET];
05752 
05753       if (byte_order != DBUS_LITTLE_ENDIAN &&
05754           byte_order != DBUS_BIG_ENDIAN)
05755         {
05756           _dbus_verbose ("Message with bad byte order '%c' received\n",
05757                          byte_order);
05758           loader->corrupted = TRUE;
05759           return TRUE;
05760         }
05761 
05762       /* Unknown types are ignored, but INVALID is
05763        * disallowed
05764        */
05765       message_type = header_data[TYPE_OFFSET];
05766       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
05767         {
05768           _dbus_verbose ("Message with bad type '%d' received\n",
05769                          message_type);
05770           loader->corrupted = TRUE;
05771           return TRUE;
05772         }      
05773       
05774       header_len_unsigned = _dbus_unpack_uint32 (byte_order, 
05775                                                  (const unsigned char *) header_data + 4);
05776       body_len_unsigned = _dbus_unpack_uint32 (byte_order, 
05777                                                (const unsigned char *) header_data + 8);
05778 
05779       if (header_len_unsigned < 16)
05780         {
05781           _dbus_verbose ("Message had broken too-small header length %u\n",
05782                          header_len_unsigned);
05783           loader->corrupted = TRUE;
05784           return TRUE;
05785         }
05786 
05787       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
05788           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
05789         {
05790           _dbus_verbose ("Header or body length too large (%u %u)\n",
05791                          header_len_unsigned,
05792                          body_len_unsigned);
05793           loader->corrupted = TRUE;
05794           return TRUE;
05795         }
05796 
05797       /* Now that we know the values are in signed range, get
05798        * rid of stupid unsigned, just causes bugs
05799        */
05800       header_len = header_len_unsigned;
05801       body_len = body_len_unsigned;
05802 
05803       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
05804         {
05805           
05806           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
05807                          header_len);
05808           loader->corrupted = TRUE;
05809           return TRUE;
05810         }
05811       
05812       if (header_len + body_len > loader->max_message_size)
05813         {
05814           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
05815                          header_len, body_len, loader->max_message_size);
05816           loader->corrupted = TRUE;
05817           return TRUE;
05818         }
05819 
05820       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
05821         {
05822           if (!load_one_message (loader, byte_order, message_type,
05823                                  header_len, body_len))
05824             return FALSE;
05825         }
05826       else
05827         return TRUE;
05828     }
05829 
05830   return TRUE;
05831 }
05832 
05840 DBusMessage*
05841 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
05842 {
05843   if (loader->messages)
05844     return loader->messages->data;
05845   else
05846     return NULL;
05847 }
05848 
05857 DBusMessage*
05858 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
05859 {
05860   return _dbus_list_pop_first (&loader->messages);
05861 }
05862 
05871 DBusList*
05872 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
05873 {
05874   return _dbus_list_pop_first_link (&loader->messages);
05875 }
05876 
05883 void
05884 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
05885                                            DBusList           *link)
05886 {
05887   _dbus_list_prepend_link (&loader->messages, link);
05888 }
05889 
05899 dbus_bool_t
05900 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
05901 {
05902   return loader->corrupted;
05903 }
05904 
05911 void
05912 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
05913                                            long                size)
05914 {
05915   if (size > MAX_SANE_MESSAGE_SIZE)
05916     {
05917       _dbus_verbose ("clamping requested max message size %ld to %d\n",
05918                      size, MAX_SANE_MESSAGE_SIZE);
05919       size = MAX_SANE_MESSAGE_SIZE;
05920     }
05921   loader->max_message_size = size;
05922 }
05923 
05930 long
05931 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
05932 {
05933   return loader->max_message_size;
05934 }
05935 
05936 static DBusDataSlotAllocator slot_allocator;
05937 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
05938 
05953 dbus_bool_t
05954 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
05955 {
05956   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05957                                           _DBUS_LOCK_NAME (message_slots),
05958                                           slot_p);
05959 }
05960 
05972 void
05973 dbus_message_free_data_slot (dbus_int32_t *slot_p)
05974 {
05975   _dbus_return_if_fail (*slot_p >= 0);
05976   
05977   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05978 }
05979 
05993 dbus_bool_t
05994 dbus_message_set_data (DBusMessage     *message,
05995                        dbus_int32_t     slot,
05996                        void            *data,
05997                        DBusFreeFunction free_data_func)
05998 {
05999   DBusFreeFunction old_free_func;
06000   void *old_data;
06001   dbus_bool_t retval;
06002 
06003   _dbus_return_val_if_fail (message != NULL, FALSE);
06004   _dbus_return_val_if_fail (slot >= 0, FALSE);
06005 
06006   retval = _dbus_data_slot_list_set (&slot_allocator,
06007                                      &message->slot_list,
06008                                      slot, data, free_data_func,
06009                                      &old_free_func, &old_data);
06010 
06011   if (retval)
06012     {
06013       /* Do the actual free outside the message lock */
06014       if (old_free_func)
06015         (* old_free_func) (old_data);
06016     }
06017 
06018   return retval;
06019 }
06020 
06029 void*
06030 dbus_message_get_data (DBusMessage   *message,
06031                        dbus_int32_t   slot)
06032 {
06033   void *res;
06034 
06035   _dbus_return_val_if_fail (message != NULL, NULL);
06036   
06037   res = _dbus_data_slot_list_get (&slot_allocator,
06038                                   &message->slot_list,
06039                                   slot);
06040 
06041   return res;
06042 }
06043 
06057 int
06058 dbus_message_type_from_string (const char *type_str)
06059 {
06060   if (strcmp (type_str, "method_call") == 0)
06061     return DBUS_MESSAGE_TYPE_METHOD_CALL;
06062   if (strcmp (type_str, "method_return") == 0)
06063     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
06064   else if (strcmp (type_str, "signal") == 0)
06065     return DBUS_MESSAGE_TYPE_SIGNAL;
06066   else if (strcmp (type_str, "error") == 0)
06067     return DBUS_MESSAGE_TYPE_ERROR;
06068   else
06069     return DBUS_MESSAGE_TYPE_INVALID;
06070 }
06071 
06085 const char *
06086 dbus_message_type_to_string (int type)
06087 {
06088   switch (type)
06089     {
06090     case DBUS_MESSAGE_TYPE_METHOD_CALL:
06091       return "method_call";
06092     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
06093       return "method_return";
06094     case DBUS_MESSAGE_TYPE_SIGNAL:
06095       return "signal";
06096     case DBUS_MESSAGE_TYPE_ERROR:
06097       return "error";
06098     default:
06099       return "invalid";
06100     }
06101 }
06102 
06104 #ifdef DBUS_BUILD_TESTS
06105 #include "dbus-test.h"
06106 #include <stdio.h>
06107 #include <stdlib.h>
06108 
06109 static void
06110 message_iter_test (DBusMessage *message)
06111 {
06112   DBusMessageIter iter, dict, dict2, array, array2;
06113   char *str;
06114   unsigned char *data;
06115   dbus_int32_t *our_int_array;
06116   int len;
06117   
06118   dbus_message_iter_init (message, &iter);
06119 
06120   /* String tests */
06121   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
06122     _dbus_assert_not_reached ("Argument type isn't string");
06123 
06124   str = dbus_message_iter_get_string (&iter);
06125   if (strcmp (str, "Test string") != 0)
06126     _dbus_assert_not_reached ("Strings differ");
06127   dbus_free (str);
06128 
06129   if (!dbus_message_iter_next (&iter))
06130     _dbus_assert_not_reached ("Reached end of arguments");
06131 
06132   /* Signed integer tests */
06133   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
06134     _dbus_assert_not_reached ("Argument type isn't int32");
06135 
06136   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
06137     _dbus_assert_not_reached ("Signed integers differ");
06138 
06139   if (!dbus_message_iter_next (&iter))
06140     _dbus_assert_not_reached ("Reached end of fields");
06141   
06142   /* Unsigned integer tests */
06143   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
06144     _dbus_assert_not_reached ("Argument type isn't int32");
06145 
06146   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
06147     _dbus_assert_not_reached ("Unsigned integers differ");
06148 
06149   if (!dbus_message_iter_next (&iter))
06150     _dbus_assert_not_reached ("Reached end of arguments");
06151 
06152   /* Double tests */
06153   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
06154     _dbus_assert_not_reached ("Argument type isn't double");
06155 
06156   if (dbus_message_iter_get_double (&iter) != 3.14159)
06157     _dbus_assert_not_reached ("Doubles differ");
06158 
06159   if (!dbus_message_iter_next (&iter))
06160     _dbus_assert_not_reached ("Reached end of arguments");
06161 
06162   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
06163     _dbus_assert_not_reached ("Argument type not an array");
06164 
06165   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
06166     _dbus_assert_not_reached ("Array type not double");
06167 
06168   
06169   dbus_message_iter_init_array_iterator (&iter, &array, NULL);
06170 
06171   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
06172     _dbus_assert_not_reached ("Argument type isn't double");
06173 
06174   if (dbus_message_iter_get_double (&array) != 1.5)
06175     _dbus_assert_not_reached ("Unsigned integers differ");
06176 
06177   if (!dbus_message_iter_next (&array))
06178     _dbus_assert_not_reached ("Reached end of arguments");
06179 
06180   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
06181     _dbus_assert_not_reached ("Argument type isn't double");
06182 
06183   if (dbus_message_iter_get_double (&array) != 2.5)
06184     _dbus_assert_not_reached ("Unsigned integers differ");
06185 
06186   if (dbus_message_iter_next (&array))
06187     _dbus_assert_not_reached ("Didn't reach end of arguments");
06188   
06189   if (!dbus_message_iter_next (&iter))
06190     _dbus_assert_not_reached ("Reached end of arguments");
06191   
06192 
06193   /* dict */
06194 
06195   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
06196     _dbus_assert_not_reached ("not dict type");
06197      
06198   dbus_message_iter_init_dict_iterator (&iter, &dict);
06199 
06200   str = dbus_message_iter_get_dict_key (&dict);
06201   if (str == NULL || strcmp (str, "test") != 0)
06202     _dbus_assert_not_reached ("wrong dict key");
06203   dbus_free (str);
06204 
06205   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
06206     _dbus_assert_not_reached ("wrong dict entry type");
06207 
06208   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
06209     _dbus_assert_not_reached ("wrong dict entry value");
06210 
06211   /* dict (in dict) */
06212 
06213   if (!dbus_message_iter_next (&dict))
06214     _dbus_assert_not_reached ("reached end of dict");
06215   
06216   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_DICT)
06217     _dbus_assert_not_reached ("not dict type");
06218     
06219   dbus_message_iter_init_dict_iterator (&dict, &dict2);
06220   
06221   str = dbus_message_iter_get_dict_key (&dict2);
06222   if (str == NULL || strcmp (str, "dictkey") != 0)
06223     _dbus_assert_not_reached ("wrong dict key");
06224   dbus_free (str);
06225   
06226   if (dbus_message_iter_get_arg_type (&dict2) != DBUS_TYPE_STRING)
06227     _dbus_assert_not_reached ("wrong dict entry type");
06228   
06229   str = dbus_message_iter_get_string (&dict2);
06230   if (str == NULL || strcmp (str, "dictvalue") != 0)
06231     _dbus_assert_not_reached ("wrong dict entry value");
06232   dbus_free (str);
06233   
06234   if (dbus_message_iter_next (&dict2))
06235     _dbus_assert_not_reached ("didn't reach end of dict");
06236 
06237   if (!dbus_message_iter_next (&dict))
06238     _dbus_assert_not_reached ("reached end of dict");
06239   
06240   /* array of array of int32 (in dict) */
06241 
06242   str = dbus_message_iter_get_dict_key (&dict);
06243   if (str == NULL || strcmp (str, "array") != 0)
06244     _dbus_assert_not_reached ("wrong dict key");
06245   dbus_free (str);
06246   
06247   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
06248     _dbus_assert_not_reached ("Argument type not an array");
06249 
06250   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
06251     _dbus_assert_not_reached ("Array type not array");
06252 
06253   dbus_message_iter_init_array_iterator (&dict, &array, NULL);
06254 
06255   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
06256     _dbus_assert_not_reached ("Argument type isn't array");
06257   
06258   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
06259     _dbus_assert_not_reached ("Array type not int32");
06260   
06261   dbus_message_iter_init_array_iterator (&array, &array2, NULL);
06262 
06263   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
06264     _dbus_assert_not_reached ("Argument type isn't int32");
06265 
06266   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
06267     _dbus_assert_not_reached ("Signed integers differ");
06268 
06269   if (!dbus_message_iter_next (&array2))
06270     _dbus_assert_not_reached ("Reached end of arguments");
06271 
06272   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
06273     _dbus_assert_not_reached ("Signed integers differ");
06274 
06275   if (dbus_message_iter_next (&array2))
06276     _dbus_assert_not_reached ("Didn't reached end of arguments");
06277 
06278   if (!dbus_message_iter_next (&array))
06279     _dbus_assert_not_reached ("Reached end of arguments");
06280 
06281   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
06282     _dbus_assert_not_reached ("Array type not int32");
06283 
06284   if (!dbus_message_iter_get_int32_array (&array,
06285                                           &our_int_array,
06286                                           &len))
06287     _dbus_assert_not_reached ("couldn't get int32 array");
06288 
06289   _dbus_assert (len == 3);
06290   _dbus_assert (our_int_array[0] == 0x34567812 &&
06291                 our_int_array[1] == 0x45678123 &&
06292                 our_int_array[2] == 0x56781234);
06293   dbus_free (our_int_array);
06294   
06295   if (dbus_message_iter_next (&array))
06296     _dbus_assert_not_reached ("Didn't reach end of array");
06297 
06298   if (dbus_message_iter_next (&dict))
06299     _dbus_assert_not_reached ("Didn't reach end of dict");
06300   
06301   if (!dbus_message_iter_next (&iter))
06302     _dbus_assert_not_reached ("Reached end of arguments");
06303   
06304   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
06305     {
06306       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
06307       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
06308     }
06309   
06310   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06311     _dbus_assert_not_reached ("wrong value after dict");
06312 
06313 
06314   if (!dbus_message_iter_next (&iter))
06315     _dbus_assert_not_reached ("Reached end of arguments");
06316   
06317   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
06318     _dbus_assert_not_reached ("not a nil type");
06319   
06320   if (!dbus_message_iter_next (&iter))
06321     _dbus_assert_not_reached ("Reached end of arguments");
06322   
06323   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_CUSTOM)
06324     _dbus_assert_not_reached ("wrong type after dict");
06325 
06326   if (!dbus_message_iter_get_custom (&iter, &str, &data, &len))
06327     _dbus_assert_not_reached ("failed to get custom type");
06328 
06329   _dbus_assert (strcmp (str, "MyTypeName")==0);
06330   _dbus_assert (len == 5);
06331   _dbus_assert (strcmp (data, "data")==0);
06332   dbus_free (str);
06333   dbus_free (data);
06334   
06335   if (!dbus_message_iter_next (&iter))
06336     _dbus_assert_not_reached ("Reached end of arguments");
06337 
06338   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06339     _dbus_assert_not_reached ("wrong value after custom");
06340 
06341   if (!dbus_message_iter_next (&iter))
06342     _dbus_assert_not_reached ("Reached end of arguments");
06343 
06344   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
06345     _dbus_assert_not_reached ("no array");
06346 
06347   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_INT32)
06348     _dbus_assert_not_reached ("Array type not int32");
06349 
06350   if (dbus_message_iter_init_array_iterator (&iter, &array, NULL))
06351     _dbus_assert_not_reached ("non empty array");
06352   
06353   if (!dbus_message_iter_next (&iter))
06354     _dbus_assert_not_reached ("Reached end of arguments");
06355 
06356   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06357     _dbus_assert_not_reached ("wrong value after empty array");
06358 
06359   if (!dbus_message_iter_next (&iter))
06360     _dbus_assert_not_reached ("Reached end of arguments");
06361 
06362   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
06363     _dbus_assert_not_reached ("non dict");
06364 
06365   if (dbus_message_iter_init_dict_iterator (&iter, &dict))
06366     _dbus_assert_not_reached ("non empty dict");
06367 
06368   if (!dbus_message_iter_next (&iter))
06369     _dbus_assert_not_reached ("Reached end of arguments");
06370 
06371   if (dbus_message_iter_get_byte (&iter) != 0xF0)
06372     _dbus_assert_not_reached ("wrong value after empty dict");
06373 
06374   if (dbus_message_iter_next (&iter))
06375     _dbus_assert_not_reached ("Didn't reach end of arguments");
06376 }
06377 
06378 
06379 static dbus_bool_t
06380 check_message_handling_type (DBusMessageIter *iter,
06381                              int type)
06382 {
06383   DBusMessageIter child_iter;
06384   
06385   switch (type)
06386     {
06387     case DBUS_TYPE_NIL:
06388       break;
06389     case DBUS_TYPE_BYTE:
06390       dbus_message_iter_get_byte (iter);
06391       break;
06392     case DBUS_TYPE_BOOLEAN:
06393       dbus_message_iter_get_boolean (iter);
06394       break;
06395     case DBUS_TYPE_INT32:
06396       dbus_message_iter_get_int32 (iter);
06397       break;
06398     case DBUS_TYPE_UINT32:
06399       dbus_message_iter_get_uint32 (iter);
06400       break;
06401     case DBUS_TYPE_INT64:
06402 #ifdef DBUS_HAVE_INT64
06403       dbus_message_iter_get_int64 (iter);
06404 #endif
06405       break;
06406     case DBUS_TYPE_UINT64:
06407 #ifdef DBUS_HAVE_INT64
06408       dbus_message_iter_get_uint64 (iter);
06409 #endif
06410       break;
06411     case DBUS_TYPE_DOUBLE:
06412       dbus_message_iter_get_double (iter);
06413       break;
06414     case DBUS_TYPE_STRING:
06415       {
06416         char *str;
06417         str = dbus_message_iter_get_string (iter);
06418         if (str == NULL)
06419           {
06420             _dbus_warn ("NULL string in message\n");
06421             return FALSE;
06422           }
06423         dbus_free (str);
06424       }
06425       break;
06426     case DBUS_TYPE_CUSTOM:
06427       {
06428         char *name;
06429         unsigned char *data;
06430         int len;
06431         
06432         if (!dbus_message_iter_get_custom (iter, &name, &data, &len))
06433           {
06434             _dbus_warn ("error reading name from custom type\n");
06435             return FALSE;
06436           }
06437         dbus_free (data);
06438         dbus_free (name);
06439       }
06440       break;
06441     case DBUS_TYPE_ARRAY:
06442       {
06443         int array_type;
06444 
06445         dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type);
06446 
06447         while (dbus_message_iter_has_next (&child_iter))
06448           {
06449             if (!check_message_handling_type (&child_iter, array_type))
06450               {
06451                 _dbus_warn ("error in array element\n");
06452                 return FALSE;
06453               }
06454             
06455             if (!dbus_message_iter_next (&child_iter))
06456               break;
06457           }
06458       }
06459       break;
06460     case DBUS_TYPE_DICT:
06461       {
06462         int entry_type;
06463         char *key;
06464         
06465         dbus_message_iter_init_dict_iterator (iter, &child_iter);
06466 
06467         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
06468           {
06469             key = dbus_message_iter_get_dict_key (&child_iter);
06470             if (key == NULL)
06471               {
06472                 _dbus_warn ("error reading dict key\n");
06473                 return FALSE;
06474               }
06475             dbus_free (key);
06476             
06477             if (!check_message_handling_type (&child_iter, entry_type))
06478               {
06479                 _dbus_warn ("error in dict value\n");
06480                 return FALSE;
06481               }
06482             
06483             if (!dbus_message_iter_next (&child_iter))
06484               break;
06485           }
06486       }
06487       break;
06488       
06489     default:
06490       _dbus_warn ("unknown type %d\n", type);
06491       return FALSE;
06492       break;
06493     }
06494   return TRUE;
06495 }
06496   
06497   
06498 static dbus_bool_t
06499 check_message_handling (DBusMessage *message)
06500 {
06501   DBusMessageIter iter;
06502   int type;
06503   dbus_bool_t retval;
06504   dbus_uint32_t client_serial;
06505   
06506   retval = FALSE;
06507   
06508   client_serial = dbus_message_get_serial (message);
06509 
06510   /* can't use set_serial due to the assertions at the start of it */
06511   _dbus_marshal_set_uint32 (&message->header,
06512                             message->byte_order,
06513                             CLIENT_SERIAL_OFFSET,
06514                             client_serial);
06515   
06516   if (client_serial != dbus_message_get_serial (message))
06517     {
06518       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
06519       goto failed;
06520     }
06521   
06522   /* If we implement message_set_arg (message, n, value)
06523    * then we would want to test it here
06524    */
06525 
06526   dbus_message_iter_init (message, &iter);
06527   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
06528     {
06529       if (!check_message_handling_type (&iter, type))
06530         goto failed;
06531 
06532       if (!dbus_message_iter_next (&iter))
06533         break;
06534     }
06535   
06536   retval = TRUE;
06537   
06538  failed:
06539   return retval;
06540 }
06541 
06542 static dbus_bool_t
06543 check_have_valid_message (DBusMessageLoader *loader)
06544 {
06545   DBusMessage *message;
06546   dbus_bool_t retval;
06547 
06548   message = NULL;
06549   retval = FALSE;
06550 
06551   if (!_dbus_message_loader_queue_messages (loader))
06552     _dbus_assert_not_reached ("no memory to queue messages");
06553   
06554   if (_dbus_message_loader_get_is_corrupted (loader))
06555     {
06556       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
06557       goto failed;
06558     }
06559   
06560   message = _dbus_message_loader_pop_message (loader);
06561   if (message == NULL)
06562     {
06563       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
06564       goto failed;
06565     }
06566   
06567   if (_dbus_string_get_length (&loader->data) > 0)
06568     {
06569       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
06570       goto failed;
06571     }
06572 
06573   /* Verify that we're able to properly deal with the message.
06574    * For example, this would detect improper handling of messages
06575    * in nonstandard byte order.
06576    */
06577   if (!check_message_handling (message))
06578     goto failed;  
06579   
06580   retval = TRUE;
06581 
06582  failed:
06583   if (message)
06584     dbus_message_unref (message);
06585 
06586   return retval;
06587 }
06588 
06589 static dbus_bool_t
06590 check_invalid_message (DBusMessageLoader *loader)
06591 {
06592   dbus_bool_t retval;
06593 
06594   retval = FALSE;
06595 
06596   if (!_dbus_message_loader_queue_messages (loader))
06597     _dbus_assert_not_reached ("no memory to queue messages");
06598   
06599   if (!_dbus_message_loader_get_is_corrupted (loader))
06600     {
06601       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
06602       goto failed;
06603     }
06604 
06605   retval = TRUE;
06606 
06607  failed:
06608   return retval;
06609 }
06610 
06611 static dbus_bool_t
06612 check_incomplete_message (DBusMessageLoader *loader)
06613 {
06614   DBusMessage *message;
06615   dbus_bool_t retval;
06616 
06617   message = NULL;
06618   retval = FALSE;
06619 
06620   if (!_dbus_message_loader_queue_messages (loader))
06621     _dbus_assert_not_reached ("no memory to queue messages");
06622   
06623   if (_dbus_message_loader_get_is_corrupted (loader))
06624     {
06625       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
06626       goto failed;
06627     }
06628   
06629   message = _dbus_message_loader_pop_message (loader);
06630   if (message != NULL)
06631     {
06632       _dbus_warn ("loaded message that was expected to be incomplete\n");
06633       goto failed;
06634     }
06635 
06636   retval = TRUE;
06637 
06638  failed:
06639   if (message)
06640     dbus_message_unref (message);
06641   return retval;
06642 }
06643 
06644 static dbus_bool_t
06645 check_loader_results (DBusMessageLoader      *loader,
06646                       DBusMessageValidity     validity)
06647 {
06648   if (!_dbus_message_loader_queue_messages (loader))
06649     _dbus_assert_not_reached ("no memory to queue messages");
06650   
06651   switch (validity)
06652     {
06653     case _DBUS_MESSAGE_VALID:
06654       return check_have_valid_message (loader);
06655     case _DBUS_MESSAGE_INVALID:
06656       return check_invalid_message (loader);
06657     case _DBUS_MESSAGE_INCOMPLETE:
06658       return check_incomplete_message (loader);
06659     case _DBUS_MESSAGE_UNKNOWN:
06660       return TRUE;
06661     }
06662 
06663   _dbus_assert_not_reached ("bad DBusMessageValidity");
06664   return FALSE;
06665 }
06666 
06667 
06676 dbus_bool_t
06677 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
06678                                             dbus_bool_t          is_raw,
06679                                             DBusString          *data)
06680 {
06681   dbus_bool_t retval;
06682 
06683   retval = FALSE;  
06684 
06685   if (is_raw)
06686     {
06687       DBusError error;
06688 
06689       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
06690       dbus_error_init (&error);
06691       if (!_dbus_file_get_contents (data, filename, &error))
06692         {
06693           _dbus_warn ("Could not load message file %s: %s\n",
06694                       _dbus_string_get_const_data (filename),
06695                       error.message);
06696           dbus_error_free (&error);
06697           goto failed;
06698         }
06699     }
06700   else
06701     {
06702       if (!_dbus_message_data_load (data, filename))
06703         {
06704           _dbus_warn ("Could not load message file %s\n",
06705                       _dbus_string_get_const_data (filename));
06706           goto failed;
06707         }
06708     }
06709 
06710   retval = TRUE;
06711   
06712  failed:
06713 
06714   return retval;
06715 }
06716 
06726 dbus_bool_t
06727 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
06728                                            dbus_bool_t          is_raw,
06729                                            DBusMessageValidity  expected_validity)
06730 {
06731   DBusString data;
06732   dbus_bool_t retval;
06733 
06734   retval = FALSE;
06735   
06736   if (!_dbus_string_init (&data))
06737     _dbus_assert_not_reached ("could not allocate string\n");
06738 
06739   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
06740                                                    &data))
06741     goto failed;
06742 
06743   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
06744 
06745  failed:
06746 
06747   if (!retval)
06748     {
06749       if (_dbus_string_get_length (&data) > 0)
06750         _dbus_verbose_bytes_of_string (&data, 0,
06751                                        _dbus_string_get_length (&data));
06752       
06753       _dbus_warn ("Failed message loader test on %s\n",
06754                   _dbus_string_get_const_data (filename));
06755     }
06756   
06757   _dbus_string_free (&data);
06758 
06759   return retval;
06760 }
06761 
06770 dbus_bool_t
06771 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
06772                                            DBusMessageValidity  expected_validity)
06773 {
06774   DBusMessageLoader *loader;
06775   dbus_bool_t retval;
06776   int len;
06777   int i;
06778 
06779   loader = NULL;
06780   retval = FALSE;
06781 
06782   /* Write the data one byte at a time */
06783   
06784   loader = _dbus_message_loader_new ();
06785 
06786   /* check some trivial loader functions */
06787   _dbus_message_loader_ref (loader);
06788   _dbus_message_loader_unref (loader);
06789   _dbus_message_loader_get_max_message_size (loader);
06790   
06791   len = _dbus_string_get_length (data);
06792   for (i = 0; i < len; i++)
06793     {
06794       DBusString *buffer;
06795 
06796       _dbus_message_loader_get_buffer (loader, &buffer);
06797       _dbus_string_append_byte (buffer,
06798                                 _dbus_string_get_byte (data, i));
06799       _dbus_message_loader_return_buffer (loader, buffer, 1);
06800     }
06801   
06802   if (!check_loader_results (loader, expected_validity))
06803     goto failed;
06804 
06805   _dbus_message_loader_unref (loader);
06806   loader = NULL;
06807 
06808   /* Write the data all at once */
06809   
06810   loader = _dbus_message_loader_new ();
06811 
06812   {
06813     DBusString *buffer;
06814     
06815     _dbus_message_loader_get_buffer (loader, &buffer);
06816     _dbus_string_copy (data, 0, buffer,
06817                        _dbus_string_get_length (buffer));
06818     _dbus_message_loader_return_buffer (loader, buffer, 1);
06819   }
06820   
06821   if (!check_loader_results (loader, expected_validity))
06822     goto failed;
06823 
06824   _dbus_message_loader_unref (loader);
06825   loader = NULL;  
06826 
06827   /* Write the data 2 bytes at a time */
06828   
06829   loader = _dbus_message_loader_new ();
06830 
06831   len = _dbus_string_get_length (data);
06832   for (i = 0; i < len; i += 2)
06833     {
06834       DBusString *buffer;
06835 
06836       _dbus_message_loader_get_buffer (loader, &buffer);
06837       _dbus_string_append_byte (buffer,
06838                                 _dbus_string_get_byte (data, i));
06839       if ((i+1) < len)
06840         _dbus_string_append_byte (buffer,
06841                                   _dbus_string_get_byte (data, i+1));
06842       _dbus_message_loader_return_buffer (loader, buffer, 1);
06843     }
06844   
06845   if (!check_loader_results (loader, expected_validity))
06846     goto failed;
06847 
06848   _dbus_message_loader_unref (loader);
06849   loader = NULL;
06850   
06851   retval = TRUE;
06852   
06853  failed:
06854   
06855   if (loader)
06856     _dbus_message_loader_unref (loader);
06857   
06858   return retval;
06859 }
06860 
06861 static dbus_bool_t
06862 process_test_subdir (const DBusString          *test_base_dir,
06863                      const char                *subdir,
06864                      DBusMessageValidity        validity,
06865                      DBusForeachMessageFileFunc function,
06866                      void                      *user_data)
06867 {
06868   DBusString test_directory;
06869   DBusString filename;
06870   DBusDirIter *dir;
06871   dbus_bool_t retval;
06872   DBusError error;
06873 
06874   retval = FALSE;
06875   dir = NULL;
06876   
06877   if (!_dbus_string_init (&test_directory))
06878     _dbus_assert_not_reached ("didn't allocate test_directory\n");
06879 
06880   _dbus_string_init_const (&filename, subdir);
06881   
06882   if (!_dbus_string_copy (test_base_dir, 0,
06883                           &test_directory, 0))
06884     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
06885   
06886   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
06887     _dbus_assert_not_reached ("couldn't allocate full path");
06888 
06889   _dbus_string_free (&filename);
06890   if (!_dbus_string_init (&filename))
06891     _dbus_assert_not_reached ("didn't allocate filename string\n");
06892 
06893   dbus_error_init (&error);
06894   dir = _dbus_directory_open (&test_directory, &error);
06895   if (dir == NULL)
06896     {
06897       _dbus_warn ("Could not open %s: %s\n",
06898                   _dbus_string_get_const_data (&test_directory),
06899                   error.message);
06900       dbus_error_free (&error);
06901       goto failed;
06902     }
06903 
06904   printf ("Testing %s:\n", subdir);
06905   
06906  next:
06907   while (_dbus_directory_get_next_file (dir, &filename, &error))
06908     {
06909       DBusString full_path;
06910       dbus_bool_t is_raw;
06911       
06912       if (!_dbus_string_init (&full_path))
06913         _dbus_assert_not_reached ("couldn't init string");
06914 
06915       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
06916         _dbus_assert_not_reached ("couldn't copy dir to full_path");
06917 
06918       if (!_dbus_concat_dir_and_file (&full_path, &filename))
06919         _dbus_assert_not_reached ("couldn't concat file to dir");
06920 
06921       if (_dbus_string_ends_with_c_str (&filename, ".message"))
06922         is_raw = FALSE;
06923       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
06924         is_raw = TRUE;
06925       else
06926         {
06927           _dbus_verbose ("Skipping non-.message file %s\n",
06928                          _dbus_string_get_const_data (&filename));
06929           _dbus_string_free (&full_path);
06930           goto next;
06931         }
06932 
06933       printf ("    %s\n",
06934               _dbus_string_get_const_data (&filename));
06935       
06936       _dbus_verbose (" expecting %s for %s\n",
06937                      validity == _DBUS_MESSAGE_VALID ? "valid" :
06938                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
06939                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
06940                      _dbus_string_get_const_data (&filename));
06941       
06942       if (! (*function) (&full_path, is_raw, validity, user_data))
06943         {
06944           _dbus_string_free (&full_path);
06945           goto failed;
06946         }
06947       else
06948         _dbus_string_free (&full_path);
06949     }
06950 
06951   if (dbus_error_is_set (&error))
06952     {
06953       _dbus_warn ("Could not get next file in %s: %s\n",
06954                   _dbus_string_get_const_data (&test_directory),
06955                   error.message);
06956       dbus_error_free (&error);
06957       goto failed;
06958     }
06959     
06960   retval = TRUE;
06961   
06962  failed:
06963 
06964   if (dir)
06965     _dbus_directory_close (dir);
06966   _dbus_string_free (&test_directory);
06967   _dbus_string_free (&filename);
06968 
06969   return retval;
06970 }
06971                      
06981 dbus_bool_t
06982 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
06983                                                DBusForeachMessageFileFunc func,
06984                                                void                      *user_data)
06985 {
06986   DBusString test_directory;
06987   dbus_bool_t retval;
06988 
06989   retval = FALSE;
06990   
06991   _dbus_string_init_const (&test_directory, test_data_dir);
06992 
06993   if (!process_test_subdir (&test_directory, "valid-messages",
06994                             _DBUS_MESSAGE_VALID, func, user_data))
06995     goto failed;
06996 
06997   if (!process_test_subdir (&test_directory, "invalid-messages",
06998                             _DBUS_MESSAGE_INVALID, func, user_data))
06999     goto failed;
07000   
07001   if (!process_test_subdir (&test_directory, "incomplete-messages",
07002                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
07003     goto failed;
07004 
07005   retval = TRUE;
07006   
07007  failed:
07008 
07009   _dbus_string_free (&test_directory);
07010   
07011   return retval;
07012 }
07013 
07014 static void
07015 verify_test_message (DBusMessage *message)
07016 {
07017   DBusMessageIter iter, dict;
07018   DBusError error;
07019   dbus_int32_t our_int;
07020   char *our_str;
07021   double our_double;
07022   dbus_bool_t our_bool;
07023   unsigned char our_byte_1, our_byte_2;
07024   dbus_uint32_t our_uint32;
07025   dbus_int32_t *our_uint32_array;
07026   int our_uint32_array_len;
07027   dbus_int32_t *our_int32_array;
07028   int our_int32_array_len;
07029   char **our_string_array;
07030   int our_string_array_len;
07031 #ifdef DBUS_HAVE_INT64
07032   dbus_int64_t our_int64;
07033   dbus_uint64_t our_uint64;
07034   dbus_int64_t *our_uint64_array;
07035   int our_uint64_array_len;
07036   dbus_int64_t *our_int64_array;
07037   int our_int64_array_len;
07038 #endif
07039   double *our_double_array;
07040   int our_double_array_len;
07041   unsigned char *our_byte_array;
07042   int our_byte_array_len;
07043   unsigned char *our_boolean_array;
07044   int our_boolean_array_len;
07045   
07046   dbus_message_iter_init (message, &iter);
07047 
07048   dbus_error_init (&error);
07049   if (!dbus_message_iter_get_args (&iter, &error,
07050                                    DBUS_TYPE_INT32, &our_int,
07051 #ifdef DBUS_HAVE_INT64
07052                                    DBUS_TYPE_INT64, &our_int64,
07053                                    DBUS_TYPE_UINT64, &our_uint64,
07054 #endif
07055                                    DBUS_TYPE_STRING, &our_str,
07056                                    DBUS_TYPE_DOUBLE, &our_double,
07057                                    DBUS_TYPE_BOOLEAN, &our_bool,
07058                                    DBUS_TYPE_BYTE, &our_byte_1,
07059                                    DBUS_TYPE_BYTE, &our_byte_2,
07060                                    DBUS_TYPE_NIL,
07061                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
07062                                    &our_uint32_array, &our_uint32_array_len,
07063                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
07064                                    &our_int32_array, &our_int32_array_len,
07065 #ifdef DBUS_HAVE_INT64
07066                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
07067                                    &our_uint64_array, &our_uint64_array_len,
07068                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
07069                                    &our_int64_array, &our_int64_array_len,
07070 #endif
07071                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
07072                                    &our_string_array, &our_string_array_len,
07073                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
07074                                    &our_double_array, &our_double_array_len,
07075                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
07076                                    &our_byte_array, &our_byte_array_len,
07077                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
07078                                    &our_boolean_array, &our_boolean_array_len,
07079                                    0))
07080     {
07081       _dbus_warn ("error: %s - %s\n", error.name,
07082                   (error.message != NULL) ? error.message : "no message");
07083       _dbus_assert_not_reached ("Could not get arguments");
07084     }
07085 
07086   if (our_int != -0x12345678)
07087     _dbus_assert_not_reached ("integers differ!");
07088 
07089 #ifdef DBUS_HAVE_INT64
07090   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
07091     _dbus_assert_not_reached ("64-bit integers differ!");
07092   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
07093     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
07094 #endif
07095   
07096   if (our_double != 3.14159)
07097     _dbus_assert_not_reached ("doubles differ!");
07098 
07099   if (strcmp (our_str, "Test string") != 0)
07100     _dbus_assert_not_reached ("strings differ!");
07101   dbus_free (our_str);
07102 
07103   if (!our_bool)
07104     _dbus_assert_not_reached ("booleans differ");
07105 
07106   if (our_byte_1 != 42)
07107     _dbus_assert_not_reached ("bytes differ!");
07108 
07109   if (our_byte_2 != 24)
07110     _dbus_assert_not_reached ("bytes differ!");
07111 
07112   if (our_uint32_array_len != 4 ||
07113       our_uint32_array[0] != 0x12345678 ||
07114       our_uint32_array[1] != 0x23456781 ||
07115       our_uint32_array[2] != 0x34567812 ||
07116       our_uint32_array[3] != 0x45678123)
07117     _dbus_assert_not_reached ("uint array differs");
07118   dbus_free (our_uint32_array);
07119 
07120   if (our_int32_array_len != 4 ||
07121       our_int32_array[0] != 0x12345678 ||
07122       our_int32_array[1] != -0x23456781 ||
07123       our_int32_array[2] != 0x34567812 ||
07124       our_int32_array[3] != -0x45678123)
07125     _dbus_assert_not_reached ("int array differs");
07126   dbus_free (our_int32_array);
07127 
07128 #ifdef DBUS_HAVE_INT64
07129   if (our_uint64_array_len != 4 ||
07130       our_uint64_array[0] != 0x12345678 ||
07131       our_uint64_array[1] != 0x23456781 ||
07132       our_uint64_array[2] != 0x34567812 ||
07133       our_uint64_array[3] != 0x45678123)
07134     _dbus_assert_not_reached ("uint64 array differs");
07135   dbus_free (our_uint64_array);
07136   
07137   if (our_int64_array_len != 4 ||
07138       our_int64_array[0] != 0x12345678 ||
07139       our_int64_array[1] != -0x23456781 ||
07140       our_int64_array[2] != 0x34567812 ||
07141       our_int64_array[3] != -0x45678123)
07142     _dbus_assert_not_reached ("int64 array differs");
07143   dbus_free (our_int64_array);
07144 #endif /* DBUS_HAVE_INT64 */
07145   
07146   if (our_string_array_len != 4)
07147     _dbus_assert_not_reached ("string array has wrong length");
07148 
07149   if (strcmp (our_string_array[0], "Foo") != 0 ||
07150       strcmp (our_string_array[1], "bar") != 0 ||
07151       strcmp (our_string_array[2], "") != 0 ||
07152       strcmp (our_string_array[3], "woo woo woo woo") != 0)
07153     _dbus_assert_not_reached ("string array differs");
07154 
07155   dbus_free_string_array (our_string_array);
07156 
07157   if (our_double_array_len != 3)
07158     _dbus_assert_not_reached ("double array had wrong length");
07159 
07160   /* On all IEEE machines (i.e. everything sane) exact equality
07161    * should be preserved over the wire
07162    */
07163   if (our_double_array[0] != 0.1234 ||
07164       our_double_array[1] != 9876.54321 ||
07165       our_double_array[2] != -300.0)
07166     _dbus_assert_not_reached ("double array had wrong values");
07167 
07168   dbus_free (our_double_array);
07169 
07170   if (our_byte_array_len != 4)
07171     _dbus_assert_not_reached ("byte array had wrong length");
07172 
07173   if (our_byte_array[0] != 'a' ||
07174       our_byte_array[1] != 'b' ||
07175       our_byte_array[2] != 'c' ||
07176       our_byte_array[3] != 234)
07177     _dbus_assert_not_reached ("byte array had wrong values");
07178 
07179   dbus_free (our_byte_array);
07180 
07181   if (our_boolean_array_len != 5)
07182     _dbus_assert_not_reached ("bool array had wrong length");
07183 
07184   if (our_boolean_array[0] != TRUE ||
07185       our_boolean_array[1] != FALSE ||
07186       our_boolean_array[2] != TRUE ||
07187       our_boolean_array[3] != TRUE ||
07188       our_boolean_array[4] != FALSE)
07189     _dbus_assert_not_reached ("bool array had wrong values");
07190 
07191   dbus_free (our_boolean_array);
07192 
07193   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
07194     _dbus_assert_not_reached ("not dict type");
07195      
07196   dbus_message_iter_init_dict_iterator (&iter, &dict);
07197 
07198   our_str = dbus_message_iter_get_dict_key (&dict);
07199   if (our_str == NULL || strcmp (our_str, "test") != 0)
07200     _dbus_assert_not_reached ("wrong dict key");
07201   dbus_free (our_str);
07202 
07203   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
07204     {
07205       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
07206       _dbus_assert_not_reached ("wrong dict entry type");
07207     }
07208 
07209   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
07210     {
07211       _dbus_verbose ("dict entry val: %x\n", our_uint32);
07212       _dbus_assert_not_reached ("wrong dict entry value");
07213     }
07214 
07215   if (dbus_message_iter_next (&dict))
07216     _dbus_assert_not_reached ("Didn't reach end of dict");
07217   
07218   if (!dbus_message_iter_next (&iter))
07219     _dbus_assert_not_reached ("Reached end of arguments");
07220   
07221   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
07222     _dbus_assert_not_reached ("wrong type after dict");
07223   
07224   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
07225     _dbus_assert_not_reached ("wrong value after dict");
07226 
07227   if (dbus_message_iter_next (&iter))
07228     _dbus_assert_not_reached ("Didn't reach end of arguments");
07229 }
07230 
07237 dbus_bool_t
07238 _dbus_message_test (const char *test_data_dir)
07239 {
07240   DBusMessage *message;
07241   DBusMessageLoader *loader;
07242   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
07243   int i;
07244   const char *data;
07245   DBusMessage *copy;
07246   const char *name1;
07247   const char *name2;
07248   const dbus_uint32_t our_uint32_array[] =
07249     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
07250   const dbus_uint32_t our_int32_array[] =
07251     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
07252 #ifdef DBUS_HAVE_INT64
07253   const dbus_uint64_t our_uint64_array[] =
07254     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
07255   const dbus_uint64_t our_int64_array[] =
07256     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
07257 #endif
07258   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
07259   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
07260   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
07261   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
07262   char sig[64];
07263   const char *s;
07264   char *t;
07265   DBusError error;
07266   
07267   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
07268 
07269   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07270                                           "/org/freedesktop/TestPath",
07271                                           "Foo.TestInterface",
07272                                           "TestMethod");
07273   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
07274   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
07275                                              "TestMethod"));
07276   _dbus_assert (strcmp (dbus_message_get_path (message),
07277                         "/org/freedesktop/TestPath") == 0);
07278   _dbus_message_set_serial (message, 1234);
07279   /* string length including nul byte not a multiple of 4 */
07280   if (!dbus_message_set_sender (message, "org.foo.bar1"))
07281     _dbus_assert_not_reached ("out of memory");
07282   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
07283   dbus_message_set_reply_serial (message, 5678);
07284   if (!dbus_message_set_sender (message, NULL))
07285     _dbus_assert_not_reached ("out of memory");
07286   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
07287   _dbus_assert (dbus_message_get_serial (message) == 1234);
07288   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
07289   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
07290 
07291   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
07292   dbus_message_set_no_reply (message, TRUE);
07293   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
07294   dbus_message_set_no_reply (message, FALSE);
07295   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
07296 
07297   /* Set/get some header fields */
07298   
07299   if (!dbus_message_set_path (message, "/foo"))
07300     _dbus_assert_not_reached ("out of memory");
07301   _dbus_assert (strcmp (dbus_message_get_path (message),
07302                         "/foo") == 0);
07303 
07304   if (!dbus_message_set_interface (message, "org.Foo"))
07305     _dbus_assert_not_reached ("out of memory");
07306   _dbus_assert (strcmp (dbus_message_get_interface (message),
07307                         "org.Foo") == 0);
07308   
07309   if (!dbus_message_set_member (message, "Bar"))
07310     _dbus_assert_not_reached ("out of memory");
07311   _dbus_assert (strcmp (dbus_message_get_member (message),
07312                         "Bar") == 0);
07313 
07314   /* Set/get them with longer values */
07315   if (!dbus_message_set_path (message, "/foo/bar"))
07316     _dbus_assert_not_reached ("out of memory");
07317   _dbus_assert (strcmp (dbus_message_get_path (message),
07318                         "/foo/bar") == 0);
07319 
07320   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
07321     _dbus_assert_not_reached ("out of memory");
07322   _dbus_assert (strcmp (dbus_message_get_interface (message),
07323                         "org.Foo.Bar") == 0);
07324   
07325   if (!dbus_message_set_member (message, "BarFoo"))
07326     _dbus_assert_not_reached ("out of memory");
07327   _dbus_assert (strcmp (dbus_message_get_member (message),
07328                         "BarFoo") == 0);
07329 
07330   /* Realloc shorter again */
07331   
07332   if (!dbus_message_set_path (message, "/foo"))
07333     _dbus_assert_not_reached ("out of memory");
07334   _dbus_assert (strcmp (dbus_message_get_path (message),
07335                         "/foo") == 0);
07336 
07337   if (!dbus_message_set_interface (message, "org.Foo"))
07338     _dbus_assert_not_reached ("out of memory");
07339   _dbus_assert (strcmp (dbus_message_get_interface (message),
07340                         "org.Foo") == 0);
07341   
07342   if (!dbus_message_set_member (message, "Bar"))
07343     _dbus_assert_not_reached ("out of memory");
07344   _dbus_assert (strcmp (dbus_message_get_member (message),
07345                         "Bar") == 0);
07346   
07347   dbus_message_unref (message);
07348   
07349   /* Test the vararg functions */
07350   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07351                                           "/org/freedesktop/TestPath",
07352                                           "Foo.TestInterface",
07353                                           "TestMethod");
07354   _dbus_message_set_serial (message, 1);
07355   dbus_message_append_args (message,
07356                             DBUS_TYPE_INT32, -0x12345678,
07357 #ifdef DBUS_HAVE_INT64
07358                             DBUS_TYPE_INT64, DBUS_INT64_CONSTANT (-0x123456789abcd),
07359                             DBUS_TYPE_UINT64, DBUS_UINT64_CONSTANT (0x123456789abcd),
07360 #endif
07361                             DBUS_TYPE_STRING, "Test string",
07362                             DBUS_TYPE_DOUBLE, 3.14159,
07363                             DBUS_TYPE_BOOLEAN, TRUE,
07364                             DBUS_TYPE_BYTE, (unsigned char) 42,
07365                             DBUS_TYPE_BYTE, 24,
07366                             DBUS_TYPE_NIL,
07367                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
07368                             _DBUS_N_ELEMENTS (our_uint32_array),
07369                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
07370                             _DBUS_N_ELEMENTS (our_int32_array),
07371 #ifdef DBUS_HAVE_INT64
07372                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
07373                             _DBUS_N_ELEMENTS (our_uint64_array),
07374                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
07375                             _DBUS_N_ELEMENTS (our_int64_array),
07376 #endif
07377                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
07378                             _DBUS_N_ELEMENTS (our_string_array),
07379                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
07380                             _DBUS_N_ELEMENTS (our_double_array),
07381                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
07382                             _DBUS_N_ELEMENTS (our_byte_array),
07383                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
07384                             _DBUS_N_ELEMENTS (our_boolean_array),
07385                             0);
07386   
07387   dbus_message_append_iter_init (message, &iter);
07388   dbus_message_iter_append_dict (&iter, &child_iter);
07389   dbus_message_iter_append_dict_key (&child_iter, "test");
07390   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07391   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
07392 
07393   i = 0;
07394   sig[i++] = DBUS_TYPE_INT32;
07395 #ifdef DBUS_HAVE_INT64
07396   sig[i++] = DBUS_TYPE_INT64;
07397   sig[i++] = DBUS_TYPE_UINT64;
07398 #endif
07399   sig[i++] = DBUS_TYPE_STRING;
07400   sig[i++] = DBUS_TYPE_DOUBLE;
07401   sig[i++] = DBUS_TYPE_BOOLEAN;
07402   sig[i++] = DBUS_TYPE_BYTE;
07403   sig[i++] = DBUS_TYPE_BYTE;
07404   sig[i++] = DBUS_TYPE_NIL;
07405   sig[i++] = DBUS_TYPE_ARRAY;
07406   sig[i++] = DBUS_TYPE_UINT32;
07407   sig[i++] = DBUS_TYPE_ARRAY;
07408   sig[i++] = DBUS_TYPE_INT32;
07409 #ifdef DBUS_HAVE_INT64
07410   sig[i++] = DBUS_TYPE_ARRAY;
07411   sig[i++] = DBUS_TYPE_UINT64;
07412   sig[i++] = DBUS_TYPE_ARRAY;
07413   sig[i++] = DBUS_TYPE_INT64;
07414 #endif
07415   sig[i++] = DBUS_TYPE_ARRAY;
07416   sig[i++] = DBUS_TYPE_STRING;
07417   sig[i++] = DBUS_TYPE_ARRAY;
07418   sig[i++] = DBUS_TYPE_DOUBLE;
07419   sig[i++] = DBUS_TYPE_ARRAY;
07420   sig[i++] = DBUS_TYPE_BYTE;
07421   sig[i++] = DBUS_TYPE_ARRAY;
07422   sig[i++] = DBUS_TYPE_BOOLEAN;
07423   sig[i++] = DBUS_TYPE_DICT;
07424   sig[i++] = DBUS_TYPE_UINT32;
07425   sig[i++] = DBUS_TYPE_INVALID;
07426 
07427   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
07428   
07429   _dbus_verbose_bytes_of_string (&message->header, 0,
07430                                  _dbus_string_get_length (&message->header));
07431   _dbus_verbose_bytes_of_string (&message->body, 0,
07432                                  _dbus_string_get_length (&message->body));
07433   
07434   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
07435                  sig, dbus_message_get_signature (message));
07436   
07437   s = dbus_message_get_signature (message);
07438   
07439   _dbus_assert (dbus_message_has_signature (message, sig));
07440   _dbus_assert (strcmp (s, sig) == 0);
07441   
07442   verify_test_message (message);
07443 
07444   copy = dbus_message_copy (message);
07445   
07446   _dbus_assert (message->client_serial == copy->client_serial);
07447   _dbus_assert (message->reply_serial == copy->reply_serial);
07448   _dbus_assert (message->header_padding == copy->header_padding);
07449   
07450   _dbus_assert (_dbus_string_get_length (&message->header) ==
07451                 _dbus_string_get_length (&copy->header));
07452 
07453   _dbus_assert (_dbus_string_get_length (&message->body) ==
07454                 _dbus_string_get_length (&copy->body));
07455   
07456   verify_test_message (copy);
07457 
07458   name1 = dbus_message_get_interface (message);
07459   name2 = dbus_message_get_interface (copy);
07460 
07461   _dbus_assert (strcmp (name1, name2) == 0);
07462 
07463   name1 = dbus_message_get_member (message);
07464   name2 = dbus_message_get_member (copy);
07465 
07466   _dbus_assert (strcmp (name1, name2) == 0);
07467   
07468   dbus_message_unref (message);  
07469   dbus_message_unref (copy);
07470 
07471   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
07472                                           "/org/freedesktop/TestPath",
07473                                           "Foo.TestInterface",
07474                                           "TestMethod");
07475 
07476   _dbus_message_set_serial (message, 1);
07477   dbus_message_set_reply_serial (message, 0x12345678);
07478 
07479   dbus_message_append_iter_init (message, &iter);
07480   dbus_message_iter_append_string (&iter, "Test string");
07481   dbus_message_iter_append_int32 (&iter, -0x12345678);
07482   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
07483   dbus_message_iter_append_double (&iter, 3.14159);
07484 
07485   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
07486   dbus_message_iter_append_double (&child_iter, 1.5);
07487   dbus_message_iter_append_double (&child_iter, 2.5);
07488 
07489   /* dict */
07490   dbus_message_iter_append_dict (&iter, &child_iter);
07491   dbus_message_iter_append_dict_key (&child_iter, "test");
07492   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
07493 
07494   /* dict (in dict) */
07495   dbus_message_iter_append_dict_key (&child_iter, "testdict");
07496   dbus_message_iter_append_dict (&child_iter, &child_iter2);
07497 
07498   dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
07499   dbus_message_iter_append_string (&child_iter2, "dictvalue");
07500 
07501   /* array of array of int32  (in dict) */
07502   dbus_message_iter_append_dict_key (&child_iter, "array");
07503   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
07504   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07505   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
07506   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
07507   _dbus_warn ("next call expected to fail with wrong array type\n");
07508   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
07509   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
07510   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
07511   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
07512   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
07513   
07514   dbus_message_iter_append_byte (&iter, 0xF0);
07515 
07516   dbus_message_iter_append_nil (&iter);
07517 
07518   dbus_message_iter_append_custom (&iter, "MyTypeName",
07519                                    "data", 5);
07520   
07521   dbus_message_iter_append_byte (&iter, 0xF0);
07522 
07523   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_INT32);
07524 
07525   dbus_message_iter_append_byte (&iter, 0xF0);
07526 
07527   dbus_message_iter_append_dict (&iter, &child_iter);
07528 
07529   dbus_message_iter_append_byte (&iter, 0xF0);
07530 
07531   message_iter_test (message);
07532   
07533   /* Message loader test */
07534   _dbus_message_lock (message);
07535   loader = _dbus_message_loader_new ();
07536 
07537   /* check ref/unref */
07538   _dbus_message_loader_ref (loader);
07539   _dbus_message_loader_unref (loader);
07540   
07541   /* Write the header data one byte at a time */
07542   data = _dbus_string_get_const_data (&message->header);
07543   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
07544     {
07545       DBusString *buffer;
07546 
07547       _dbus_message_loader_get_buffer (loader, &buffer);
07548       _dbus_string_append_byte (buffer, data[i]);
07549       _dbus_message_loader_return_buffer (loader, buffer, 1);
07550     }
07551 
07552   /* Write the body data one byte at a time */
07553   data = _dbus_string_get_const_data (&message->body);
07554   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
07555     {
07556       DBusString *buffer;
07557 
07558       _dbus_message_loader_get_buffer (loader, &buffer);
07559       _dbus_string_append_byte (buffer, data[i]);
07560       _dbus_message_loader_return_buffer (loader, buffer, 1);
07561     }
07562 
07563   copy = dbus_message_copy (message); /* save for tests below */
07564   dbus_message_unref (message);
07565 
07566   /* Now pop back the message */
07567   if (!_dbus_message_loader_queue_messages (loader))
07568     _dbus_assert_not_reached ("no memory to queue messages");
07569   
07570   if (_dbus_message_loader_get_is_corrupted (loader))
07571     _dbus_assert_not_reached ("message loader corrupted");
07572   
07573   message = _dbus_message_loader_pop_message (loader);
07574   if (!message)
07575     _dbus_assert_not_reached ("received a NULL message");
07576 
07577   if (dbus_message_get_reply_serial (message) != 0x12345678)
07578     _dbus_assert_not_reached ("reply serial fields differ");
07579   
07580   message_iter_test (message);
07581   
07582   dbus_message_unref (message);
07583   _dbus_message_loader_unref (loader);
07584 
07585   message = dbus_message_new_method_return (copy);
07586   if (message == NULL)
07587     _dbus_assert_not_reached ("out of memory\n");
07588   dbus_message_unref (copy);
07589 
07590   if (!dbus_message_append_args (message,
07591                                  DBUS_TYPE_STRING, "hello",
07592                                  DBUS_TYPE_INVALID))
07593     _dbus_assert_not_reached ("no memory");
07594 
07595   if (!dbus_message_has_signature (message, "s"))
07596     _dbus_assert_not_reached ("method return has wrong signature");
07597 
07598   dbus_error_init (&error);
07599   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
07600                               &t, DBUS_TYPE_INVALID))
07601     
07602     {
07603       _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
07604       exit (1);
07605     }
07606   dbus_free (t);
07607   
07608   dbus_message_unref (message);
07609 
07610   /* This ServiceAcquired message used to trigger a bug in
07611    * setting header fields, adding to regression test.
07612    */
07613   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
07614                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
07615                                      "ServiceAcquired");
07616   
07617   if (message == NULL)
07618     _dbus_assert_not_reached ("out of memory");
07619 
07620   _dbus_verbose ("Bytes after creation\n");
07621   _dbus_verbose_bytes_of_string (&message->header, 0,
07622                                  _dbus_string_get_length (&message->header));
07623   
07624   if (!dbus_message_set_destination (message, ":1.0") ||
07625       !dbus_message_append_args (message,
07626                                  DBUS_TYPE_STRING, ":1.0",
07627                                  DBUS_TYPE_INVALID))
07628     _dbus_assert_not_reached ("out of memory");
07629 
07630   _dbus_verbose ("Bytes after set_destination() and append_args()\n");
07631   _dbus_verbose_bytes_of_string (&message->header, 0,
07632                                  _dbus_string_get_length (&message->header));
07633   
07634   if (!dbus_message_set_sender (message, "org.freedesktop.DBus"))
07635     _dbus_assert_not_reached ("out of memory");
07636 
07637   _dbus_verbose ("Bytes after set_sender()\n");
07638   _dbus_verbose_bytes_of_string (&message->header, 0,
07639                                  _dbus_string_get_length (&message->header));
07640 
07641   /* When the bug happened the above set_destination() would
07642    * corrupt the signature
07643    */
07644   if (!dbus_message_has_signature (message, "s"))
07645     {
07646       _dbus_warn ("Signature should be 's' but is '%s'\n",
07647                   dbus_message_get_signature (message));
07648       _dbus_assert_not_reached ("signal has wrong signature");
07649     }
07650   
07651   /* have to set destination again to reproduce the bug */
07652   if (!dbus_message_set_destination (message, ":1.0"))
07653     _dbus_assert_not_reached ("out of memory");
07654 
07655   _dbus_verbose ("Bytes after set_destination()\n");
07656   _dbus_verbose_bytes_of_string (&message->header, 0,
07657                                  _dbus_string_get_length (&message->header));
07658   
07659   /* When the bug happened the above set_destination() would
07660    * corrupt the signature
07661    */
07662   if (!dbus_message_has_signature (message, "s"))
07663     {
07664       _dbus_warn ("Signature should be 's' but is '%s'\n",
07665                   dbus_message_get_signature (message));
07666       _dbus_assert_not_reached ("signal has wrong signature");
07667     }
07668 
07669   dbus_error_init (&error);
07670   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
07671                               &t, DBUS_TYPE_INVALID))
07672     
07673     {
07674       _dbus_warn ("Failed to get expected string arg for signal: %s\n", error.message);
07675       exit (1);
07676     }
07677   dbus_free (t);  
07678   
07679   dbus_message_unref (message);
07680   
07681   /* Now load every message in test_data_dir if we have one */
07682   if (test_data_dir == NULL)
07683     return TRUE;
07684 
07685   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
07686                                                         (DBusForeachMessageFileFunc)
07687                                                         dbus_internal_do_not_use_try_message_file,
07688                                                         NULL);
07689 }
07690 
07691 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Mar 30 21:15:21 2005 for D-BUS by  doxygen 1.4.1