D-Bus 1.2.24
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-message.c DBusMessage object 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include "dbus-internals.h" 00026 #include "dbus-marshal-recursive.h" 00027 #include "dbus-marshal-validate.h" 00028 #include "dbus-marshal-byteswap.h" 00029 #include "dbus-marshal-header.h" 00030 #include "dbus-signature.h" 00031 #include "dbus-message-private.h" 00032 #include "dbus-object-tree.h" 00033 #include "dbus-memory.h" 00034 #include "dbus-list.h" 00035 #include "dbus-threads-internal.h" 00036 #include <string.h> 00037 00038 static void dbus_message_finalize (DBusMessage *message); 00039 00050 /* Not thread locked, but strictly const/read-only so should be OK 00051 */ 00053 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, ""); 00054 00055 /* these have wacky values to help trap uninitialized iterators; 00056 * but has to fit in 3 bits 00057 */ 00058 enum { 00059 DBUS_MESSAGE_ITER_TYPE_READER = 3, 00060 DBUS_MESSAGE_ITER_TYPE_WRITER = 7 00061 }; 00062 00064 typedef struct DBusMessageRealIter DBusMessageRealIter; 00065 00071 struct DBusMessageRealIter 00072 { 00073 DBusMessage *message; 00074 dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 00075 dbus_uint32_t iter_type : 3; 00076 dbus_uint32_t sig_refcount : 8; 00077 union 00078 { 00079 DBusTypeWriter writer; 00080 DBusTypeReader reader; 00081 } u; 00082 }; 00083 00084 static void 00085 get_const_signature (DBusHeader *header, 00086 const DBusString **type_str_p, 00087 int *type_pos_p) 00088 { 00089 if (_dbus_header_get_field_raw (header, 00090 DBUS_HEADER_FIELD_SIGNATURE, 00091 type_str_p, 00092 type_pos_p)) 00093 { 00094 *type_pos_p += 1; /* skip the signature length which is 1 byte */ 00095 } 00096 else 00097 { 00098 *type_str_p = &_dbus_empty_signature_str; 00099 *type_pos_p = 0; 00100 } 00101 } 00102 00108 static void 00109 _dbus_message_byteswap (DBusMessage *message) 00110 { 00111 const DBusString *type_str; 00112 int type_pos; 00113 00114 if (message->byte_order == DBUS_COMPILER_BYTE_ORDER) 00115 return; 00116 00117 _dbus_verbose ("Swapping message into compiler byte order\n"); 00118 00119 get_const_signature (&message->header, &type_str, &type_pos); 00120 00121 _dbus_marshal_byteswap (type_str, type_pos, 00122 message->byte_order, 00123 DBUS_COMPILER_BYTE_ORDER, 00124 &message->body, 0); 00125 00126 message->byte_order = DBUS_COMPILER_BYTE_ORDER; 00127 00128 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER); 00129 } 00130 00137 #define ensure_byte_order(message) \ 00138 if (message->byte_order != DBUS_COMPILER_BYTE_ORDER) \ 00139 _dbus_message_byteswap (message) 00140 00151 void 00152 _dbus_message_get_network_data (DBusMessage *message, 00153 const DBusString **header, 00154 const DBusString **body) 00155 { 00156 _dbus_assert (message->locked); 00157 00158 *header = &message->header.data; 00159 *body = &message->body; 00160 } 00161 00173 void 00174 dbus_message_set_serial (DBusMessage *message, 00175 dbus_uint32_t serial) 00176 { 00177 _dbus_return_if_fail (message != NULL); 00178 _dbus_return_if_fail (!message->locked); 00179 00180 _dbus_header_set_serial (&message->header, serial); 00181 } 00182 00195 void 00196 _dbus_message_add_size_counter_link (DBusMessage *message, 00197 DBusList *link) 00198 { 00199 /* right now we don't recompute the delta when message 00200 * size changes, and that's OK for current purposes 00201 * I think, but could be important to change later. 00202 * Do recompute it whenever there are no outstanding counters, 00203 * since it's basically free. 00204 */ 00205 if (message->size_counters == NULL) 00206 { 00207 message->size_counter_delta = 00208 _dbus_string_get_length (&message->header.data) + 00209 _dbus_string_get_length (&message->body); 00210 00211 #if 0 00212 _dbus_verbose ("message has size %ld\n", 00213 message->size_counter_delta); 00214 #endif 00215 } 00216 00217 _dbus_list_append_link (&message->size_counters, link); 00218 00219 _dbus_counter_adjust (link->data, message->size_counter_delta); 00220 } 00221 00231 dbus_bool_t 00232 _dbus_message_add_size_counter (DBusMessage *message, 00233 DBusCounter *counter) 00234 { 00235 DBusList *link; 00236 00237 link = _dbus_list_alloc_link (counter); 00238 if (link == NULL) 00239 return FALSE; 00240 00241 _dbus_counter_ref (counter); 00242 _dbus_message_add_size_counter_link (message, link); 00243 00244 return TRUE; 00245 } 00246 00255 void 00256 _dbus_message_remove_size_counter (DBusMessage *message, 00257 DBusCounter *counter, 00258 DBusList **link_return) 00259 { 00260 DBusList *link; 00261 00262 link = _dbus_list_find_last (&message->size_counters, 00263 counter); 00264 _dbus_assert (link != NULL); 00265 00266 _dbus_list_unlink (&message->size_counters, 00267 link); 00268 if (link_return) 00269 *link_return = link; 00270 else 00271 _dbus_list_free_link (link); 00272 00273 _dbus_counter_adjust (counter, - message->size_counter_delta); 00274 00275 _dbus_counter_unref (counter); 00276 } 00277 00288 void 00289 dbus_message_lock (DBusMessage *message) 00290 { 00291 if (!message->locked) 00292 { 00293 _dbus_header_update_lengths (&message->header, 00294 _dbus_string_get_length (&message->body)); 00295 00296 /* must have a signature if you have a body */ 00297 _dbus_assert (_dbus_string_get_length (&message->body) == 0 || 00298 dbus_message_get_signature (message) != NULL); 00299 00300 message->locked = TRUE; 00301 } 00302 } 00303 00304 static dbus_bool_t 00305 set_or_delete_string_field (DBusMessage *message, 00306 int field, 00307 int typecode, 00308 const char *value) 00309 { 00310 if (value == NULL) 00311 return _dbus_header_delete_field (&message->header, field); 00312 else 00313 return _dbus_header_set_field_basic (&message->header, 00314 field, 00315 typecode, 00316 &value); 00317 } 00318 00319 #if 0 00320 /* Probably we don't need to use this */ 00344 static dbus_bool_t 00345 _dbus_message_set_signature (DBusMessage *message, 00346 const char *signature) 00347 { 00348 _dbus_return_val_if_fail (message != NULL, FALSE); 00349 _dbus_return_val_if_fail (!message->locked, FALSE); 00350 _dbus_return_val_if_fail (signature == NULL || 00351 _dbus_check_is_valid_signature (signature)); 00352 /* can't delete the signature if you have a message body */ 00353 _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || 00354 signature != NULL); 00355 00356 return set_or_delete_string_field (message, 00357 DBUS_HEADER_FIELD_SIGNATURE, 00358 DBUS_TYPE_SIGNATURE, 00359 signature); 00360 } 00361 #endif 00362 00363 /* Message Cache 00364 * 00365 * We cache some DBusMessage to reduce the overhead of allocating 00366 * them. In my profiling this consistently made about an 8% 00367 * difference. It avoids the malloc for the message, the malloc for 00368 * the slot list, the malloc for the header string and body string, 00369 * and the associated free() calls. It does introduce another global 00370 * lock which could be a performance issue in certain cases. 00371 * 00372 * For the echo client/server the round trip time goes from around 00373 * .000077 to .000069 with the message cache on my laptop. The sysprof 00374 * change is as follows (numbers are cumulative percentage): 00375 * 00376 * with message cache implemented as array as it is now (0.000069 per): 00377 * new_empty_header 1.46 00378 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache) 00379 * mutex_unlock 0.25 00380 * self 0.41 00381 * unref 2.24 00382 * self 0.68 00383 * list_clear 0.43 00384 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache) 00385 * mutex_unlock 0.25 00386 * 00387 * with message cache implemented as list (0.000070 per roundtrip): 00388 * new_empty_header 2.72 00389 * list_pop_first 1.88 00390 * unref 3.3 00391 * list_prepend 1.63 00392 * 00393 * without cache (0.000077 per roundtrip): 00394 * new_empty_header 6.7 00395 * string_init_preallocated 3.43 00396 * dbus_malloc 2.43 00397 * dbus_malloc0 2.59 00398 * 00399 * unref 4.02 00400 * string_free 1.82 00401 * dbus_free 1.63 00402 * dbus_free 0.71 00403 * 00404 * If you implement the message_cache with a list, the primary reason 00405 * it's slower is that you add another thread lock (on the DBusList 00406 * mempool). 00407 */ 00408 00410 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE 00411 00413 #define MAX_MESSAGE_CACHE_SIZE 5 00414 00415 _DBUS_DEFINE_GLOBAL_LOCK (message_cache); 00416 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; 00417 static int message_cache_count = 0; 00418 static dbus_bool_t message_cache_shutdown_registered = FALSE; 00419 00420 static void 00421 dbus_message_cache_shutdown (void *data) 00422 { 00423 int i; 00424 00425 _DBUS_LOCK (message_cache); 00426 00427 i = 0; 00428 while (i < MAX_MESSAGE_CACHE_SIZE) 00429 { 00430 if (message_cache[i]) 00431 dbus_message_finalize (message_cache[i]); 00432 00433 ++i; 00434 } 00435 00436 message_cache_count = 0; 00437 message_cache_shutdown_registered = FALSE; 00438 00439 _DBUS_UNLOCK (message_cache); 00440 } 00441 00449 static DBusMessage* 00450 dbus_message_get_cached (void) 00451 { 00452 DBusMessage *message; 00453 int i; 00454 00455 message = NULL; 00456 00457 _DBUS_LOCK (message_cache); 00458 00459 _dbus_assert (message_cache_count >= 0); 00460 00461 if (message_cache_count == 0) 00462 { 00463 _DBUS_UNLOCK (message_cache); 00464 return NULL; 00465 } 00466 00467 /* This is not necessarily true unless count > 0, and 00468 * message_cache is uninitialized until the shutdown is 00469 * registered 00470 */ 00471 _dbus_assert (message_cache_shutdown_registered); 00472 00473 i = 0; 00474 while (i < MAX_MESSAGE_CACHE_SIZE) 00475 { 00476 if (message_cache[i]) 00477 { 00478 message = message_cache[i]; 00479 message_cache[i] = NULL; 00480 message_cache_count -= 1; 00481 break; 00482 } 00483 ++i; 00484 } 00485 _dbus_assert (message_cache_count >= 0); 00486 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00487 _dbus_assert (message != NULL); 00488 00489 _dbus_assert (message->refcount.value == 0); 00490 _dbus_assert (message->size_counters == NULL); 00491 00492 _DBUS_UNLOCK (message_cache); 00493 00494 return message; 00495 } 00496 00497 static void 00498 free_size_counter (void *element, 00499 void *data) 00500 { 00501 DBusCounter *counter = element; 00502 DBusMessage *message = data; 00503 00504 _dbus_counter_adjust (counter, - message->size_counter_delta); 00505 00506 _dbus_counter_unref (counter); 00507 } 00508 00514 static void 00515 dbus_message_cache_or_finalize (DBusMessage *message) 00516 { 00517 dbus_bool_t was_cached; 00518 int i; 00519 00520 _dbus_assert (message->refcount.value == 0); 00521 00522 /* This calls application code and has to be done first thing 00523 * without holding the lock 00524 */ 00525 _dbus_data_slot_list_clear (&message->slot_list); 00526 00527 _dbus_list_foreach (&message->size_counters, 00528 free_size_counter, message); 00529 _dbus_list_clear (&message->size_counters); 00530 00531 was_cached = FALSE; 00532 00533 _DBUS_LOCK (message_cache); 00534 00535 if (!message_cache_shutdown_registered) 00536 { 00537 _dbus_assert (message_cache_count == 0); 00538 00539 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL)) 00540 goto out; 00541 00542 i = 0; 00543 while (i < MAX_MESSAGE_CACHE_SIZE) 00544 { 00545 message_cache[i] = NULL; 00546 ++i; 00547 } 00548 00549 message_cache_shutdown_registered = TRUE; 00550 } 00551 00552 _dbus_assert (message_cache_count >= 0); 00553 00554 if ((_dbus_string_get_length (&message->header.data) + 00555 _dbus_string_get_length (&message->body)) > 00556 MAX_MESSAGE_SIZE_TO_CACHE) 00557 goto out; 00558 00559 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE) 00560 goto out; 00561 00562 /* Find empty slot */ 00563 i = 0; 00564 while (message_cache[i] != NULL) 00565 ++i; 00566 00567 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00568 00569 _dbus_assert (message_cache[i] == NULL); 00570 message_cache[i] = message; 00571 message_cache_count += 1; 00572 was_cached = TRUE; 00573 #ifndef DBUS_DISABLE_CHECKS 00574 message->in_cache = TRUE; 00575 #endif 00576 00577 out: 00578 _dbus_assert (message->refcount.value == 0); 00579 00580 _DBUS_UNLOCK (message_cache); 00581 00582 if (!was_cached) 00583 dbus_message_finalize (message); 00584 } 00585 00586 #ifndef DBUS_DISABLE_CHECKS 00587 static dbus_bool_t 00588 _dbus_message_iter_check (DBusMessageRealIter *iter) 00589 { 00590 if (iter == NULL) 00591 { 00592 _dbus_warn_check_failed ("dbus message iterator is NULL\n"); 00593 return FALSE; 00594 } 00595 00596 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER) 00597 { 00598 if (iter->u.reader.byte_order != iter->message->byte_order) 00599 { 00600 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n"); 00601 return FALSE; 00602 } 00603 /* because we swap the message into compiler order when you init an iter */ 00604 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); 00605 } 00606 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) 00607 { 00608 if (iter->u.writer.byte_order != iter->message->byte_order) 00609 { 00610 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n"); 00611 return FALSE; 00612 } 00613 /* because we swap the message into compiler order when you init an iter */ 00614 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); 00615 } 00616 else 00617 { 00618 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n"); 00619 return FALSE; 00620 } 00621 00622 if (iter->changed_stamp != iter->message->changed_stamp) 00623 { 00624 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); 00625 return FALSE; 00626 } 00627 00628 return TRUE; 00629 } 00630 #endif /* DBUS_DISABLE_CHECKS */ 00631 00644 dbus_bool_t 00645 _dbus_message_iter_get_args_valist (DBusMessageIter *iter, 00646 DBusError *error, 00647 int first_arg_type, 00648 va_list var_args) 00649 { 00650 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 00651 int spec_type, msg_type, i; 00652 dbus_bool_t retval; 00653 00654 _dbus_assert (_dbus_message_iter_check (real)); 00655 00656 retval = FALSE; 00657 00658 spec_type = first_arg_type; 00659 i = 0; 00660 00661 while (spec_type != DBUS_TYPE_INVALID) 00662 { 00663 msg_type = dbus_message_iter_get_arg_type (iter); 00664 00665 if (msg_type != spec_type) 00666 { 00667 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00668 "Argument %d is specified to be of type \"%s\", but " 00669 "is actually of type \"%s\"\n", i, 00670 _dbus_type_to_string (spec_type), 00671 _dbus_type_to_string (msg_type)); 00672 00673 goto out; 00674 } 00675 00676 if (dbus_type_is_basic (spec_type)) 00677 { 00678 DBusBasicValue *ptr; 00679 00680 ptr = va_arg (var_args, DBusBasicValue*); 00681 00682 _dbus_assert (ptr != NULL); 00683 00684 _dbus_type_reader_read_basic (&real->u.reader, 00685 ptr); 00686 } 00687 else if (spec_type == DBUS_TYPE_ARRAY) 00688 { 00689 int element_type; 00690 int spec_element_type; 00691 const DBusBasicValue **ptr; 00692 int *n_elements_p; 00693 DBusTypeReader array; 00694 00695 spec_element_type = va_arg (var_args, int); 00696 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 00697 00698 if (spec_element_type != element_type) 00699 { 00700 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00701 "Argument %d is specified to be an array of \"%s\", but " 00702 "is actually an array of \"%s\"\n", 00703 i, 00704 _dbus_type_to_string (spec_element_type), 00705 _dbus_type_to_string (element_type)); 00706 00707 goto out; 00708 } 00709 00710 if (dbus_type_is_fixed (spec_element_type)) 00711 { 00712 ptr = va_arg (var_args, const DBusBasicValue**); 00713 n_elements_p = va_arg (var_args, int*); 00714 00715 _dbus_assert (ptr != NULL); 00716 _dbus_assert (n_elements_p != NULL); 00717 00718 _dbus_type_reader_recurse (&real->u.reader, &array); 00719 00720 _dbus_type_reader_read_fixed_multi (&array, 00721 ptr, n_elements_p); 00722 } 00723 else if (spec_element_type == DBUS_TYPE_STRING || 00724 spec_element_type == DBUS_TYPE_SIGNATURE || 00725 spec_element_type == DBUS_TYPE_OBJECT_PATH) 00726 { 00727 char ***str_array_p; 00728 int n_elements; 00729 char **str_array; 00730 00731 str_array_p = va_arg (var_args, char***); 00732 n_elements_p = va_arg (var_args, int*); 00733 00734 _dbus_assert (str_array_p != NULL); 00735 _dbus_assert (n_elements_p != NULL); 00736 00737 /* Count elements in the array */ 00738 _dbus_type_reader_recurse (&real->u.reader, &array); 00739 00740 n_elements = 0; 00741 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 00742 { 00743 ++n_elements; 00744 _dbus_type_reader_next (&array); 00745 } 00746 00747 str_array = dbus_new0 (char*, n_elements + 1); 00748 if (str_array == NULL) 00749 { 00750 _DBUS_SET_OOM (error); 00751 goto out; 00752 } 00753 00754 /* Now go through and dup each string */ 00755 _dbus_type_reader_recurse (&real->u.reader, &array); 00756 00757 i = 0; 00758 while (i < n_elements) 00759 { 00760 const char *s; 00761 _dbus_type_reader_read_basic (&array, 00762 &s); 00763 00764 str_array[i] = _dbus_strdup (s); 00765 if (str_array[i] == NULL) 00766 { 00767 dbus_free_string_array (str_array); 00768 _DBUS_SET_OOM (error); 00769 goto out; 00770 } 00771 00772 ++i; 00773 00774 if (!_dbus_type_reader_next (&array)) 00775 _dbus_assert (i == n_elements); 00776 } 00777 00778 _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); 00779 _dbus_assert (i == n_elements); 00780 _dbus_assert (str_array[i] == NULL); 00781 00782 *str_array_p = str_array; 00783 *n_elements_p = n_elements; 00784 } 00785 #ifndef DBUS_DISABLE_CHECKS 00786 else 00787 { 00788 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", 00789 _DBUS_FUNCTION_NAME); 00790 goto out; 00791 } 00792 #endif 00793 } 00794 #ifndef DBUS_DISABLE_CHECKS 00795 else 00796 { 00797 _dbus_warn ("you can only read arrays and basic types with %s for now\n", 00798 _DBUS_FUNCTION_NAME); 00799 goto out; 00800 } 00801 #endif 00802 00803 spec_type = va_arg (var_args, int); 00804 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) 00805 { 00806 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00807 "Message has only %d arguments, but more were expected", i); 00808 goto out; 00809 } 00810 00811 i++; 00812 } 00813 00814 retval = TRUE; 00815 00816 out: 00817 00818 return retval; 00819 } 00820 00879 dbus_uint32_t 00880 dbus_message_get_serial (DBusMessage *message) 00881 { 00882 _dbus_return_val_if_fail (message != NULL, 0); 00883 00884 return _dbus_header_get_serial (&message->header); 00885 } 00886 00895 dbus_bool_t 00896 dbus_message_set_reply_serial (DBusMessage *message, 00897 dbus_uint32_t reply_serial) 00898 { 00899 _dbus_return_val_if_fail (message != NULL, FALSE); 00900 _dbus_return_val_if_fail (!message->locked, FALSE); 00901 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */ 00902 00903 return _dbus_header_set_field_basic (&message->header, 00904 DBUS_HEADER_FIELD_REPLY_SERIAL, 00905 DBUS_TYPE_UINT32, 00906 &reply_serial); 00907 } 00908 00915 dbus_uint32_t 00916 dbus_message_get_reply_serial (DBusMessage *message) 00917 { 00918 dbus_uint32_t v_UINT32; 00919 00920 _dbus_return_val_if_fail (message != NULL, 0); 00921 00922 if (_dbus_header_get_field_basic (&message->header, 00923 DBUS_HEADER_FIELD_REPLY_SERIAL, 00924 DBUS_TYPE_UINT32, 00925 &v_UINT32)) 00926 return v_UINT32; 00927 else 00928 return 0; 00929 } 00930 00931 static void 00932 dbus_message_finalize (DBusMessage *message) 00933 { 00934 _dbus_assert (message->refcount.value == 0); 00935 00936 /* This calls application callbacks! */ 00937 _dbus_data_slot_list_free (&message->slot_list); 00938 00939 _dbus_list_foreach (&message->size_counters, 00940 free_size_counter, message); 00941 _dbus_list_clear (&message->size_counters); 00942 00943 _dbus_header_free (&message->header); 00944 _dbus_string_free (&message->body); 00945 00946 _dbus_assert (message->refcount.value == 0); 00947 00948 dbus_free (message); 00949 } 00950 00951 static DBusMessage* 00952 dbus_message_new_empty_header (void) 00953 { 00954 DBusMessage *message; 00955 dbus_bool_t from_cache; 00956 00957 message = dbus_message_get_cached (); 00958 00959 if (message != NULL) 00960 { 00961 from_cache = TRUE; 00962 } 00963 else 00964 { 00965 from_cache = FALSE; 00966 message = dbus_new (DBusMessage, 1); 00967 if (message == NULL) 00968 return NULL; 00969 #ifndef DBUS_DISABLE_CHECKS 00970 message->generation = _dbus_current_generation; 00971 #endif 00972 } 00973 00974 message->refcount.value = 1; 00975 message->byte_order = DBUS_COMPILER_BYTE_ORDER; 00976 message->locked = FALSE; 00977 #ifndef DBUS_DISABLE_CHECKS 00978 message->in_cache = FALSE; 00979 #endif 00980 message->size_counters = NULL; 00981 message->size_counter_delta = 0; 00982 message->changed_stamp = 0; 00983 00984 if (!from_cache) 00985 _dbus_data_slot_list_init (&message->slot_list); 00986 00987 if (from_cache) 00988 { 00989 _dbus_header_reinit (&message->header, message->byte_order); 00990 _dbus_string_set_length (&message->body, 0); 00991 } 00992 else 00993 { 00994 if (!_dbus_header_init (&message->header, message->byte_order)) 00995 { 00996 dbus_free (message); 00997 return NULL; 00998 } 00999 01000 if (!_dbus_string_init_preallocated (&message->body, 32)) 01001 { 01002 _dbus_header_free (&message->header); 01003 dbus_free (message); 01004 return NULL; 01005 } 01006 } 01007 01008 return message; 01009 } 01010 01023 DBusMessage* 01024 dbus_message_new (int message_type) 01025 { 01026 DBusMessage *message; 01027 01028 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL); 01029 01030 message = dbus_message_new_empty_header (); 01031 if (message == NULL) 01032 return NULL; 01033 01034 if (!_dbus_header_create (&message->header, 01035 message_type, 01036 NULL, NULL, NULL, NULL, NULL)) 01037 { 01038 dbus_message_unref (message); 01039 return NULL; 01040 } 01041 01042 return message; 01043 } 01044 01066 DBusMessage* 01067 dbus_message_new_method_call (const char *destination, 01068 const char *path, 01069 const char *interface, 01070 const char *method) 01071 { 01072 DBusMessage *message; 01073 01074 _dbus_return_val_if_fail (path != NULL, NULL); 01075 _dbus_return_val_if_fail (method != NULL, NULL); 01076 _dbus_return_val_if_fail (destination == NULL || 01077 _dbus_check_is_valid_bus_name (destination), NULL); 01078 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01079 _dbus_return_val_if_fail (interface == NULL || 01080 _dbus_check_is_valid_interface (interface), NULL); 01081 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); 01082 01083 message = dbus_message_new_empty_header (); 01084 if (message == NULL) 01085 return NULL; 01086 01087 if (!_dbus_header_create (&message->header, 01088 DBUS_MESSAGE_TYPE_METHOD_CALL, 01089 destination, path, interface, method, NULL)) 01090 { 01091 dbus_message_unref (message); 01092 return NULL; 01093 } 01094 01095 return message; 01096 } 01097 01105 DBusMessage* 01106 dbus_message_new_method_return (DBusMessage *method_call) 01107 { 01108 DBusMessage *message; 01109 const char *sender; 01110 01111 _dbus_return_val_if_fail (method_call != NULL, NULL); 01112 01113 sender = dbus_message_get_sender (method_call); 01114 01115 /* sender is allowed to be null here in peer-to-peer case */ 01116 01117 message = dbus_message_new_empty_header (); 01118 if (message == NULL) 01119 return NULL; 01120 01121 if (!_dbus_header_create (&message->header, 01122 DBUS_MESSAGE_TYPE_METHOD_RETURN, 01123 sender, NULL, NULL, NULL, NULL)) 01124 { 01125 dbus_message_unref (message); 01126 return NULL; 01127 } 01128 01129 dbus_message_set_no_reply (message, TRUE); 01130 01131 if (!dbus_message_set_reply_serial (message, 01132 dbus_message_get_serial (method_call))) 01133 { 01134 dbus_message_unref (message); 01135 return NULL; 01136 } 01137 01138 return message; 01139 } 01140 01155 DBusMessage* 01156 dbus_message_new_signal (const char *path, 01157 const char *interface, 01158 const char *name) 01159 { 01160 DBusMessage *message; 01161 01162 _dbus_return_val_if_fail (path != NULL, NULL); 01163 _dbus_return_val_if_fail (interface != NULL, NULL); 01164 _dbus_return_val_if_fail (name != NULL, NULL); 01165 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01166 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL); 01167 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); 01168 01169 message = dbus_message_new_empty_header (); 01170 if (message == NULL) 01171 return NULL; 01172 01173 if (!_dbus_header_create (&message->header, 01174 DBUS_MESSAGE_TYPE_SIGNAL, 01175 NULL, path, interface, name, NULL)) 01176 { 01177 dbus_message_unref (message); 01178 return NULL; 01179 } 01180 01181 dbus_message_set_no_reply (message, TRUE); 01182 01183 return message; 01184 } 01185 01200 DBusMessage* 01201 dbus_message_new_error (DBusMessage *reply_to, 01202 const char *error_name, 01203 const char *error_message) 01204 { 01205 DBusMessage *message; 01206 const char *sender; 01207 DBusMessageIter iter; 01208 01209 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01210 _dbus_return_val_if_fail (error_name != NULL, NULL); 01211 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01212 01213 sender = dbus_message_get_sender (reply_to); 01214 01215 /* sender may be NULL for non-message-bus case or 01216 * when the message bus is dealing with an unregistered 01217 * connection. 01218 */ 01219 message = dbus_message_new_empty_header (); 01220 if (message == NULL) 01221 return NULL; 01222 01223 if (!_dbus_header_create (&message->header, 01224 DBUS_MESSAGE_TYPE_ERROR, 01225 sender, NULL, NULL, NULL, error_name)) 01226 { 01227 dbus_message_unref (message); 01228 return NULL; 01229 } 01230 01231 dbus_message_set_no_reply (message, TRUE); 01232 01233 if (!dbus_message_set_reply_serial (message, 01234 dbus_message_get_serial (reply_to))) 01235 { 01236 dbus_message_unref (message); 01237 return NULL; 01238 } 01239 01240 if (error_message != NULL) 01241 { 01242 dbus_message_iter_init_append (message, &iter); 01243 if (!dbus_message_iter_append_basic (&iter, 01244 DBUS_TYPE_STRING, 01245 &error_message)) 01246 { 01247 dbus_message_unref (message); 01248 return NULL; 01249 } 01250 } 01251 01252 return message; 01253 } 01254 01271 DBusMessage* 01272 dbus_message_new_error_printf (DBusMessage *reply_to, 01273 const char *error_name, 01274 const char *error_format, 01275 ...) 01276 { 01277 va_list args; 01278 DBusString str; 01279 DBusMessage *message; 01280 01281 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01282 _dbus_return_val_if_fail (error_name != NULL, NULL); 01283 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01284 01285 if (!_dbus_string_init (&str)) 01286 return NULL; 01287 01288 va_start (args, error_format); 01289 01290 if (_dbus_string_append_printf_valist (&str, error_format, args)) 01291 message = dbus_message_new_error (reply_to, error_name, 01292 _dbus_string_get_const_data (&str)); 01293 else 01294 message = NULL; 01295 01296 _dbus_string_free (&str); 01297 01298 va_end (args); 01299 01300 return message; 01301 } 01302 01303 01314 DBusMessage * 01315 dbus_message_copy (const DBusMessage *message) 01316 { 01317 DBusMessage *retval; 01318 01319 _dbus_return_val_if_fail (message != NULL, NULL); 01320 01321 retval = dbus_new0 (DBusMessage, 1); 01322 if (retval == NULL) 01323 return NULL; 01324 01325 retval->refcount.value = 1; 01326 retval->byte_order = message->byte_order; 01327 retval->locked = FALSE; 01328 #ifndef DBUS_DISABLE_CHECKS 01329 retval->generation = message->generation; 01330 #endif 01331 01332 if (!_dbus_header_copy (&message->header, &retval->header)) 01333 { 01334 dbus_free (retval); 01335 return NULL; 01336 } 01337 01338 if (!_dbus_string_init_preallocated (&retval->body, 01339 _dbus_string_get_length (&message->body))) 01340 { 01341 _dbus_header_free (&retval->header); 01342 dbus_free (retval); 01343 return NULL; 01344 } 01345 01346 if (!_dbus_string_copy (&message->body, 0, 01347 &retval->body, 0)) 01348 goto failed_copy; 01349 01350 return retval; 01351 01352 failed_copy: 01353 _dbus_header_free (&retval->header); 01354 _dbus_string_free (&retval->body); 01355 dbus_free (retval); 01356 01357 return NULL; 01358 } 01359 01360 01368 DBusMessage * 01369 dbus_message_ref (DBusMessage *message) 01370 { 01371 dbus_int32_t old_refcount; 01372 01373 _dbus_return_val_if_fail (message != NULL, NULL); 01374 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); 01375 _dbus_return_val_if_fail (!message->in_cache, NULL); 01376 01377 old_refcount = _dbus_atomic_inc (&message->refcount); 01378 _dbus_assert (old_refcount >= 1); 01379 01380 return message; 01381 } 01382 01390 void 01391 dbus_message_unref (DBusMessage *message) 01392 { 01393 dbus_int32_t old_refcount; 01394 01395 _dbus_return_if_fail (message != NULL); 01396 _dbus_return_if_fail (message->generation == _dbus_current_generation); 01397 _dbus_return_if_fail (!message->in_cache); 01398 01399 old_refcount = _dbus_atomic_dec (&message->refcount); 01400 01401 _dbus_assert (old_refcount >= 0); 01402 01403 if (old_refcount == 1) 01404 { 01405 /* Calls application callbacks! */ 01406 dbus_message_cache_or_finalize (message); 01407 } 01408 } 01409 01420 int 01421 dbus_message_get_type (DBusMessage *message) 01422 { 01423 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID); 01424 01425 return _dbus_header_get_message_type (&message->header); 01426 } 01427 01485 dbus_bool_t 01486 dbus_message_append_args (DBusMessage *message, 01487 int first_arg_type, 01488 ...) 01489 { 01490 dbus_bool_t retval; 01491 va_list var_args; 01492 01493 _dbus_return_val_if_fail (message != NULL, FALSE); 01494 01495 va_start (var_args, first_arg_type); 01496 retval = dbus_message_append_args_valist (message, 01497 first_arg_type, 01498 var_args); 01499 va_end (var_args); 01500 01501 return retval; 01502 } 01503 01517 dbus_bool_t 01518 dbus_message_append_args_valist (DBusMessage *message, 01519 int first_arg_type, 01520 va_list var_args) 01521 { 01522 int type; 01523 DBusMessageIter iter; 01524 01525 _dbus_return_val_if_fail (message != NULL, FALSE); 01526 01527 type = first_arg_type; 01528 01529 dbus_message_iter_init_append (message, &iter); 01530 01531 while (type != DBUS_TYPE_INVALID) 01532 { 01533 if (dbus_type_is_basic (type)) 01534 { 01535 const DBusBasicValue *value; 01536 value = va_arg (var_args, const DBusBasicValue*); 01537 01538 if (!dbus_message_iter_append_basic (&iter, 01539 type, 01540 value)) 01541 goto failed; 01542 } 01543 else if (type == DBUS_TYPE_ARRAY) 01544 { 01545 int element_type; 01546 DBusMessageIter array; 01547 char buf[2]; 01548 01549 element_type = va_arg (var_args, int); 01550 01551 buf[0] = element_type; 01552 buf[1] = '\0'; 01553 if (!dbus_message_iter_open_container (&iter, 01554 DBUS_TYPE_ARRAY, 01555 buf, 01556 &array)) 01557 goto failed; 01558 01559 if (dbus_type_is_fixed (element_type)) 01560 { 01561 const DBusBasicValue **value; 01562 int n_elements; 01563 01564 value = va_arg (var_args, const DBusBasicValue**); 01565 n_elements = va_arg (var_args, int); 01566 01567 if (!dbus_message_iter_append_fixed_array (&array, 01568 element_type, 01569 value, 01570 n_elements)) { 01571 dbus_message_iter_abandon_container (&iter, &array); 01572 goto failed; 01573 } 01574 } 01575 else if (element_type == DBUS_TYPE_STRING || 01576 element_type == DBUS_TYPE_SIGNATURE || 01577 element_type == DBUS_TYPE_OBJECT_PATH) 01578 { 01579 const char ***value_p; 01580 const char **value; 01581 int n_elements; 01582 int i; 01583 01584 value_p = va_arg (var_args, const char***); 01585 n_elements = va_arg (var_args, int); 01586 01587 value = *value_p; 01588 01589 i = 0; 01590 while (i < n_elements) 01591 { 01592 if (!dbus_message_iter_append_basic (&array, 01593 element_type, 01594 &value[i])) { 01595 dbus_message_iter_abandon_container (&iter, &array); 01596 goto failed; 01597 } 01598 ++i; 01599 } 01600 } 01601 else 01602 { 01603 _dbus_warn ("arrays of %s can't be appended with %s for now\n", 01604 _dbus_type_to_string (element_type), 01605 _DBUS_FUNCTION_NAME); 01606 goto failed; 01607 } 01608 01609 if (!dbus_message_iter_close_container (&iter, &array)) 01610 goto failed; 01611 } 01612 #ifndef DBUS_DISABLE_CHECKS 01613 else 01614 { 01615 _dbus_warn ("type %s isn't supported yet in %s\n", 01616 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME); 01617 goto failed; 01618 } 01619 #endif 01620 01621 type = va_arg (var_args, int); 01622 } 01623 01624 return TRUE; 01625 01626 failed: 01627 return FALSE; 01628 } 01629 01665 dbus_bool_t 01666 dbus_message_get_args (DBusMessage *message, 01667 DBusError *error, 01668 int first_arg_type, 01669 ...) 01670 { 01671 dbus_bool_t retval; 01672 va_list var_args; 01673 01674 _dbus_return_val_if_fail (message != NULL, FALSE); 01675 _dbus_return_val_if_error_is_set (error, FALSE); 01676 01677 va_start (var_args, first_arg_type); 01678 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args); 01679 va_end (var_args); 01680 01681 return retval; 01682 } 01683 01694 dbus_bool_t 01695 dbus_message_get_args_valist (DBusMessage *message, 01696 DBusError *error, 01697 int first_arg_type, 01698 va_list var_args) 01699 { 01700 DBusMessageIter iter; 01701 01702 _dbus_return_val_if_fail (message != NULL, FALSE); 01703 _dbus_return_val_if_error_is_set (error, FALSE); 01704 01705 dbus_message_iter_init (message, &iter); 01706 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); 01707 } 01708 01709 static void 01710 _dbus_message_iter_init_common (DBusMessage *message, 01711 DBusMessageRealIter *real, 01712 int iter_type) 01713 { 01714 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); 01715 01716 /* Since the iterator will read or write who-knows-what from the 01717 * message, we need to get in the right byte order 01718 */ 01719 ensure_byte_order (message); 01720 01721 real->message = message; 01722 real->changed_stamp = message->changed_stamp; 01723 real->iter_type = iter_type; 01724 real->sig_refcount = 0; 01725 } 01726 01749 dbus_bool_t 01750 dbus_message_iter_init (DBusMessage *message, 01751 DBusMessageIter *iter) 01752 { 01753 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01754 const DBusString *type_str; 01755 int type_pos; 01756 01757 _dbus_return_val_if_fail (message != NULL, FALSE); 01758 _dbus_return_val_if_fail (iter != NULL, FALSE); 01759 01760 get_const_signature (&message->header, &type_str, &type_pos); 01761 01762 _dbus_message_iter_init_common (message, real, 01763 DBUS_MESSAGE_ITER_TYPE_READER); 01764 01765 _dbus_type_reader_init (&real->u.reader, 01766 message->byte_order, 01767 type_str, type_pos, 01768 &message->body, 01769 0); 01770 01771 return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID; 01772 } 01773 01780 dbus_bool_t 01781 dbus_message_iter_has_next (DBusMessageIter *iter) 01782 { 01783 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01784 01785 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01786 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01787 01788 return _dbus_type_reader_has_next (&real->u.reader); 01789 } 01790 01799 dbus_bool_t 01800 dbus_message_iter_next (DBusMessageIter *iter) 01801 { 01802 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01803 01804 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01805 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01806 01807 return _dbus_type_reader_next (&real->u.reader); 01808 } 01809 01824 int 01825 dbus_message_iter_get_arg_type (DBusMessageIter *iter) 01826 { 01827 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01828 01829 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 01830 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01831 01832 return _dbus_type_reader_get_current_type (&real->u.reader); 01833 } 01834 01843 int 01844 dbus_message_iter_get_element_type (DBusMessageIter *iter) 01845 { 01846 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01847 01848 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 01849 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); 01850 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 01851 01852 return _dbus_type_reader_get_element_type (&real->u.reader); 01853 } 01854 01880 void 01881 dbus_message_iter_recurse (DBusMessageIter *iter, 01882 DBusMessageIter *sub) 01883 { 01884 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01885 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 01886 01887 _dbus_return_if_fail (_dbus_message_iter_check (real)); 01888 _dbus_return_if_fail (sub != NULL); 01889 01890 *real_sub = *real; 01891 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader); 01892 } 01893 01905 char * 01906 dbus_message_iter_get_signature (DBusMessageIter *iter) 01907 { 01908 const DBusString *sig; 01909 DBusString retstr; 01910 char *ret; 01911 int start, len; 01912 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01913 01914 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL); 01915 01916 if (!_dbus_string_init (&retstr)) 01917 return NULL; 01918 01919 _dbus_type_reader_get_signature (&real->u.reader, &sig, 01920 &start, &len); 01921 if (!_dbus_string_append_len (&retstr, 01922 _dbus_string_get_const_data (sig) + start, 01923 len)) 01924 return NULL; 01925 if (!_dbus_string_steal_data (&retstr, &ret)) 01926 return NULL; 01927 _dbus_string_free (&retstr); 01928 return ret; 01929 } 01930 01971 void 01972 dbus_message_iter_get_basic (DBusMessageIter *iter, 01973 void *value) 01974 { 01975 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01976 01977 _dbus_return_if_fail (_dbus_message_iter_check (real)); 01978 _dbus_return_if_fail (value != NULL); 01979 01980 _dbus_type_reader_read_basic (&real->u.reader, 01981 value); 01982 } 01983 02002 int 02003 dbus_message_iter_get_array_len (DBusMessageIter *iter) 02004 { 02005 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02006 02007 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02008 02009 return _dbus_type_reader_get_array_length (&real->u.reader); 02010 } 02011 02043 void 02044 dbus_message_iter_get_fixed_array (DBusMessageIter *iter, 02045 void *value, 02046 int *n_elements) 02047 { 02048 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02049 int subtype = _dbus_type_reader_get_current_type(&real->u.reader); 02050 02051 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02052 _dbus_return_if_fail (value != NULL); 02053 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) || 02054 dbus_type_is_fixed (subtype)); 02055 02056 _dbus_type_reader_read_fixed_multi (&real->u.reader, 02057 value, n_elements); 02058 } 02059 02071 void 02072 dbus_message_iter_init_append (DBusMessage *message, 02073 DBusMessageIter *iter) 02074 { 02075 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02076 02077 _dbus_return_if_fail (message != NULL); 02078 _dbus_return_if_fail (iter != NULL); 02079 02080 _dbus_message_iter_init_common (message, real, 02081 DBUS_MESSAGE_ITER_TYPE_WRITER); 02082 02083 /* We create the signature string and point iterators at it "on demand" 02084 * when a value is actually appended. That means that init() never fails 02085 * due to OOM. 02086 */ 02087 _dbus_type_writer_init_types_delayed (&real->u.writer, 02088 message->byte_order, 02089 &message->body, 02090 _dbus_string_get_length (&message->body)); 02091 } 02092 02101 static dbus_bool_t 02102 _dbus_message_iter_open_signature (DBusMessageRealIter *real) 02103 { 02104 DBusString *str; 02105 const DBusString *current_sig; 02106 int current_sig_pos; 02107 02108 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02109 02110 if (real->u.writer.type_str != NULL) 02111 { 02112 _dbus_assert (real->sig_refcount > 0); 02113 real->sig_refcount += 1; 02114 return TRUE; 02115 } 02116 02117 str = dbus_new (DBusString, 1); 02118 if (str == NULL) 02119 return FALSE; 02120 02121 if (!_dbus_header_get_field_raw (&real->message->header, 02122 DBUS_HEADER_FIELD_SIGNATURE, 02123 ¤t_sig, ¤t_sig_pos)) 02124 current_sig = NULL; 02125 02126 if (current_sig) 02127 { 02128 int current_len; 02129 02130 current_len = _dbus_string_get_byte (current_sig, current_sig_pos); 02131 current_sig_pos += 1; /* move on to sig data */ 02132 02133 if (!_dbus_string_init_preallocated (str, current_len + 4)) 02134 { 02135 dbus_free (str); 02136 return FALSE; 02137 } 02138 02139 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len, 02140 str, 0)) 02141 { 02142 _dbus_string_free (str); 02143 dbus_free (str); 02144 return FALSE; 02145 } 02146 } 02147 else 02148 { 02149 if (!_dbus_string_init_preallocated (str, 4)) 02150 { 02151 dbus_free (str); 02152 return FALSE; 02153 } 02154 } 02155 02156 real->sig_refcount = 1; 02157 02158 _dbus_type_writer_add_types (&real->u.writer, 02159 str, _dbus_string_get_length (str)); 02160 return TRUE; 02161 } 02162 02172 static dbus_bool_t 02173 _dbus_message_iter_close_signature (DBusMessageRealIter *real) 02174 { 02175 DBusString *str; 02176 const char *v_STRING; 02177 dbus_bool_t retval; 02178 02179 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02180 _dbus_assert (real->u.writer.type_str != NULL); 02181 _dbus_assert (real->sig_refcount > 0); 02182 02183 real->sig_refcount -= 1; 02184 02185 if (real->sig_refcount > 0) 02186 return TRUE; 02187 _dbus_assert (real->sig_refcount == 0); 02188 02189 retval = TRUE; 02190 02191 str = real->u.writer.type_str; 02192 02193 v_STRING = _dbus_string_get_const_data (str); 02194 if (!_dbus_header_set_field_basic (&real->message->header, 02195 DBUS_HEADER_FIELD_SIGNATURE, 02196 DBUS_TYPE_SIGNATURE, 02197 &v_STRING)) 02198 retval = FALSE; 02199 02200 _dbus_type_writer_remove_types (&real->u.writer); 02201 _dbus_string_free (str); 02202 dbus_free (str); 02203 02204 return retval; 02205 } 02206 02214 static void 02215 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real) 02216 { 02217 DBusString *str; 02218 02219 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02220 _dbus_assert (real->u.writer.type_str != NULL); 02221 _dbus_assert (real->sig_refcount > 0); 02222 02223 real->sig_refcount -= 1; 02224 02225 if (real->sig_refcount > 0) 02226 return; 02227 _dbus_assert (real->sig_refcount == 0); 02228 02229 str = real->u.writer.type_str; 02230 02231 _dbus_type_writer_remove_types (&real->u.writer); 02232 _dbus_string_free (str); 02233 dbus_free (str); 02234 } 02235 02236 #ifndef DBUS_DISABLE_CHECKS 02237 static dbus_bool_t 02238 _dbus_message_iter_append_check (DBusMessageRealIter *iter) 02239 { 02240 if (!_dbus_message_iter_check (iter)) 02241 return FALSE; 02242 02243 if (iter->message->locked) 02244 { 02245 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n"); 02246 return FALSE; 02247 } 02248 02249 return TRUE; 02250 } 02251 #endif /* DBUS_DISABLE_CHECKS */ 02252 02268 dbus_bool_t 02269 dbus_message_iter_append_basic (DBusMessageIter *iter, 02270 int type, 02271 const void *value) 02272 { 02273 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02274 dbus_bool_t ret; 02275 02276 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02277 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02278 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE); 02279 _dbus_return_val_if_fail (value != NULL, FALSE); 02280 02281 if (!_dbus_message_iter_open_signature (real)) 02282 return FALSE; 02283 02284 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02285 02286 if (!_dbus_message_iter_close_signature (real)) 02287 ret = FALSE; 02288 02289 return ret; 02290 } 02291 02327 dbus_bool_t 02328 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02329 int element_type, 02330 const void *value, 02331 int n_elements) 02332 { 02333 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02334 dbus_bool_t ret; 02335 02336 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02337 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02338 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type), FALSE); 02339 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02340 _dbus_return_val_if_fail (value != NULL, FALSE); 02341 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02342 _dbus_return_val_if_fail (n_elements <= 02343 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02344 FALSE); 02345 02346 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02347 02348 return ret; 02349 } 02350 02372 dbus_bool_t 02373 dbus_message_iter_open_container (DBusMessageIter *iter, 02374 int type, 02375 const char *contained_signature, 02376 DBusMessageIter *sub) 02377 { 02378 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02379 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02380 DBusString contained_str; 02381 02382 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02383 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02384 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02385 _dbus_return_val_if_fail (sub != NULL, FALSE); 02386 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02387 contained_signature == NULL) || 02388 (type == DBUS_TYPE_DICT_ENTRY && 02389 contained_signature == NULL) || 02390 (type == DBUS_TYPE_VARIANT && 02391 contained_signature != NULL) || 02392 (type == DBUS_TYPE_ARRAY && 02393 contained_signature != NULL), FALSE); 02394 02395 /* this would fail if the contained_signature is a dict entry, since 02396 * dict entries are invalid signatures standalone (they must be in 02397 * an array) 02398 */ 02399 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02400 (contained_signature == NULL || 02401 _dbus_check_is_valid_signature (contained_signature)), 02402 FALSE); 02403 02404 if (!_dbus_message_iter_open_signature (real)) 02405 return FALSE; 02406 02407 *real_sub = *real; 02408 02409 if (contained_signature != NULL) 02410 { 02411 _dbus_string_init_const (&contained_str, contained_signature); 02412 02413 return _dbus_type_writer_recurse (&real->u.writer, 02414 type, 02415 &contained_str, 0, 02416 &real_sub->u.writer); 02417 } 02418 else 02419 { 02420 return _dbus_type_writer_recurse (&real->u.writer, 02421 type, 02422 NULL, 0, 02423 &real_sub->u.writer); 02424 } 02425 } 02426 02427 02441 dbus_bool_t 02442 dbus_message_iter_close_container (DBusMessageIter *iter, 02443 DBusMessageIter *sub) 02444 { 02445 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02446 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02447 dbus_bool_t ret; 02448 02449 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02450 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02451 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 02452 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02453 02454 ret = _dbus_type_writer_unrecurse (&real->u.writer, 02455 &real_sub->u.writer); 02456 02457 if (!_dbus_message_iter_close_signature (real)) 02458 ret = FALSE; 02459 02460 return ret; 02461 } 02462 02474 void 02475 dbus_message_iter_abandon_container (DBusMessageIter *iter, 02476 DBusMessageIter *sub) 02477 { 02478 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02479 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02480 02481 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 02482 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02483 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 02484 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02485 02486 _dbus_message_iter_abandon_signature (real); 02487 } 02488 02505 void 02506 dbus_message_set_no_reply (DBusMessage *message, 02507 dbus_bool_t no_reply) 02508 { 02509 _dbus_return_if_fail (message != NULL); 02510 _dbus_return_if_fail (!message->locked); 02511 02512 _dbus_header_toggle_flag (&message->header, 02513 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 02514 no_reply); 02515 } 02516 02524 dbus_bool_t 02525 dbus_message_get_no_reply (DBusMessage *message) 02526 { 02527 _dbus_return_val_if_fail (message != NULL, FALSE); 02528 02529 return _dbus_header_get_flag (&message->header, 02530 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 02531 } 02532 02547 void 02548 dbus_message_set_auto_start (DBusMessage *message, 02549 dbus_bool_t auto_start) 02550 { 02551 _dbus_return_if_fail (message != NULL); 02552 _dbus_return_if_fail (!message->locked); 02553 02554 _dbus_header_toggle_flag (&message->header, 02555 DBUS_HEADER_FLAG_NO_AUTO_START, 02556 !auto_start); 02557 } 02558 02566 dbus_bool_t 02567 dbus_message_get_auto_start (DBusMessage *message) 02568 { 02569 _dbus_return_val_if_fail (message != NULL, FALSE); 02570 02571 return !_dbus_header_get_flag (&message->header, 02572 DBUS_HEADER_FLAG_NO_AUTO_START); 02573 } 02574 02575 02588 dbus_bool_t 02589 dbus_message_set_path (DBusMessage *message, 02590 const char *object_path) 02591 { 02592 _dbus_return_val_if_fail (message != NULL, FALSE); 02593 _dbus_return_val_if_fail (!message->locked, FALSE); 02594 _dbus_return_val_if_fail (object_path == NULL || 02595 _dbus_check_is_valid_path (object_path), 02596 FALSE); 02597 02598 return set_or_delete_string_field (message, 02599 DBUS_HEADER_FIELD_PATH, 02600 DBUS_TYPE_OBJECT_PATH, 02601 object_path); 02602 } 02603 02617 const char* 02618 dbus_message_get_path (DBusMessage *message) 02619 { 02620 const char *v; 02621 02622 _dbus_return_val_if_fail (message != NULL, NULL); 02623 02624 v = NULL; /* in case field doesn't exist */ 02625 _dbus_header_get_field_basic (&message->header, 02626 DBUS_HEADER_FIELD_PATH, 02627 DBUS_TYPE_OBJECT_PATH, 02628 &v); 02629 return v; 02630 } 02631 02641 dbus_bool_t 02642 dbus_message_has_path (DBusMessage *message, 02643 const char *path) 02644 { 02645 const char *msg_path; 02646 msg_path = dbus_message_get_path (message); 02647 02648 if (msg_path == NULL) 02649 { 02650 if (path == NULL) 02651 return TRUE; 02652 else 02653 return FALSE; 02654 } 02655 02656 if (path == NULL) 02657 return FALSE; 02658 02659 if (strcmp (msg_path, path) == 0) 02660 return TRUE; 02661 02662 return FALSE; 02663 } 02664 02685 dbus_bool_t 02686 dbus_message_get_path_decomposed (DBusMessage *message, 02687 char ***path) 02688 { 02689 const char *v; 02690 02691 _dbus_return_val_if_fail (message != NULL, FALSE); 02692 _dbus_return_val_if_fail (path != NULL, FALSE); 02693 02694 *path = NULL; 02695 02696 v = dbus_message_get_path (message); 02697 if (v != NULL) 02698 { 02699 if (!_dbus_decompose_path (v, strlen (v), 02700 path, NULL)) 02701 return FALSE; 02702 } 02703 return TRUE; 02704 } 02705 02719 dbus_bool_t 02720 dbus_message_set_interface (DBusMessage *message, 02721 const char *interface) 02722 { 02723 _dbus_return_val_if_fail (message != NULL, FALSE); 02724 _dbus_return_val_if_fail (!message->locked, FALSE); 02725 _dbus_return_val_if_fail (interface == NULL || 02726 _dbus_check_is_valid_interface (interface), 02727 FALSE); 02728 02729 return set_or_delete_string_field (message, 02730 DBUS_HEADER_FIELD_INTERFACE, 02731 DBUS_TYPE_STRING, 02732 interface); 02733 } 02734 02748 const char* 02749 dbus_message_get_interface (DBusMessage *message) 02750 { 02751 const char *v; 02752 02753 _dbus_return_val_if_fail (message != NULL, NULL); 02754 02755 v = NULL; /* in case field doesn't exist */ 02756 _dbus_header_get_field_basic (&message->header, 02757 DBUS_HEADER_FIELD_INTERFACE, 02758 DBUS_TYPE_STRING, 02759 &v); 02760 return v; 02761 } 02762 02770 dbus_bool_t 02771 dbus_message_has_interface (DBusMessage *message, 02772 const char *interface) 02773 { 02774 const char *msg_interface; 02775 msg_interface = dbus_message_get_interface (message); 02776 02777 if (msg_interface == NULL) 02778 { 02779 if (interface == NULL) 02780 return TRUE; 02781 else 02782 return FALSE; 02783 } 02784 02785 if (interface == NULL) 02786 return FALSE; 02787 02788 if (strcmp (msg_interface, interface) == 0) 02789 return TRUE; 02790 02791 return FALSE; 02792 02793 } 02794 02807 dbus_bool_t 02808 dbus_message_set_member (DBusMessage *message, 02809 const char *member) 02810 { 02811 _dbus_return_val_if_fail (message != NULL, FALSE); 02812 _dbus_return_val_if_fail (!message->locked, FALSE); 02813 _dbus_return_val_if_fail (member == NULL || 02814 _dbus_check_is_valid_member (member), 02815 FALSE); 02816 02817 return set_or_delete_string_field (message, 02818 DBUS_HEADER_FIELD_MEMBER, 02819 DBUS_TYPE_STRING, 02820 member); 02821 } 02822 02834 const char* 02835 dbus_message_get_member (DBusMessage *message) 02836 { 02837 const char *v; 02838 02839 _dbus_return_val_if_fail (message != NULL, NULL); 02840 02841 v = NULL; /* in case field doesn't exist */ 02842 _dbus_header_get_field_basic (&message->header, 02843 DBUS_HEADER_FIELD_MEMBER, 02844 DBUS_TYPE_STRING, 02845 &v); 02846 return v; 02847 } 02848 02856 dbus_bool_t 02857 dbus_message_has_member (DBusMessage *message, 02858 const char *member) 02859 { 02860 const char *msg_member; 02861 msg_member = dbus_message_get_member (message); 02862 02863 if (msg_member == NULL) 02864 { 02865 if (member == NULL) 02866 return TRUE; 02867 else 02868 return FALSE; 02869 } 02870 02871 if (member == NULL) 02872 return FALSE; 02873 02874 if (strcmp (msg_member, member) == 0) 02875 return TRUE; 02876 02877 return FALSE; 02878 02879 } 02880 02892 dbus_bool_t 02893 dbus_message_set_error_name (DBusMessage *message, 02894 const char *error_name) 02895 { 02896 _dbus_return_val_if_fail (message != NULL, FALSE); 02897 _dbus_return_val_if_fail (!message->locked, FALSE); 02898 _dbus_return_val_if_fail (error_name == NULL || 02899 _dbus_check_is_valid_error_name (error_name), 02900 FALSE); 02901 02902 return set_or_delete_string_field (message, 02903 DBUS_HEADER_FIELD_ERROR_NAME, 02904 DBUS_TYPE_STRING, 02905 error_name); 02906 } 02907 02918 const char* 02919 dbus_message_get_error_name (DBusMessage *message) 02920 { 02921 const char *v; 02922 02923 _dbus_return_val_if_fail (message != NULL, NULL); 02924 02925 v = NULL; /* in case field doesn't exist */ 02926 _dbus_header_get_field_basic (&message->header, 02927 DBUS_HEADER_FIELD_ERROR_NAME, 02928 DBUS_TYPE_STRING, 02929 &v); 02930 return v; 02931 } 02932 02946 dbus_bool_t 02947 dbus_message_set_destination (DBusMessage *message, 02948 const char *destination) 02949 { 02950 _dbus_return_val_if_fail (message != NULL, FALSE); 02951 _dbus_return_val_if_fail (!message->locked, FALSE); 02952 _dbus_return_val_if_fail (destination == NULL || 02953 _dbus_check_is_valid_bus_name (destination), 02954 FALSE); 02955 02956 return set_or_delete_string_field (message, 02957 DBUS_HEADER_FIELD_DESTINATION, 02958 DBUS_TYPE_STRING, 02959 destination); 02960 } 02961 02971 const char* 02972 dbus_message_get_destination (DBusMessage *message) 02973 { 02974 const char *v; 02975 02976 _dbus_return_val_if_fail (message != NULL, NULL); 02977 02978 v = NULL; /* in case field doesn't exist */ 02979 _dbus_header_get_field_basic (&message->header, 02980 DBUS_HEADER_FIELD_DESTINATION, 02981 DBUS_TYPE_STRING, 02982 &v); 02983 return v; 02984 } 02985 03000 dbus_bool_t 03001 dbus_message_set_sender (DBusMessage *message, 03002 const char *sender) 03003 { 03004 _dbus_return_val_if_fail (message != NULL, FALSE); 03005 _dbus_return_val_if_fail (!message->locked, FALSE); 03006 _dbus_return_val_if_fail (sender == NULL || 03007 _dbus_check_is_valid_bus_name (sender), 03008 FALSE); 03009 03010 return set_or_delete_string_field (message, 03011 DBUS_HEADER_FIELD_SENDER, 03012 DBUS_TYPE_STRING, 03013 sender); 03014 } 03015 03031 const char* 03032 dbus_message_get_sender (DBusMessage *message) 03033 { 03034 const char *v; 03035 03036 _dbus_return_val_if_fail (message != NULL, NULL); 03037 03038 v = NULL; /* in case field doesn't exist */ 03039 _dbus_header_get_field_basic (&message->header, 03040 DBUS_HEADER_FIELD_SENDER, 03041 DBUS_TYPE_STRING, 03042 &v); 03043 return v; 03044 } 03045 03064 const char* 03065 dbus_message_get_signature (DBusMessage *message) 03066 { 03067 const DBusString *type_str; 03068 int type_pos; 03069 03070 _dbus_return_val_if_fail (message != NULL, NULL); 03071 03072 get_const_signature (&message->header, &type_str, &type_pos); 03073 03074 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03075 } 03076 03077 static dbus_bool_t 03078 _dbus_message_has_type_interface_member (DBusMessage *message, 03079 int type, 03080 const char *interface, 03081 const char *member) 03082 { 03083 const char *n; 03084 03085 _dbus_assert (message != NULL); 03086 _dbus_assert (interface != NULL); 03087 _dbus_assert (member != NULL); 03088 03089 if (dbus_message_get_type (message) != type) 03090 return FALSE; 03091 03092 /* Optimize by checking the short member name first 03093 * instead of the longer interface name 03094 */ 03095 03096 n = dbus_message_get_member (message); 03097 03098 if (n && strcmp (n, member) == 0) 03099 { 03100 n = dbus_message_get_interface (message); 03101 03102 if (n == NULL || strcmp (n, interface) == 0) 03103 return TRUE; 03104 } 03105 03106 return FALSE; 03107 } 03108 03123 dbus_bool_t 03124 dbus_message_is_method_call (DBusMessage *message, 03125 const char *interface, 03126 const char *method) 03127 { 03128 _dbus_return_val_if_fail (message != NULL, FALSE); 03129 _dbus_return_val_if_fail (interface != NULL, FALSE); 03130 _dbus_return_val_if_fail (method != NULL, FALSE); 03131 /* don't check that interface/method are valid since it would be 03132 * expensive, and not catch many common errors 03133 */ 03134 03135 return _dbus_message_has_type_interface_member (message, 03136 DBUS_MESSAGE_TYPE_METHOD_CALL, 03137 interface, method); 03138 } 03139 03151 dbus_bool_t 03152 dbus_message_is_signal (DBusMessage *message, 03153 const char *interface, 03154 const char *signal_name) 03155 { 03156 _dbus_return_val_if_fail (message != NULL, FALSE); 03157 _dbus_return_val_if_fail (interface != NULL, FALSE); 03158 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03159 /* don't check that interface/name are valid since it would be 03160 * expensive, and not catch many common errors 03161 */ 03162 03163 return _dbus_message_has_type_interface_member (message, 03164 DBUS_MESSAGE_TYPE_SIGNAL, 03165 interface, signal_name); 03166 } 03167 03178 dbus_bool_t 03179 dbus_message_is_error (DBusMessage *message, 03180 const char *error_name) 03181 { 03182 const char *n; 03183 03184 _dbus_return_val_if_fail (message != NULL, FALSE); 03185 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03186 /* don't check that error_name is valid since it would be expensive, 03187 * and not catch many common errors 03188 */ 03189 03190 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03191 return FALSE; 03192 03193 n = dbus_message_get_error_name (message); 03194 03195 if (n && strcmp (n, error_name) == 0) 03196 return TRUE; 03197 else 03198 return FALSE; 03199 } 03200 03211 dbus_bool_t 03212 dbus_message_has_destination (DBusMessage *message, 03213 const char *name) 03214 { 03215 const char *s; 03216 03217 _dbus_return_val_if_fail (message != NULL, FALSE); 03218 _dbus_return_val_if_fail (name != NULL, FALSE); 03219 /* don't check that name is valid since it would be expensive, and 03220 * not catch many common errors 03221 */ 03222 03223 s = dbus_message_get_destination (message); 03224 03225 if (s && strcmp (s, name) == 0) 03226 return TRUE; 03227 else 03228 return FALSE; 03229 } 03230 03246 dbus_bool_t 03247 dbus_message_has_sender (DBusMessage *message, 03248 const char *name) 03249 { 03250 const char *s; 03251 03252 _dbus_return_val_if_fail (message != NULL, FALSE); 03253 _dbus_return_val_if_fail (name != NULL, FALSE); 03254 /* don't check that name is valid since it would be expensive, and 03255 * not catch many common errors 03256 */ 03257 03258 s = dbus_message_get_sender (message); 03259 03260 if (s && strcmp (s, name) == 0) 03261 return TRUE; 03262 else 03263 return FALSE; 03264 } 03265 03275 dbus_bool_t 03276 dbus_message_has_signature (DBusMessage *message, 03277 const char *signature) 03278 { 03279 const char *s; 03280 03281 _dbus_return_val_if_fail (message != NULL, FALSE); 03282 _dbus_return_val_if_fail (signature != NULL, FALSE); 03283 /* don't check that signature is valid since it would be expensive, 03284 * and not catch many common errors 03285 */ 03286 03287 s = dbus_message_get_signature (message); 03288 03289 if (s && strcmp (s, signature) == 0) 03290 return TRUE; 03291 else 03292 return FALSE; 03293 } 03294 03317 dbus_bool_t 03318 dbus_set_error_from_message (DBusError *error, 03319 DBusMessage *message) 03320 { 03321 const char *str; 03322 03323 _dbus_return_val_if_fail (message != NULL, FALSE); 03324 _dbus_return_val_if_error_is_set (error, FALSE); 03325 03326 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03327 return FALSE; 03328 03329 str = NULL; 03330 dbus_message_get_args (message, NULL, 03331 DBUS_TYPE_STRING, &str, 03332 DBUS_TYPE_INVALID); 03333 03334 dbus_set_error (error, dbus_message_get_error_name (message), 03335 str ? "%s" : NULL, str); 03336 03337 return TRUE; 03338 } 03339 03358 #define INITIAL_LOADER_DATA_LEN 32 03359 03366 DBusMessageLoader* 03367 _dbus_message_loader_new (void) 03368 { 03369 DBusMessageLoader *loader; 03370 03371 loader = dbus_new0 (DBusMessageLoader, 1); 03372 if (loader == NULL) 03373 return NULL; 03374 03375 loader->refcount = 1; 03376 03377 loader->corrupted = FALSE; 03378 loader->corruption_reason = DBUS_VALID; 03379 03380 /* this can be configured by the app, but defaults to the protocol max */ 03381 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03382 03383 if (!_dbus_string_init (&loader->data)) 03384 { 03385 dbus_free (loader); 03386 return NULL; 03387 } 03388 03389 /* preallocate the buffer for speed, ignore failure */ 03390 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03391 _dbus_string_set_length (&loader->data, 0); 03392 03393 return loader; 03394 } 03395 03402 DBusMessageLoader * 03403 _dbus_message_loader_ref (DBusMessageLoader *loader) 03404 { 03405 loader->refcount += 1; 03406 03407 return loader; 03408 } 03409 03416 void 03417 _dbus_message_loader_unref (DBusMessageLoader *loader) 03418 { 03419 loader->refcount -= 1; 03420 if (loader->refcount == 0) 03421 { 03422 _dbus_list_foreach (&loader->messages, 03423 (DBusForeachFunction) dbus_message_unref, 03424 NULL); 03425 _dbus_list_clear (&loader->messages); 03426 _dbus_string_free (&loader->data); 03427 dbus_free (loader); 03428 } 03429 } 03430 03449 void 03450 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 03451 DBusString **buffer) 03452 { 03453 _dbus_assert (!loader->buffer_outstanding); 03454 03455 *buffer = &loader->data; 03456 03457 loader->buffer_outstanding = TRUE; 03458 } 03459 03470 void 03471 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 03472 DBusString *buffer, 03473 int bytes_read) 03474 { 03475 _dbus_assert (loader->buffer_outstanding); 03476 _dbus_assert (buffer == &loader->data); 03477 03478 loader->buffer_outstanding = FALSE; 03479 } 03480 03481 /* 03482 * FIXME when we move the header out of the buffer, that memmoves all 03483 * buffered messages. Kind of crappy. 03484 * 03485 * Also we copy the header and body, which is kind of crappy. To 03486 * avoid this, we have to allow header and body to be in a single 03487 * memory block, which is good for messages we read and bad for 03488 * messages we are creating. But we could move_len() the buffer into 03489 * this single memory block, and move_len() will just swap the buffers 03490 * if you're moving the entire buffer replacing the dest string. 03491 * 03492 * We could also have the message loader tell the transport how many 03493 * bytes to read; so it would first ask for some arbitrary number like 03494 * 256, then if the message was incomplete it would use the 03495 * header/body len to ask for exactly the size of the message (or 03496 * blocks the size of a typical kernel buffer for the socket). That 03497 * way we don't get trailing bytes in the buffer that have to be 03498 * memmoved. Though I suppose we also don't have a chance of reading a 03499 * bunch of small messages at once, so the optimization may be stupid. 03500 * 03501 * Another approach would be to keep a "start" index into 03502 * loader->data and only delete it occasionally, instead of after 03503 * each message is loaded. 03504 * 03505 * load_message() returns FALSE if not enough memory OR the loader was corrupted 03506 */ 03507 static dbus_bool_t 03508 load_message (DBusMessageLoader *loader, 03509 DBusMessage *message, 03510 int byte_order, 03511 int fields_array_len, 03512 int header_len, 03513 int body_len) 03514 { 03515 dbus_bool_t oom; 03516 DBusValidity validity; 03517 const DBusString *type_str; 03518 int type_pos; 03519 DBusValidationMode mode; 03520 03521 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 03522 03523 oom = FALSE; 03524 03525 #if 0 03526 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 03527 #endif 03528 03529 /* 1. VALIDATE AND COPY OVER HEADER */ 03530 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 03531 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 03532 03533 if (!_dbus_header_load (&message->header, 03534 mode, 03535 &validity, 03536 byte_order, 03537 fields_array_len, 03538 header_len, 03539 body_len, 03540 &loader->data, 0, 03541 _dbus_string_get_length (&loader->data))) 03542 { 03543 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 03544 03545 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 03546 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 03547 _dbus_assert (validity != DBUS_VALID); 03548 03549 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 03550 oom = TRUE; 03551 else 03552 { 03553 loader->corrupted = TRUE; 03554 loader->corruption_reason = validity; 03555 } 03556 goto failed; 03557 } 03558 03559 _dbus_assert (validity == DBUS_VALID); 03560 03561 message->byte_order = byte_order; 03562 03563 /* 2. VALIDATE BODY */ 03564 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 03565 { 03566 get_const_signature (&message->header, &type_str, &type_pos); 03567 03568 /* Because the bytes_remaining arg is NULL, this validates that the 03569 * body is the right length 03570 */ 03571 validity = _dbus_validate_body_with_reason (type_str, 03572 type_pos, 03573 byte_order, 03574 NULL, 03575 &loader->data, 03576 header_len, 03577 body_len); 03578 if (validity != DBUS_VALID) 03579 { 03580 _dbus_verbose ("Failed to validate message body code %d\n", validity); 03581 03582 loader->corrupted = TRUE; 03583 loader->corruption_reason = validity; 03584 03585 goto failed; 03586 } 03587 } 03588 03589 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 03590 03591 if (!_dbus_list_append (&loader->messages, message)) 03592 { 03593 _dbus_verbose ("Failed to append new message to loader queue\n"); 03594 oom = TRUE; 03595 goto failed; 03596 } 03597 03598 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 03599 _dbus_assert (_dbus_string_get_length (&loader->data) >= 03600 (header_len + body_len)); 03601 03602 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 03603 { 03604 _dbus_verbose ("Failed to move body into new message\n"); 03605 oom = TRUE; 03606 goto failed; 03607 } 03608 03609 _dbus_string_delete (&loader->data, 0, header_len + body_len); 03610 03611 /* don't waste more than 2k of memory */ 03612 _dbus_string_compact (&loader->data, 2048); 03613 03614 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 03615 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 03616 03617 _dbus_verbose ("Loaded message %p\n", message); 03618 03619 _dbus_assert (!oom); 03620 _dbus_assert (!loader->corrupted); 03621 _dbus_assert (loader->messages != NULL); 03622 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 03623 03624 return TRUE; 03625 03626 failed: 03627 03628 /* Clean up */ 03629 03630 /* does nothing if the message isn't in the list */ 03631 _dbus_list_remove_last (&loader->messages, message); 03632 03633 if (oom) 03634 _dbus_assert (!loader->corrupted); 03635 else 03636 _dbus_assert (loader->corrupted); 03637 03638 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 03639 03640 return FALSE; 03641 } 03642 03657 dbus_bool_t 03658 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 03659 { 03660 while (!loader->corrupted && 03661 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 03662 { 03663 DBusValidity validity; 03664 int byte_order, fields_array_len, header_len, body_len; 03665 03666 if (_dbus_header_have_message_untrusted (loader->max_message_size, 03667 &validity, 03668 &byte_order, 03669 &fields_array_len, 03670 &header_len, 03671 &body_len, 03672 &loader->data, 0, 03673 _dbus_string_get_length (&loader->data))) 03674 { 03675 DBusMessage *message; 03676 03677 _dbus_assert (validity == DBUS_VALID); 03678 03679 message = dbus_message_new_empty_header (); 03680 if (message == NULL) 03681 return FALSE; 03682 03683 if (!load_message (loader, message, 03684 byte_order, fields_array_len, 03685 header_len, body_len)) 03686 { 03687 dbus_message_unref (message); 03688 /* load_message() returns false if corrupted or OOM; if 03689 * corrupted then return TRUE for not OOM 03690 */ 03691 return loader->corrupted; 03692 } 03693 03694 _dbus_assert (loader->messages != NULL); 03695 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 03696 } 03697 else 03698 { 03699 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 03700 validity); 03701 if (validity != DBUS_VALID) 03702 { 03703 loader->corrupted = TRUE; 03704 loader->corruption_reason = validity; 03705 } 03706 return TRUE; 03707 } 03708 } 03709 03710 return TRUE; 03711 } 03712 03720 DBusMessage* 03721 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 03722 { 03723 if (loader->messages) 03724 return loader->messages->data; 03725 else 03726 return NULL; 03727 } 03728 03737 DBusMessage* 03738 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 03739 { 03740 return _dbus_list_pop_first (&loader->messages); 03741 } 03742 03751 DBusList* 03752 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 03753 { 03754 return _dbus_list_pop_first_link (&loader->messages); 03755 } 03756 03763 void 03764 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 03765 DBusList *link) 03766 { 03767 _dbus_list_prepend_link (&loader->messages, link); 03768 } 03769 03779 dbus_bool_t 03780 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 03781 { 03782 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 03783 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 03784 return loader->corrupted; 03785 } 03786 03793 DBusValidity 03794 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 03795 { 03796 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 03797 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 03798 03799 return loader->corruption_reason; 03800 } 03801 03808 void 03809 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 03810 long size) 03811 { 03812 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 03813 { 03814 _dbus_verbose ("clamping requested max message size %ld to %d\n", 03815 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 03816 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03817 } 03818 loader->max_message_size = size; 03819 } 03820 03827 long 03828 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 03829 { 03830 return loader->max_message_size; 03831 } 03832 03833 static DBusDataSlotAllocator slot_allocator; 03834 _DBUS_DEFINE_GLOBAL_LOCK (message_slots); 03835 03850 dbus_bool_t 03851 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 03852 { 03853 return _dbus_data_slot_allocator_alloc (&slot_allocator, 03854 &_DBUS_LOCK_NAME (message_slots), 03855 slot_p); 03856 } 03857 03869 void 03870 dbus_message_free_data_slot (dbus_int32_t *slot_p) 03871 { 03872 _dbus_return_if_fail (*slot_p >= 0); 03873 03874 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 03875 } 03876 03890 dbus_bool_t 03891 dbus_message_set_data (DBusMessage *message, 03892 dbus_int32_t slot, 03893 void *data, 03894 DBusFreeFunction free_data_func) 03895 { 03896 DBusFreeFunction old_free_func; 03897 void *old_data; 03898 dbus_bool_t retval; 03899 03900 _dbus_return_val_if_fail (message != NULL, FALSE); 03901 _dbus_return_val_if_fail (slot >= 0, FALSE); 03902 03903 retval = _dbus_data_slot_list_set (&slot_allocator, 03904 &message->slot_list, 03905 slot, data, free_data_func, 03906 &old_free_func, &old_data); 03907 03908 if (retval) 03909 { 03910 /* Do the actual free outside the message lock */ 03911 if (old_free_func) 03912 (* old_free_func) (old_data); 03913 } 03914 03915 return retval; 03916 } 03917 03926 void* 03927 dbus_message_get_data (DBusMessage *message, 03928 dbus_int32_t slot) 03929 { 03930 void *res; 03931 03932 _dbus_return_val_if_fail (message != NULL, NULL); 03933 03934 res = _dbus_data_slot_list_get (&slot_allocator, 03935 &message->slot_list, 03936 slot); 03937 03938 return res; 03939 } 03940 03954 int 03955 dbus_message_type_from_string (const char *type_str) 03956 { 03957 if (strcmp (type_str, "method_call") == 0) 03958 return DBUS_MESSAGE_TYPE_METHOD_CALL; 03959 if (strcmp (type_str, "method_return") == 0) 03960 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 03961 else if (strcmp (type_str, "signal") == 0) 03962 return DBUS_MESSAGE_TYPE_SIGNAL; 03963 else if (strcmp (type_str, "error") == 0) 03964 return DBUS_MESSAGE_TYPE_ERROR; 03965 else 03966 return DBUS_MESSAGE_TYPE_INVALID; 03967 } 03968 03982 const char * 03983 dbus_message_type_to_string (int type) 03984 { 03985 switch (type) 03986 { 03987 case DBUS_MESSAGE_TYPE_METHOD_CALL: 03988 return "method_call"; 03989 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 03990 return "method_return"; 03991 case DBUS_MESSAGE_TYPE_SIGNAL: 03992 return "signal"; 03993 case DBUS_MESSAGE_TYPE_ERROR: 03994 return "error"; 03995 default: 03996 return "invalid"; 03997 } 03998 } 03999 04012 dbus_bool_t 04013 dbus_message_marshal (DBusMessage *msg, 04014 char **marshalled_data_p, 04015 int *len_p) 04016 { 04017 DBusString tmp; 04018 dbus_bool_t was_locked; 04019 04020 _dbus_return_val_if_fail (msg != NULL, FALSE); 04021 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04022 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04023 04024 if (!_dbus_string_init (&tmp)) 04025 return FALSE; 04026 04027 /* Ensure the message is locked, to ensure the length header is filled in. */ 04028 was_locked = msg->locked; 04029 04030 if (!was_locked) 04031 dbus_message_lock (msg); 04032 04033 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04034 goto fail; 04035 04036 *len_p = _dbus_string_get_length (&tmp); 04037 04038 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04039 goto fail; 04040 04041 *len_p = _dbus_string_get_length (&tmp); 04042 04043 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04044 goto fail; 04045 04046 _dbus_string_free (&tmp); 04047 04048 if (!was_locked) 04049 msg->locked = FALSE; 04050 04051 return TRUE; 04052 04053 fail: 04054 _dbus_string_free (&tmp); 04055 04056 if (!was_locked) 04057 msg->locked = FALSE; 04058 04059 return FALSE; 04060 } 04061 04074 DBusMessage * 04075 dbus_message_demarshal (const char *str, 04076 int len, 04077 DBusError *error) 04078 { 04079 DBusMessageLoader *loader; 04080 DBusString *buffer; 04081 DBusMessage *msg; 04082 04083 _dbus_return_val_if_fail (str != NULL, NULL); 04084 04085 loader = _dbus_message_loader_new (); 04086 04087 if (loader == NULL) 04088 return NULL; 04089 04090 _dbus_message_loader_get_buffer (loader, &buffer); 04091 _dbus_string_append_len (buffer, str, len); 04092 _dbus_message_loader_return_buffer (loader, buffer, len); 04093 04094 if (!_dbus_message_loader_queue_messages (loader)) 04095 goto fail_oom; 04096 04097 if (_dbus_message_loader_get_is_corrupted (loader)) 04098 goto fail_corrupt; 04099 04100 msg = _dbus_message_loader_pop_message (loader); 04101 04102 if (!msg) 04103 goto fail_oom; 04104 04105 _dbus_message_loader_unref (loader); 04106 return msg; 04107 04108 fail_corrupt: 04109 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04110 _dbus_validity_to_error_message (loader->corruption_reason)); 04111 _dbus_message_loader_unref (loader); 04112 return NULL; 04113 04114 fail_oom: 04115 _DBUS_SET_OOM (error); 04116 _dbus_message_loader_unref (loader); 04117 return NULL; 04118 } 04119 04133 int 04134 dbus_message_demarshal_bytes_needed(const char *buf, 04135 int len) 04136 { 04137 DBusString str; 04138 int byte_order, fields_array_len, header_len, body_len; 04139 DBusValidity validity = DBUS_VALID; 04140 int have_message; 04141 04142 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04143 return 0; 04144 04145 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04146 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04147 _dbus_string_init_const_len (&str, buf, len); 04148 04149 validity = DBUS_VALID; 04150 have_message 04151 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04152 &validity, &byte_order, 04153 &fields_array_len, 04154 &header_len, 04155 &body_len, 04156 &str, 0, 04157 len); 04158 _dbus_string_free (&str); 04159 04160 if (validity == DBUS_VALID) 04161 { 04162 _dbus_assert(have_message); 04163 return header_len + body_len; 04164 } 04165 else 04166 { 04167 return -1; /* broken! */ 04168 } 04169 } 04170 04173 /* tests in dbus-message-util.c */