D-Bus
1.4.10
|
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 <config.h> 00026 #include "dbus-internals.h" 00027 #include "dbus-marshal-recursive.h" 00028 #include "dbus-marshal-validate.h" 00029 #include "dbus-marshal-byteswap.h" 00030 #include "dbus-marshal-header.h" 00031 #include "dbus-signature.h" 00032 #include "dbus-message-private.h" 00033 #include "dbus-object-tree.h" 00034 #include "dbus-memory.h" 00035 #include "dbus-list.h" 00036 #include "dbus-threads-internal.h" 00037 #ifdef HAVE_UNIX_FD_PASSING 00038 #include "dbus-sysdeps-unix.h" 00039 #endif 00040 00041 #include <string.h> 00042 00043 static void dbus_message_finalize (DBusMessage *message); 00044 00055 /* Not thread locked, but strictly const/read-only so should be OK 00056 */ 00058 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, ""); 00059 00060 /* these have wacky values to help trap uninitialized iterators; 00061 * but has to fit in 3 bits 00062 */ 00063 enum { 00064 DBUS_MESSAGE_ITER_TYPE_READER = 3, 00065 DBUS_MESSAGE_ITER_TYPE_WRITER = 7 00066 }; 00067 00069 typedef struct DBusMessageRealIter DBusMessageRealIter; 00070 00076 struct DBusMessageRealIter 00077 { 00078 DBusMessage *message; 00079 dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 00080 dbus_uint32_t iter_type : 3; 00081 dbus_uint32_t sig_refcount : 8; 00082 union 00083 { 00084 DBusTypeWriter writer; 00085 DBusTypeReader reader; 00086 } u; 00087 }; 00088 00089 static void 00090 get_const_signature (DBusHeader *header, 00091 const DBusString **type_str_p, 00092 int *type_pos_p) 00093 { 00094 if (_dbus_header_get_field_raw (header, 00095 DBUS_HEADER_FIELD_SIGNATURE, 00096 type_str_p, 00097 type_pos_p)) 00098 { 00099 *type_pos_p += 1; /* skip the signature length which is 1 byte */ 00100 } 00101 else 00102 { 00103 *type_str_p = &_dbus_empty_signature_str; 00104 *type_pos_p = 0; 00105 } 00106 } 00107 00113 static void 00114 _dbus_message_byteswap (DBusMessage *message) 00115 { 00116 const DBusString *type_str; 00117 int type_pos; 00118 00119 if (message->byte_order == DBUS_COMPILER_BYTE_ORDER) 00120 return; 00121 00122 _dbus_verbose ("Swapping message into compiler byte order\n"); 00123 00124 get_const_signature (&message->header, &type_str, &type_pos); 00125 00126 _dbus_marshal_byteswap (type_str, type_pos, 00127 message->byte_order, 00128 DBUS_COMPILER_BYTE_ORDER, 00129 &message->body, 0); 00130 00131 message->byte_order = DBUS_COMPILER_BYTE_ORDER; 00132 00133 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER); 00134 } 00135 00142 #define ensure_byte_order(message) \ 00143 if (message->byte_order != DBUS_COMPILER_BYTE_ORDER) \ 00144 _dbus_message_byteswap (message) 00145 00156 void 00157 _dbus_message_get_network_data (DBusMessage *message, 00158 const DBusString **header, 00159 const DBusString **body) 00160 { 00161 _dbus_assert (message->locked); 00162 00163 *header = &message->header.data; 00164 *body = &message->body; 00165 } 00166 00176 void _dbus_message_get_unix_fds(DBusMessage *message, 00177 const int **fds, 00178 unsigned *n_fds) 00179 { 00180 _dbus_assert (message->locked); 00181 00182 #ifdef HAVE_UNIX_FD_PASSING 00183 *fds = message->unix_fds; 00184 *n_fds = message->n_unix_fds; 00185 #else 00186 *fds = NULL; 00187 *n_fds = 0; 00188 #endif 00189 } 00190 00202 void 00203 dbus_message_set_serial (DBusMessage *message, 00204 dbus_uint32_t serial) 00205 { 00206 _dbus_return_if_fail (message != NULL); 00207 _dbus_return_if_fail (!message->locked); 00208 00209 _dbus_header_set_serial (&message->header, serial); 00210 } 00211 00223 void 00224 _dbus_message_add_counter_link (DBusMessage *message, 00225 DBusList *link) 00226 { 00227 /* right now we don't recompute the delta when message 00228 * size changes, and that's OK for current purposes 00229 * I think, but could be important to change later. 00230 * Do recompute it whenever there are no outstanding counters, 00231 * since it's basically free. 00232 */ 00233 if (message->counters == NULL) 00234 { 00235 message->size_counter_delta = 00236 _dbus_string_get_length (&message->header.data) + 00237 _dbus_string_get_length (&message->body); 00238 00239 #ifdef HAVE_UNIX_FD_PASSING 00240 message->unix_fd_counter_delta = message->n_unix_fds; 00241 #endif 00242 00243 #if 0 00244 _dbus_verbose ("message has size %ld\n", 00245 message->size_counter_delta); 00246 #endif 00247 } 00248 00249 _dbus_list_append_link (&message->counters, link); 00250 00251 _dbus_counter_adjust_size (link->data, message->size_counter_delta); 00252 00253 #ifdef HAVE_UNIX_FD_PASSING 00254 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta); 00255 #endif 00256 } 00257 00267 dbus_bool_t 00268 _dbus_message_add_counter (DBusMessage *message, 00269 DBusCounter *counter) 00270 { 00271 DBusList *link; 00272 00273 link = _dbus_list_alloc_link (counter); 00274 if (link == NULL) 00275 return FALSE; 00276 00277 _dbus_counter_ref (counter); 00278 _dbus_message_add_counter_link (message, link); 00279 00280 return TRUE; 00281 } 00282 00291 void 00292 _dbus_message_remove_counter (DBusMessage *message, 00293 DBusCounter *counter, 00294 DBusList **link_return) 00295 { 00296 DBusList *link; 00297 00298 link = _dbus_list_find_last (&message->counters, 00299 counter); 00300 _dbus_assert (link != NULL); 00301 00302 _dbus_list_unlink (&message->counters, 00303 link); 00304 if (link_return) 00305 *link_return = link; 00306 else 00307 _dbus_list_free_link (link); 00308 00309 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00310 00311 #ifdef HAVE_UNIX_FD_PASSING 00312 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00313 #endif 00314 00315 _dbus_counter_unref (counter); 00316 } 00317 00328 void 00329 dbus_message_lock (DBusMessage *message) 00330 { 00331 if (!message->locked) 00332 { 00333 _dbus_header_update_lengths (&message->header, 00334 _dbus_string_get_length (&message->body)); 00335 00336 /* must have a signature if you have a body */ 00337 _dbus_assert (_dbus_string_get_length (&message->body) == 0 || 00338 dbus_message_get_signature (message) != NULL); 00339 00340 message->locked = TRUE; 00341 } 00342 } 00343 00344 static dbus_bool_t 00345 set_or_delete_string_field (DBusMessage *message, 00346 int field, 00347 int typecode, 00348 const char *value) 00349 { 00350 if (value == NULL) 00351 return _dbus_header_delete_field (&message->header, field); 00352 else 00353 return _dbus_header_set_field_basic (&message->header, 00354 field, 00355 typecode, 00356 &value); 00357 } 00358 00359 #if 0 00360 /* Probably we don't need to use this */ 00384 static dbus_bool_t 00385 _dbus_message_set_signature (DBusMessage *message, 00386 const char *signature) 00387 { 00388 _dbus_return_val_if_fail (message != NULL, FALSE); 00389 _dbus_return_val_if_fail (!message->locked, FALSE); 00390 _dbus_return_val_if_fail (signature == NULL || 00391 _dbus_check_is_valid_signature (signature)); 00392 /* can't delete the signature if you have a message body */ 00393 _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || 00394 signature != NULL); 00395 00396 return set_or_delete_string_field (message, 00397 DBUS_HEADER_FIELD_SIGNATURE, 00398 DBUS_TYPE_SIGNATURE, 00399 signature); 00400 } 00401 #endif 00402 00403 /* Message Cache 00404 * 00405 * We cache some DBusMessage to reduce the overhead of allocating 00406 * them. In my profiling this consistently made about an 8% 00407 * difference. It avoids the malloc for the message, the malloc for 00408 * the slot list, the malloc for the header string and body string, 00409 * and the associated free() calls. It does introduce another global 00410 * lock which could be a performance issue in certain cases. 00411 * 00412 * For the echo client/server the round trip time goes from around 00413 * .000077 to .000069 with the message cache on my laptop. The sysprof 00414 * change is as follows (numbers are cumulative percentage): 00415 * 00416 * with message cache implemented as array as it is now (0.000069 per): 00417 * new_empty_header 1.46 00418 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache) 00419 * mutex_unlock 0.25 00420 * self 0.41 00421 * unref 2.24 00422 * self 0.68 00423 * list_clear 0.43 00424 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache) 00425 * mutex_unlock 0.25 00426 * 00427 * with message cache implemented as list (0.000070 per roundtrip): 00428 * new_empty_header 2.72 00429 * list_pop_first 1.88 00430 * unref 3.3 00431 * list_prepend 1.63 00432 * 00433 * without cache (0.000077 per roundtrip): 00434 * new_empty_header 6.7 00435 * string_init_preallocated 3.43 00436 * dbus_malloc 2.43 00437 * dbus_malloc0 2.59 00438 * 00439 * unref 4.02 00440 * string_free 1.82 00441 * dbus_free 1.63 00442 * dbus_free 0.71 00443 * 00444 * If you implement the message_cache with a list, the primary reason 00445 * it's slower is that you add another thread lock (on the DBusList 00446 * mempool). 00447 */ 00448 00450 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE 00451 00453 #define MAX_MESSAGE_CACHE_SIZE 5 00454 00455 _DBUS_DEFINE_GLOBAL_LOCK (message_cache); 00456 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; 00457 static int message_cache_count = 0; 00458 static dbus_bool_t message_cache_shutdown_registered = FALSE; 00459 00460 static void 00461 dbus_message_cache_shutdown (void *data) 00462 { 00463 int i; 00464 00465 _DBUS_LOCK (message_cache); 00466 00467 i = 0; 00468 while (i < MAX_MESSAGE_CACHE_SIZE) 00469 { 00470 if (message_cache[i]) 00471 dbus_message_finalize (message_cache[i]); 00472 00473 ++i; 00474 } 00475 00476 message_cache_count = 0; 00477 message_cache_shutdown_registered = FALSE; 00478 00479 _DBUS_UNLOCK (message_cache); 00480 } 00481 00489 static DBusMessage* 00490 dbus_message_get_cached (void) 00491 { 00492 DBusMessage *message; 00493 int i; 00494 00495 message = NULL; 00496 00497 _DBUS_LOCK (message_cache); 00498 00499 _dbus_assert (message_cache_count >= 0); 00500 00501 if (message_cache_count == 0) 00502 { 00503 _DBUS_UNLOCK (message_cache); 00504 return NULL; 00505 } 00506 00507 /* This is not necessarily true unless count > 0, and 00508 * message_cache is uninitialized until the shutdown is 00509 * registered 00510 */ 00511 _dbus_assert (message_cache_shutdown_registered); 00512 00513 i = 0; 00514 while (i < MAX_MESSAGE_CACHE_SIZE) 00515 { 00516 if (message_cache[i]) 00517 { 00518 message = message_cache[i]; 00519 message_cache[i] = NULL; 00520 message_cache_count -= 1; 00521 break; 00522 } 00523 ++i; 00524 } 00525 _dbus_assert (message_cache_count >= 0); 00526 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00527 _dbus_assert (message != NULL); 00528 00529 _dbus_assert (message->refcount.value == 0); 00530 _dbus_assert (message->counters == NULL); 00531 00532 _DBUS_UNLOCK (message_cache); 00533 00534 return message; 00535 } 00536 00537 #ifdef HAVE_UNIX_FD_PASSING 00538 static void 00539 close_unix_fds(int *fds, unsigned *n_fds) 00540 { 00541 DBusError e; 00542 int i; 00543 00544 if (*n_fds <= 0) 00545 return; 00546 00547 dbus_error_init(&e); 00548 00549 for (i = 0; i < *n_fds; i++) 00550 { 00551 if (!_dbus_close(fds[i], &e)) 00552 { 00553 _dbus_warn("Failed to close file descriptor: %s\n", e.message); 00554 dbus_error_free(&e); 00555 } 00556 } 00557 00558 *n_fds = 0; 00559 00560 /* We don't free the array here, in case we can recycle it later */ 00561 } 00562 #endif 00563 00564 static void 00565 free_counter (void *element, 00566 void *data) 00567 { 00568 DBusCounter *counter = element; 00569 DBusMessage *message = data; 00570 00571 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00572 #ifdef HAVE_UNIX_FD_PASSING 00573 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00574 #endif 00575 00576 _dbus_counter_unref (counter); 00577 } 00578 00584 static void 00585 dbus_message_cache_or_finalize (DBusMessage *message) 00586 { 00587 dbus_bool_t was_cached; 00588 int i; 00589 00590 _dbus_assert (message->refcount.value == 0); 00591 00592 /* This calls application code and has to be done first thing 00593 * without holding the lock 00594 */ 00595 _dbus_data_slot_list_clear (&message->slot_list); 00596 00597 _dbus_list_foreach (&message->counters, 00598 free_counter, message); 00599 _dbus_list_clear (&message->counters); 00600 00601 #ifdef HAVE_UNIX_FD_PASSING 00602 close_unix_fds(message->unix_fds, &message->n_unix_fds); 00603 #endif 00604 00605 was_cached = FALSE; 00606 00607 _DBUS_LOCK (message_cache); 00608 00609 if (!message_cache_shutdown_registered) 00610 { 00611 _dbus_assert (message_cache_count == 0); 00612 00613 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL)) 00614 goto out; 00615 00616 i = 0; 00617 while (i < MAX_MESSAGE_CACHE_SIZE) 00618 { 00619 message_cache[i] = NULL; 00620 ++i; 00621 } 00622 00623 message_cache_shutdown_registered = TRUE; 00624 } 00625 00626 _dbus_assert (message_cache_count >= 0); 00627 00628 if ((_dbus_string_get_length (&message->header.data) + 00629 _dbus_string_get_length (&message->body)) > 00630 MAX_MESSAGE_SIZE_TO_CACHE) 00631 goto out; 00632 00633 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE) 00634 goto out; 00635 00636 /* Find empty slot */ 00637 i = 0; 00638 while (message_cache[i] != NULL) 00639 ++i; 00640 00641 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00642 00643 _dbus_assert (message_cache[i] == NULL); 00644 message_cache[i] = message; 00645 message_cache_count += 1; 00646 was_cached = TRUE; 00647 #ifndef DBUS_DISABLE_CHECKS 00648 message->in_cache = TRUE; 00649 #endif 00650 00651 out: 00652 _dbus_assert (message->refcount.value == 0); 00653 00654 _DBUS_UNLOCK (message_cache); 00655 00656 if (!was_cached) 00657 dbus_message_finalize (message); 00658 } 00659 00660 #ifndef DBUS_DISABLE_CHECKS 00661 static dbus_bool_t 00662 _dbus_message_iter_check (DBusMessageRealIter *iter) 00663 { 00664 if (iter == NULL) 00665 { 00666 _dbus_warn_check_failed ("dbus message iterator is NULL\n"); 00667 return FALSE; 00668 } 00669 00670 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER) 00671 { 00672 if (iter->u.reader.byte_order != iter->message->byte_order) 00673 { 00674 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n"); 00675 return FALSE; 00676 } 00677 /* because we swap the message into compiler order when you init an iter */ 00678 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); 00679 } 00680 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) 00681 { 00682 if (iter->u.writer.byte_order != iter->message->byte_order) 00683 { 00684 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n"); 00685 return FALSE; 00686 } 00687 /* because we swap the message into compiler order when you init an iter */ 00688 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); 00689 } 00690 else 00691 { 00692 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n"); 00693 return FALSE; 00694 } 00695 00696 if (iter->changed_stamp != iter->message->changed_stamp) 00697 { 00698 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); 00699 return FALSE; 00700 } 00701 00702 return TRUE; 00703 } 00704 #endif /* DBUS_DISABLE_CHECKS */ 00705 00720 dbus_bool_t 00721 _dbus_message_iter_get_args_valist (DBusMessageIter *iter, 00722 DBusError *error, 00723 int first_arg_type, 00724 va_list var_args) 00725 { 00726 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 00727 int spec_type, msg_type, i; 00728 dbus_bool_t retval; 00729 00730 _dbus_assert (_dbus_message_iter_check (real)); 00731 00732 retval = FALSE; 00733 00734 spec_type = first_arg_type; 00735 i = 0; 00736 00737 while (spec_type != DBUS_TYPE_INVALID) 00738 { 00739 msg_type = dbus_message_iter_get_arg_type (iter); 00740 00741 if (msg_type != spec_type) 00742 { 00743 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00744 "Argument %d is specified to be of type \"%s\", but " 00745 "is actually of type \"%s\"\n", i, 00746 _dbus_type_to_string (spec_type), 00747 _dbus_type_to_string (msg_type)); 00748 00749 goto out; 00750 } 00751 00752 if (spec_type == DBUS_TYPE_UNIX_FD) 00753 { 00754 #ifdef HAVE_UNIX_FD_PASSING 00755 DBusBasicValue idx; 00756 int *pfd, nfd; 00757 00758 pfd = va_arg (var_args, int*); 00759 _dbus_assert(pfd); 00760 00761 _dbus_type_reader_read_basic(&real->u.reader, &idx); 00762 00763 if (idx.u32 >= real->message->n_unix_fds) 00764 { 00765 dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE, 00766 "Message refers to file descriptor at index %i," 00767 "but has only %i descriptors attached.\n", 00768 idx.u32, 00769 real->message->n_unix_fds); 00770 goto out; 00771 } 00772 00773 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0) 00774 goto out; 00775 00776 *pfd = nfd; 00777 #else 00778 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00779 "Platform does not support file desciptor passing.\n"); 00780 goto out; 00781 #endif 00782 } 00783 else if (dbus_type_is_basic (spec_type)) 00784 { 00785 DBusBasicValue *ptr; 00786 00787 ptr = va_arg (var_args, DBusBasicValue*); 00788 00789 _dbus_assert (ptr != NULL); 00790 00791 _dbus_type_reader_read_basic (&real->u.reader, 00792 ptr); 00793 } 00794 else if (spec_type == DBUS_TYPE_ARRAY) 00795 { 00796 int element_type; 00797 int spec_element_type; 00798 const DBusBasicValue **ptr; 00799 int *n_elements_p; 00800 DBusTypeReader array; 00801 00802 spec_element_type = va_arg (var_args, int); 00803 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 00804 00805 if (spec_element_type != element_type) 00806 { 00807 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00808 "Argument %d is specified to be an array of \"%s\", but " 00809 "is actually an array of \"%s\"\n", 00810 i, 00811 _dbus_type_to_string (spec_element_type), 00812 _dbus_type_to_string (element_type)); 00813 00814 goto out; 00815 } 00816 00817 if (dbus_type_is_fixed (spec_element_type) && 00818 element_type != DBUS_TYPE_UNIX_FD) 00819 { 00820 ptr = va_arg (var_args, const DBusBasicValue**); 00821 n_elements_p = va_arg (var_args, int*); 00822 00823 _dbus_assert (ptr != NULL); 00824 _dbus_assert (n_elements_p != NULL); 00825 00826 _dbus_type_reader_recurse (&real->u.reader, &array); 00827 00828 _dbus_type_reader_read_fixed_multi (&array, 00829 (void *) ptr, n_elements_p); 00830 } 00831 else if (spec_element_type == DBUS_TYPE_STRING || 00832 spec_element_type == DBUS_TYPE_SIGNATURE || 00833 spec_element_type == DBUS_TYPE_OBJECT_PATH) 00834 { 00835 char ***str_array_p; 00836 int n_elements; 00837 char **str_array; 00838 00839 str_array_p = va_arg (var_args, char***); 00840 n_elements_p = va_arg (var_args, int*); 00841 00842 _dbus_assert (str_array_p != NULL); 00843 _dbus_assert (n_elements_p != NULL); 00844 00845 /* Count elements in the array */ 00846 _dbus_type_reader_recurse (&real->u.reader, &array); 00847 00848 n_elements = 0; 00849 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 00850 { 00851 ++n_elements; 00852 _dbus_type_reader_next (&array); 00853 } 00854 00855 str_array = dbus_new0 (char*, n_elements + 1); 00856 if (str_array == NULL) 00857 { 00858 _DBUS_SET_OOM (error); 00859 goto out; 00860 } 00861 00862 /* Now go through and dup each string */ 00863 _dbus_type_reader_recurse (&real->u.reader, &array); 00864 00865 i = 0; 00866 while (i < n_elements) 00867 { 00868 const char *s; 00869 _dbus_type_reader_read_basic (&array, 00870 (void *) &s); 00871 00872 str_array[i] = _dbus_strdup (s); 00873 if (str_array[i] == NULL) 00874 { 00875 dbus_free_string_array (str_array); 00876 _DBUS_SET_OOM (error); 00877 goto out; 00878 } 00879 00880 ++i; 00881 00882 if (!_dbus_type_reader_next (&array)) 00883 _dbus_assert (i == n_elements); 00884 } 00885 00886 _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); 00887 _dbus_assert (i == n_elements); 00888 _dbus_assert (str_array[i] == NULL); 00889 00890 *str_array_p = str_array; 00891 *n_elements_p = n_elements; 00892 } 00893 #ifndef DBUS_DISABLE_CHECKS 00894 else 00895 { 00896 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", 00897 _DBUS_FUNCTION_NAME); 00898 goto out; 00899 } 00900 #endif 00901 } 00902 #ifndef DBUS_DISABLE_CHECKS 00903 else 00904 { 00905 _dbus_warn ("you can only read arrays and basic types with %s for now\n", 00906 _DBUS_FUNCTION_NAME); 00907 goto out; 00908 } 00909 #endif 00910 00911 spec_type = va_arg (var_args, int); 00912 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) 00913 { 00914 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00915 "Message has only %d arguments, but more were expected", i); 00916 goto out; 00917 } 00918 00919 i++; 00920 } 00921 00922 retval = TRUE; 00923 00924 out: 00925 00926 return retval; 00927 } 00928 00987 dbus_uint32_t 00988 dbus_message_get_serial (DBusMessage *message) 00989 { 00990 _dbus_return_val_if_fail (message != NULL, 0); 00991 00992 return _dbus_header_get_serial (&message->header); 00993 } 00994 01003 dbus_bool_t 01004 dbus_message_set_reply_serial (DBusMessage *message, 01005 dbus_uint32_t reply_serial) 01006 { 01007 _dbus_return_val_if_fail (message != NULL, FALSE); 01008 _dbus_return_val_if_fail (!message->locked, FALSE); 01009 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */ 01010 01011 return _dbus_header_set_field_basic (&message->header, 01012 DBUS_HEADER_FIELD_REPLY_SERIAL, 01013 DBUS_TYPE_UINT32, 01014 &reply_serial); 01015 } 01016 01023 dbus_uint32_t 01024 dbus_message_get_reply_serial (DBusMessage *message) 01025 { 01026 dbus_uint32_t v_UINT32; 01027 01028 _dbus_return_val_if_fail (message != NULL, 0); 01029 01030 if (_dbus_header_get_field_basic (&message->header, 01031 DBUS_HEADER_FIELD_REPLY_SERIAL, 01032 DBUS_TYPE_UINT32, 01033 &v_UINT32)) 01034 return v_UINT32; 01035 else 01036 return 0; 01037 } 01038 01039 static void 01040 dbus_message_finalize (DBusMessage *message) 01041 { 01042 _dbus_assert (message->refcount.value == 0); 01043 01044 /* This calls application callbacks! */ 01045 _dbus_data_slot_list_free (&message->slot_list); 01046 01047 _dbus_list_foreach (&message->counters, 01048 free_counter, message); 01049 _dbus_list_clear (&message->counters); 01050 01051 _dbus_header_free (&message->header); 01052 _dbus_string_free (&message->body); 01053 01054 #ifdef HAVE_UNIX_FD_PASSING 01055 close_unix_fds(message->unix_fds, &message->n_unix_fds); 01056 dbus_free(message->unix_fds); 01057 #endif 01058 01059 _dbus_assert (message->refcount.value == 0); 01060 01061 dbus_free (message); 01062 } 01063 01064 static DBusMessage* 01065 dbus_message_new_empty_header (void) 01066 { 01067 DBusMessage *message; 01068 dbus_bool_t from_cache; 01069 01070 message = dbus_message_get_cached (); 01071 01072 if (message != NULL) 01073 { 01074 from_cache = TRUE; 01075 } 01076 else 01077 { 01078 from_cache = FALSE; 01079 message = dbus_new (DBusMessage, 1); 01080 if (message == NULL) 01081 return NULL; 01082 #ifndef DBUS_DISABLE_CHECKS 01083 message->generation = _dbus_current_generation; 01084 #endif 01085 01086 #ifdef HAVE_UNIX_FD_PASSING 01087 message->unix_fds = NULL; 01088 message->n_unix_fds_allocated = 0; 01089 #endif 01090 } 01091 01092 message->refcount.value = 1; 01093 message->byte_order = DBUS_COMPILER_BYTE_ORDER; 01094 message->locked = FALSE; 01095 #ifndef DBUS_DISABLE_CHECKS 01096 message->in_cache = FALSE; 01097 #endif 01098 message->counters = NULL; 01099 message->size_counter_delta = 0; 01100 message->changed_stamp = 0; 01101 01102 #ifdef HAVE_UNIX_FD_PASSING 01103 message->n_unix_fds = 0; 01104 message->n_unix_fds_allocated = 0; 01105 message->unix_fd_counter_delta = 0; 01106 #endif 01107 01108 if (!from_cache) 01109 _dbus_data_slot_list_init (&message->slot_list); 01110 01111 if (from_cache) 01112 { 01113 _dbus_header_reinit (&message->header, message->byte_order); 01114 _dbus_string_set_length (&message->body, 0); 01115 } 01116 else 01117 { 01118 if (!_dbus_header_init (&message->header, message->byte_order)) 01119 { 01120 dbus_free (message); 01121 return NULL; 01122 } 01123 01124 if (!_dbus_string_init_preallocated (&message->body, 32)) 01125 { 01126 _dbus_header_free (&message->header); 01127 dbus_free (message); 01128 return NULL; 01129 } 01130 } 01131 01132 return message; 01133 } 01134 01147 DBusMessage* 01148 dbus_message_new (int message_type) 01149 { 01150 DBusMessage *message; 01151 01152 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL); 01153 01154 message = dbus_message_new_empty_header (); 01155 if (message == NULL) 01156 return NULL; 01157 01158 if (!_dbus_header_create (&message->header, 01159 message_type, 01160 NULL, NULL, NULL, NULL, NULL)) 01161 { 01162 dbus_message_unref (message); 01163 return NULL; 01164 } 01165 01166 return message; 01167 } 01168 01190 DBusMessage* 01191 dbus_message_new_method_call (const char *destination, 01192 const char *path, 01193 const char *interface, 01194 const char *method) 01195 { 01196 DBusMessage *message; 01197 01198 _dbus_return_val_if_fail (path != NULL, NULL); 01199 _dbus_return_val_if_fail (method != NULL, NULL); 01200 _dbus_return_val_if_fail (destination == NULL || 01201 _dbus_check_is_valid_bus_name (destination), NULL); 01202 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01203 _dbus_return_val_if_fail (interface == NULL || 01204 _dbus_check_is_valid_interface (interface), NULL); 01205 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); 01206 01207 message = dbus_message_new_empty_header (); 01208 if (message == NULL) 01209 return NULL; 01210 01211 if (!_dbus_header_create (&message->header, 01212 DBUS_MESSAGE_TYPE_METHOD_CALL, 01213 destination, path, interface, method, NULL)) 01214 { 01215 dbus_message_unref (message); 01216 return NULL; 01217 } 01218 01219 return message; 01220 } 01221 01229 DBusMessage* 01230 dbus_message_new_method_return (DBusMessage *method_call) 01231 { 01232 DBusMessage *message; 01233 const char *sender; 01234 01235 _dbus_return_val_if_fail (method_call != NULL, NULL); 01236 01237 sender = dbus_message_get_sender (method_call); 01238 01239 /* sender is allowed to be null here in peer-to-peer case */ 01240 01241 message = dbus_message_new_empty_header (); 01242 if (message == NULL) 01243 return NULL; 01244 01245 if (!_dbus_header_create (&message->header, 01246 DBUS_MESSAGE_TYPE_METHOD_RETURN, 01247 sender, NULL, NULL, NULL, NULL)) 01248 { 01249 dbus_message_unref (message); 01250 return NULL; 01251 } 01252 01253 dbus_message_set_no_reply (message, TRUE); 01254 01255 if (!dbus_message_set_reply_serial (message, 01256 dbus_message_get_serial (method_call))) 01257 { 01258 dbus_message_unref (message); 01259 return NULL; 01260 } 01261 01262 return message; 01263 } 01264 01279 DBusMessage* 01280 dbus_message_new_signal (const char *path, 01281 const char *interface, 01282 const char *name) 01283 { 01284 DBusMessage *message; 01285 01286 _dbus_return_val_if_fail (path != NULL, NULL); 01287 _dbus_return_val_if_fail (interface != NULL, NULL); 01288 _dbus_return_val_if_fail (name != NULL, NULL); 01289 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01290 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL); 01291 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); 01292 01293 message = dbus_message_new_empty_header (); 01294 if (message == NULL) 01295 return NULL; 01296 01297 if (!_dbus_header_create (&message->header, 01298 DBUS_MESSAGE_TYPE_SIGNAL, 01299 NULL, path, interface, name, NULL)) 01300 { 01301 dbus_message_unref (message); 01302 return NULL; 01303 } 01304 01305 dbus_message_set_no_reply (message, TRUE); 01306 01307 return message; 01308 } 01309 01324 DBusMessage* 01325 dbus_message_new_error (DBusMessage *reply_to, 01326 const char *error_name, 01327 const char *error_message) 01328 { 01329 DBusMessage *message; 01330 const char *sender; 01331 DBusMessageIter iter; 01332 01333 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01334 _dbus_return_val_if_fail (error_name != NULL, NULL); 01335 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01336 01337 sender = dbus_message_get_sender (reply_to); 01338 01339 /* sender may be NULL for non-message-bus case or 01340 * when the message bus is dealing with an unregistered 01341 * connection. 01342 */ 01343 message = dbus_message_new_empty_header (); 01344 if (message == NULL) 01345 return NULL; 01346 01347 if (!_dbus_header_create (&message->header, 01348 DBUS_MESSAGE_TYPE_ERROR, 01349 sender, NULL, NULL, NULL, error_name)) 01350 { 01351 dbus_message_unref (message); 01352 return NULL; 01353 } 01354 01355 dbus_message_set_no_reply (message, TRUE); 01356 01357 if (!dbus_message_set_reply_serial (message, 01358 dbus_message_get_serial (reply_to))) 01359 { 01360 dbus_message_unref (message); 01361 return NULL; 01362 } 01363 01364 if (error_message != NULL) 01365 { 01366 dbus_message_iter_init_append (message, &iter); 01367 if (!dbus_message_iter_append_basic (&iter, 01368 DBUS_TYPE_STRING, 01369 &error_message)) 01370 { 01371 dbus_message_unref (message); 01372 return NULL; 01373 } 01374 } 01375 01376 return message; 01377 } 01378 01395 DBusMessage* 01396 dbus_message_new_error_printf (DBusMessage *reply_to, 01397 const char *error_name, 01398 const char *error_format, 01399 ...) 01400 { 01401 va_list args; 01402 DBusString str; 01403 DBusMessage *message; 01404 01405 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01406 _dbus_return_val_if_fail (error_name != NULL, NULL); 01407 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01408 01409 if (!_dbus_string_init (&str)) 01410 return NULL; 01411 01412 va_start (args, error_format); 01413 01414 if (_dbus_string_append_printf_valist (&str, error_format, args)) 01415 message = dbus_message_new_error (reply_to, error_name, 01416 _dbus_string_get_const_data (&str)); 01417 else 01418 message = NULL; 01419 01420 _dbus_string_free (&str); 01421 01422 va_end (args); 01423 01424 return message; 01425 } 01426 01427 01440 DBusMessage * 01441 dbus_message_copy (const DBusMessage *message) 01442 { 01443 DBusMessage *retval; 01444 01445 _dbus_return_val_if_fail (message != NULL, NULL); 01446 01447 retval = dbus_new0 (DBusMessage, 1); 01448 if (retval == NULL) 01449 return NULL; 01450 01451 retval->refcount.value = 1; 01452 retval->byte_order = message->byte_order; 01453 retval->locked = FALSE; 01454 #ifndef DBUS_DISABLE_CHECKS 01455 retval->generation = message->generation; 01456 #endif 01457 01458 if (!_dbus_header_copy (&message->header, &retval->header)) 01459 { 01460 dbus_free (retval); 01461 return NULL; 01462 } 01463 01464 if (!_dbus_string_init_preallocated (&retval->body, 01465 _dbus_string_get_length (&message->body))) 01466 { 01467 _dbus_header_free (&retval->header); 01468 dbus_free (retval); 01469 return NULL; 01470 } 01471 01472 if (!_dbus_string_copy (&message->body, 0, 01473 &retval->body, 0)) 01474 goto failed_copy; 01475 01476 #ifdef HAVE_UNIX_FD_PASSING 01477 retval->unix_fds = dbus_new(int, message->n_unix_fds); 01478 if (retval->unix_fds == NULL && message->n_unix_fds > 0) 01479 goto failed_copy; 01480 01481 retval->n_unix_fds_allocated = message->n_unix_fds; 01482 01483 for (retval->n_unix_fds = 0; 01484 retval->n_unix_fds < message->n_unix_fds; 01485 retval->n_unix_fds++) 01486 { 01487 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL); 01488 01489 if (retval->unix_fds[retval->n_unix_fds] < 0) 01490 goto failed_copy; 01491 } 01492 01493 #endif 01494 01495 return retval; 01496 01497 failed_copy: 01498 _dbus_header_free (&retval->header); 01499 _dbus_string_free (&retval->body); 01500 01501 #ifdef HAVE_UNIX_FD_PASSING 01502 close_unix_fds(retval->unix_fds, &retval->n_unix_fds); 01503 dbus_free(retval->unix_fds); 01504 #endif 01505 01506 dbus_free (retval); 01507 01508 return NULL; 01509 } 01510 01511 01519 DBusMessage * 01520 dbus_message_ref (DBusMessage *message) 01521 { 01522 dbus_int32_t old_refcount; 01523 01524 _dbus_return_val_if_fail (message != NULL, NULL); 01525 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); 01526 _dbus_return_val_if_fail (!message->in_cache, NULL); 01527 01528 old_refcount = _dbus_atomic_inc (&message->refcount); 01529 _dbus_assert (old_refcount >= 1); 01530 01531 return message; 01532 } 01533 01541 void 01542 dbus_message_unref (DBusMessage *message) 01543 { 01544 dbus_int32_t old_refcount; 01545 01546 _dbus_return_if_fail (message != NULL); 01547 _dbus_return_if_fail (message->generation == _dbus_current_generation); 01548 _dbus_return_if_fail (!message->in_cache); 01549 01550 old_refcount = _dbus_atomic_dec (&message->refcount); 01551 01552 _dbus_assert (old_refcount >= 0); 01553 01554 if (old_refcount == 1) 01555 { 01556 /* Calls application callbacks! */ 01557 dbus_message_cache_or_finalize (message); 01558 } 01559 } 01560 01571 int 01572 dbus_message_get_type (DBusMessage *message) 01573 { 01574 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID); 01575 01576 return _dbus_header_get_message_type (&message->header); 01577 } 01578 01641 dbus_bool_t 01642 dbus_message_append_args (DBusMessage *message, 01643 int first_arg_type, 01644 ...) 01645 { 01646 dbus_bool_t retval; 01647 va_list var_args; 01648 01649 _dbus_return_val_if_fail (message != NULL, FALSE); 01650 01651 va_start (var_args, first_arg_type); 01652 retval = dbus_message_append_args_valist (message, 01653 first_arg_type, 01654 var_args); 01655 va_end (var_args); 01656 01657 return retval; 01658 } 01659 01673 dbus_bool_t 01674 dbus_message_append_args_valist (DBusMessage *message, 01675 int first_arg_type, 01676 va_list var_args) 01677 { 01678 int type; 01679 DBusMessageIter iter; 01680 01681 _dbus_return_val_if_fail (message != NULL, FALSE); 01682 01683 type = first_arg_type; 01684 01685 dbus_message_iter_init_append (message, &iter); 01686 01687 while (type != DBUS_TYPE_INVALID) 01688 { 01689 if (dbus_type_is_basic (type)) 01690 { 01691 const DBusBasicValue *value; 01692 value = va_arg (var_args, const DBusBasicValue*); 01693 01694 if (!dbus_message_iter_append_basic (&iter, 01695 type, 01696 value)) 01697 goto failed; 01698 } 01699 else if (type == DBUS_TYPE_ARRAY) 01700 { 01701 int element_type; 01702 DBusMessageIter array; 01703 char buf[2]; 01704 01705 element_type = va_arg (var_args, int); 01706 01707 buf[0] = element_type; 01708 buf[1] = '\0'; 01709 if (!dbus_message_iter_open_container (&iter, 01710 DBUS_TYPE_ARRAY, 01711 buf, 01712 &array)) 01713 goto failed; 01714 01715 if (dbus_type_is_fixed (element_type) && 01716 element_type != DBUS_TYPE_UNIX_FD) 01717 { 01718 const DBusBasicValue **value; 01719 int n_elements; 01720 01721 value = va_arg (var_args, const DBusBasicValue**); 01722 n_elements = va_arg (var_args, int); 01723 01724 if (!dbus_message_iter_append_fixed_array (&array, 01725 element_type, 01726 value, 01727 n_elements)) { 01728 dbus_message_iter_abandon_container (&iter, &array); 01729 goto failed; 01730 } 01731 } 01732 else if (element_type == DBUS_TYPE_STRING || 01733 element_type == DBUS_TYPE_SIGNATURE || 01734 element_type == DBUS_TYPE_OBJECT_PATH) 01735 { 01736 const char ***value_p; 01737 const char **value; 01738 int n_elements; 01739 int i; 01740 01741 value_p = va_arg (var_args, const char***); 01742 n_elements = va_arg (var_args, int); 01743 01744 value = *value_p; 01745 01746 i = 0; 01747 while (i < n_elements) 01748 { 01749 if (!dbus_message_iter_append_basic (&array, 01750 element_type, 01751 &value[i])) { 01752 dbus_message_iter_abandon_container (&iter, &array); 01753 goto failed; 01754 } 01755 ++i; 01756 } 01757 } 01758 else 01759 { 01760 _dbus_warn ("arrays of %s can't be appended with %s for now\n", 01761 _dbus_type_to_string (element_type), 01762 _DBUS_FUNCTION_NAME); 01763 goto failed; 01764 } 01765 01766 if (!dbus_message_iter_close_container (&iter, &array)) 01767 goto failed; 01768 } 01769 #ifndef DBUS_DISABLE_CHECKS 01770 else 01771 { 01772 _dbus_warn ("type %s isn't supported yet in %s\n", 01773 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME); 01774 goto failed; 01775 } 01776 #endif 01777 01778 type = va_arg (var_args, int); 01779 } 01780 01781 return TRUE; 01782 01783 failed: 01784 return FALSE; 01785 } 01786 01831 dbus_bool_t 01832 dbus_message_get_args (DBusMessage *message, 01833 DBusError *error, 01834 int first_arg_type, 01835 ...) 01836 { 01837 dbus_bool_t retval; 01838 va_list var_args; 01839 01840 _dbus_return_val_if_fail (message != NULL, FALSE); 01841 _dbus_return_val_if_error_is_set (error, FALSE); 01842 01843 va_start (var_args, first_arg_type); 01844 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args); 01845 va_end (var_args); 01846 01847 return retval; 01848 } 01849 01860 dbus_bool_t 01861 dbus_message_get_args_valist (DBusMessage *message, 01862 DBusError *error, 01863 int first_arg_type, 01864 va_list var_args) 01865 { 01866 DBusMessageIter iter; 01867 01868 _dbus_return_val_if_fail (message != NULL, FALSE); 01869 _dbus_return_val_if_error_is_set (error, FALSE); 01870 01871 dbus_message_iter_init (message, &iter); 01872 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); 01873 } 01874 01875 static void 01876 _dbus_message_iter_init_common (DBusMessage *message, 01877 DBusMessageRealIter *real, 01878 int iter_type) 01879 { 01880 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); 01881 01882 /* Since the iterator will read or write who-knows-what from the 01883 * message, we need to get in the right byte order 01884 */ 01885 ensure_byte_order (message); 01886 01887 real->message = message; 01888 real->changed_stamp = message->changed_stamp; 01889 real->iter_type = iter_type; 01890 real->sig_refcount = 0; 01891 } 01892 01915 dbus_bool_t 01916 dbus_message_iter_init (DBusMessage *message, 01917 DBusMessageIter *iter) 01918 { 01919 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01920 const DBusString *type_str; 01921 int type_pos; 01922 01923 _dbus_return_val_if_fail (message != NULL, FALSE); 01924 _dbus_return_val_if_fail (iter != NULL, FALSE); 01925 01926 get_const_signature (&message->header, &type_str, &type_pos); 01927 01928 _dbus_message_iter_init_common (message, real, 01929 DBUS_MESSAGE_ITER_TYPE_READER); 01930 01931 _dbus_type_reader_init (&real->u.reader, 01932 message->byte_order, 01933 type_str, type_pos, 01934 &message->body, 01935 0); 01936 01937 return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID; 01938 } 01939 01946 dbus_bool_t 01947 dbus_message_iter_has_next (DBusMessageIter *iter) 01948 { 01949 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01950 01951 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01952 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01953 01954 return _dbus_type_reader_has_next (&real->u.reader); 01955 } 01956 01965 dbus_bool_t 01966 dbus_message_iter_next (DBusMessageIter *iter) 01967 { 01968 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01969 01970 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01971 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01972 01973 return _dbus_type_reader_next (&real->u.reader); 01974 } 01975 01990 int 01991 dbus_message_iter_get_arg_type (DBusMessageIter *iter) 01992 { 01993 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01994 01995 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 01996 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01997 01998 return _dbus_type_reader_get_current_type (&real->u.reader); 01999 } 02000 02009 int 02010 dbus_message_iter_get_element_type (DBusMessageIter *iter) 02011 { 02012 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02013 02014 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02015 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); 02016 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 02017 02018 return _dbus_type_reader_get_element_type (&real->u.reader); 02019 } 02020 02046 void 02047 dbus_message_iter_recurse (DBusMessageIter *iter, 02048 DBusMessageIter *sub) 02049 { 02050 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02051 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02052 02053 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02054 _dbus_return_if_fail (sub != NULL); 02055 02056 *real_sub = *real; 02057 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader); 02058 } 02059 02071 char * 02072 dbus_message_iter_get_signature (DBusMessageIter *iter) 02073 { 02074 const DBusString *sig; 02075 DBusString retstr; 02076 char *ret; 02077 int start, len; 02078 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02079 02080 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL); 02081 02082 if (!_dbus_string_init (&retstr)) 02083 return NULL; 02084 02085 _dbus_type_reader_get_signature (&real->u.reader, &sig, 02086 &start, &len); 02087 if (!_dbus_string_append_len (&retstr, 02088 _dbus_string_get_const_data (sig) + start, 02089 len)) 02090 return NULL; 02091 if (!_dbus_string_steal_data (&retstr, &ret)) 02092 return NULL; 02093 _dbus_string_free (&retstr); 02094 return ret; 02095 } 02096 02144 void 02145 dbus_message_iter_get_basic (DBusMessageIter *iter, 02146 void *value) 02147 { 02148 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02149 02150 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02151 _dbus_return_if_fail (value != NULL); 02152 02153 if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD) 02154 { 02155 #ifdef HAVE_UNIX_FD_PASSING 02156 DBusBasicValue idx; 02157 02158 _dbus_type_reader_read_basic(&real->u.reader, &idx); 02159 02160 if (idx.u32 >= real->message->n_unix_fds) { 02161 /* Hmm, we cannot really signal an error here, so let's make 02162 sure to return an invalid fd. */ 02163 *((int*) value) = -1; 02164 return; 02165 } 02166 02167 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL); 02168 #else 02169 *((int*) value) = -1; 02170 #endif 02171 } 02172 else 02173 { 02174 _dbus_type_reader_read_basic (&real->u.reader, 02175 value); 02176 } 02177 } 02178 02197 int 02198 dbus_message_iter_get_array_len (DBusMessageIter *iter) 02199 { 02200 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02201 02202 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02203 02204 return _dbus_type_reader_get_array_length (&real->u.reader); 02205 } 02206 02242 void 02243 dbus_message_iter_get_fixed_array (DBusMessageIter *iter, 02244 void *value, 02245 int *n_elements) 02246 { 02247 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02248 int subtype = _dbus_type_reader_get_current_type(&real->u.reader); 02249 02250 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02251 _dbus_return_if_fail (value != NULL); 02252 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) || 02253 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD)); 02254 02255 _dbus_type_reader_read_fixed_multi (&real->u.reader, 02256 value, n_elements); 02257 } 02258 02270 void 02271 dbus_message_iter_init_append (DBusMessage *message, 02272 DBusMessageIter *iter) 02273 { 02274 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02275 02276 _dbus_return_if_fail (message != NULL); 02277 _dbus_return_if_fail (iter != NULL); 02278 02279 _dbus_message_iter_init_common (message, real, 02280 DBUS_MESSAGE_ITER_TYPE_WRITER); 02281 02282 /* We create the signature string and point iterators at it "on demand" 02283 * when a value is actually appended. That means that init() never fails 02284 * due to OOM. 02285 */ 02286 _dbus_type_writer_init_types_delayed (&real->u.writer, 02287 message->byte_order, 02288 &message->body, 02289 _dbus_string_get_length (&message->body)); 02290 } 02291 02300 static dbus_bool_t 02301 _dbus_message_iter_open_signature (DBusMessageRealIter *real) 02302 { 02303 DBusString *str; 02304 const DBusString *current_sig; 02305 int current_sig_pos; 02306 02307 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02308 02309 if (real->u.writer.type_str != NULL) 02310 { 02311 _dbus_assert (real->sig_refcount > 0); 02312 real->sig_refcount += 1; 02313 return TRUE; 02314 } 02315 02316 str = dbus_new (DBusString, 1); 02317 if (str == NULL) 02318 return FALSE; 02319 02320 if (!_dbus_header_get_field_raw (&real->message->header, 02321 DBUS_HEADER_FIELD_SIGNATURE, 02322 ¤t_sig, ¤t_sig_pos)) 02323 current_sig = NULL; 02324 02325 if (current_sig) 02326 { 02327 int current_len; 02328 02329 current_len = _dbus_string_get_byte (current_sig, current_sig_pos); 02330 current_sig_pos += 1; /* move on to sig data */ 02331 02332 if (!_dbus_string_init_preallocated (str, current_len + 4)) 02333 { 02334 dbus_free (str); 02335 return FALSE; 02336 } 02337 02338 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len, 02339 str, 0)) 02340 { 02341 _dbus_string_free (str); 02342 dbus_free (str); 02343 return FALSE; 02344 } 02345 } 02346 else 02347 { 02348 if (!_dbus_string_init_preallocated (str, 4)) 02349 { 02350 dbus_free (str); 02351 return FALSE; 02352 } 02353 } 02354 02355 real->sig_refcount = 1; 02356 02357 _dbus_type_writer_add_types (&real->u.writer, 02358 str, _dbus_string_get_length (str)); 02359 return TRUE; 02360 } 02361 02371 static dbus_bool_t 02372 _dbus_message_iter_close_signature (DBusMessageRealIter *real) 02373 { 02374 DBusString *str; 02375 const char *v_STRING; 02376 dbus_bool_t retval; 02377 02378 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02379 _dbus_assert (real->u.writer.type_str != NULL); 02380 _dbus_assert (real->sig_refcount > 0); 02381 02382 real->sig_refcount -= 1; 02383 02384 if (real->sig_refcount > 0) 02385 return TRUE; 02386 _dbus_assert (real->sig_refcount == 0); 02387 02388 retval = TRUE; 02389 02390 str = real->u.writer.type_str; 02391 02392 v_STRING = _dbus_string_get_const_data (str); 02393 if (!_dbus_header_set_field_basic (&real->message->header, 02394 DBUS_HEADER_FIELD_SIGNATURE, 02395 DBUS_TYPE_SIGNATURE, 02396 &v_STRING)) 02397 retval = FALSE; 02398 02399 _dbus_type_writer_remove_types (&real->u.writer); 02400 _dbus_string_free (str); 02401 dbus_free (str); 02402 02403 return retval; 02404 } 02405 02413 static void 02414 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real) 02415 { 02416 DBusString *str; 02417 02418 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02419 _dbus_assert (real->u.writer.type_str != NULL); 02420 _dbus_assert (real->sig_refcount > 0); 02421 02422 real->sig_refcount -= 1; 02423 02424 if (real->sig_refcount > 0) 02425 return; 02426 _dbus_assert (real->sig_refcount == 0); 02427 02428 str = real->u.writer.type_str; 02429 02430 _dbus_type_writer_remove_types (&real->u.writer); 02431 _dbus_string_free (str); 02432 dbus_free (str); 02433 } 02434 02435 #ifndef DBUS_DISABLE_CHECKS 02436 static dbus_bool_t 02437 _dbus_message_iter_append_check (DBusMessageRealIter *iter) 02438 { 02439 if (!_dbus_message_iter_check (iter)) 02440 return FALSE; 02441 02442 if (iter->message->locked) 02443 { 02444 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n"); 02445 return FALSE; 02446 } 02447 02448 return TRUE; 02449 } 02450 #endif /* DBUS_DISABLE_CHECKS */ 02451 02452 #ifdef HAVE_UNIX_FD_PASSING 02453 static int * 02454 expand_fd_array(DBusMessage *m, 02455 unsigned n) 02456 { 02457 _dbus_assert(m); 02458 02459 /* This makes space for adding n new fds to the array and returns a 02460 pointer to the place were the first fd should be put. */ 02461 02462 if (m->n_unix_fds + n > m->n_unix_fds_allocated) 02463 { 02464 unsigned k; 02465 int *p; 02466 02467 /* Make twice as much space as necessary */ 02468 k = (m->n_unix_fds + n) * 2; 02469 02470 /* Allocate at least four */ 02471 if (k < 4) 02472 k = 4; 02473 02474 p = dbus_realloc(m->unix_fds, k * sizeof(int)); 02475 if (p == NULL) 02476 return NULL; 02477 02478 m->unix_fds = p; 02479 m->n_unix_fds_allocated = k; 02480 } 02481 02482 return m->unix_fds + m->n_unix_fds; 02483 } 02484 #endif 02485 02505 dbus_bool_t 02506 dbus_message_iter_append_basic (DBusMessageIter *iter, 02507 int type, 02508 const void *value) 02509 { 02510 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02511 dbus_bool_t ret; 02512 02513 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02514 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02515 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE); 02516 _dbus_return_val_if_fail (value != NULL, FALSE); 02517 02518 #ifndef DBUS_DISABLE_CHECKS 02519 switch (type) 02520 { 02521 const char * const *string_p; 02522 const dbus_bool_t *bool_p; 02523 02524 case DBUS_TYPE_STRING: 02525 string_p = value; 02526 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE); 02527 break; 02528 02529 case DBUS_TYPE_OBJECT_PATH: 02530 string_p = value; 02531 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE); 02532 break; 02533 02534 case DBUS_TYPE_SIGNATURE: 02535 string_p = value; 02536 _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE); 02537 break; 02538 02539 case DBUS_TYPE_BOOLEAN: 02540 bool_p = value; 02541 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE); 02542 break; 02543 02544 default: 02545 { 02546 /* nothing to check, all possible values are allowed */ 02547 } 02548 } 02549 #endif 02550 02551 if (!_dbus_message_iter_open_signature (real)) 02552 return FALSE; 02553 02554 if (type == DBUS_TYPE_UNIX_FD) 02555 { 02556 #ifdef HAVE_UNIX_FD_PASSING 02557 int *fds; 02558 dbus_uint32_t u; 02559 02560 /* First step, include the fd in the fd list of this message */ 02561 if (!(fds = expand_fd_array(real->message, 1))) 02562 return FALSE; 02563 02564 *fds = _dbus_dup(*(int*) value, NULL); 02565 if (*fds < 0) 02566 return FALSE; 02567 02568 u = real->message->n_unix_fds; 02569 02570 /* Second step, write the index to the fd */ 02571 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) { 02572 _dbus_close(*fds, NULL); 02573 return FALSE; 02574 } 02575 02576 real->message->n_unix_fds += 1; 02577 u += 1; 02578 02579 /* Final step, update the header accordingly */ 02580 ret = _dbus_header_set_field_basic (&real->message->header, 02581 DBUS_HEADER_FIELD_UNIX_FDS, 02582 DBUS_TYPE_UINT32, 02583 &u); 02584 02585 /* If any of these operations fail the message is 02586 hosed. However, no memory or fds should be leaked since what 02587 has been added to message has been added to the message, and 02588 can hence be accounted for when the message is being 02589 freed. */ 02590 #else 02591 ret = FALSE; 02592 #endif 02593 } 02594 else 02595 { 02596 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02597 } 02598 02599 if (!_dbus_message_iter_close_signature (real)) 02600 ret = FALSE; 02601 02602 return ret; 02603 } 02604 02640 dbus_bool_t 02641 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02642 int element_type, 02643 const void *value, 02644 int n_elements) 02645 { 02646 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02647 dbus_bool_t ret; 02648 02649 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02650 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02651 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); 02652 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02653 _dbus_return_val_if_fail (value != NULL, FALSE); 02654 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02655 _dbus_return_val_if_fail (n_elements <= 02656 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02657 FALSE); 02658 02659 #ifndef DBUS_DISABLE_CHECKS 02660 if (element_type == DBUS_TYPE_BOOLEAN) 02661 { 02662 const dbus_bool_t * const *bools = value; 02663 int i; 02664 02665 for (i = 0; i < n_elements; i++) 02666 { 02667 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE); 02668 } 02669 } 02670 #endif 02671 02672 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02673 02674 return ret; 02675 } 02676 02698 dbus_bool_t 02699 dbus_message_iter_open_container (DBusMessageIter *iter, 02700 int type, 02701 const char *contained_signature, 02702 DBusMessageIter *sub) 02703 { 02704 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02705 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02706 DBusString contained_str; 02707 02708 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02709 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02710 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02711 _dbus_return_val_if_fail (sub != NULL, FALSE); 02712 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02713 contained_signature == NULL) || 02714 (type == DBUS_TYPE_DICT_ENTRY && 02715 contained_signature == NULL) || 02716 (type == DBUS_TYPE_VARIANT && 02717 contained_signature != NULL) || 02718 (type == DBUS_TYPE_ARRAY && 02719 contained_signature != NULL), FALSE); 02720 02721 /* this would fail if the contained_signature is a dict entry, since 02722 * dict entries are invalid signatures standalone (they must be in 02723 * an array) 02724 */ 02725 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02726 (contained_signature == NULL || 02727 _dbus_check_is_valid_signature (contained_signature)), 02728 FALSE); 02729 02730 if (!_dbus_message_iter_open_signature (real)) 02731 return FALSE; 02732 02733 *real_sub = *real; 02734 02735 if (contained_signature != NULL) 02736 { 02737 _dbus_string_init_const (&contained_str, contained_signature); 02738 02739 return _dbus_type_writer_recurse (&real->u.writer, 02740 type, 02741 &contained_str, 0, 02742 &real_sub->u.writer); 02743 } 02744 else 02745 { 02746 return _dbus_type_writer_recurse (&real->u.writer, 02747 type, 02748 NULL, 0, 02749 &real_sub->u.writer); 02750 } 02751 } 02752 02753 02767 dbus_bool_t 02768 dbus_message_iter_close_container (DBusMessageIter *iter, 02769 DBusMessageIter *sub) 02770 { 02771 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02772 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02773 dbus_bool_t ret; 02774 02775 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02776 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02777 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 02778 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02779 02780 ret = _dbus_type_writer_unrecurse (&real->u.writer, 02781 &real_sub->u.writer); 02782 02783 if (!_dbus_message_iter_close_signature (real)) 02784 ret = FALSE; 02785 02786 return ret; 02787 } 02788 02800 void 02801 dbus_message_iter_abandon_container (DBusMessageIter *iter, 02802 DBusMessageIter *sub) 02803 { 02804 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02805 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02806 02807 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 02808 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02809 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 02810 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02811 02812 _dbus_message_iter_abandon_signature (real); 02813 } 02814 02831 void 02832 dbus_message_set_no_reply (DBusMessage *message, 02833 dbus_bool_t no_reply) 02834 { 02835 _dbus_return_if_fail (message != NULL); 02836 _dbus_return_if_fail (!message->locked); 02837 02838 _dbus_header_toggle_flag (&message->header, 02839 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 02840 no_reply); 02841 } 02842 02850 dbus_bool_t 02851 dbus_message_get_no_reply (DBusMessage *message) 02852 { 02853 _dbus_return_val_if_fail (message != NULL, FALSE); 02854 02855 return _dbus_header_get_flag (&message->header, 02856 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 02857 } 02858 02873 void 02874 dbus_message_set_auto_start (DBusMessage *message, 02875 dbus_bool_t auto_start) 02876 { 02877 _dbus_return_if_fail (message != NULL); 02878 _dbus_return_if_fail (!message->locked); 02879 02880 _dbus_header_toggle_flag (&message->header, 02881 DBUS_HEADER_FLAG_NO_AUTO_START, 02882 !auto_start); 02883 } 02884 02892 dbus_bool_t 02893 dbus_message_get_auto_start (DBusMessage *message) 02894 { 02895 _dbus_return_val_if_fail (message != NULL, FALSE); 02896 02897 return !_dbus_header_get_flag (&message->header, 02898 DBUS_HEADER_FLAG_NO_AUTO_START); 02899 } 02900 02901 02914 dbus_bool_t 02915 dbus_message_set_path (DBusMessage *message, 02916 const char *object_path) 02917 { 02918 _dbus_return_val_if_fail (message != NULL, FALSE); 02919 _dbus_return_val_if_fail (!message->locked, FALSE); 02920 _dbus_return_val_if_fail (object_path == NULL || 02921 _dbus_check_is_valid_path (object_path), 02922 FALSE); 02923 02924 return set_or_delete_string_field (message, 02925 DBUS_HEADER_FIELD_PATH, 02926 DBUS_TYPE_OBJECT_PATH, 02927 object_path); 02928 } 02929 02943 const char* 02944 dbus_message_get_path (DBusMessage *message) 02945 { 02946 const char *v; 02947 02948 _dbus_return_val_if_fail (message != NULL, NULL); 02949 02950 v = NULL; /* in case field doesn't exist */ 02951 _dbus_header_get_field_basic (&message->header, 02952 DBUS_HEADER_FIELD_PATH, 02953 DBUS_TYPE_OBJECT_PATH, 02954 (void *) &v); 02955 return v; 02956 } 02957 02967 dbus_bool_t 02968 dbus_message_has_path (DBusMessage *message, 02969 const char *path) 02970 { 02971 const char *msg_path; 02972 msg_path = dbus_message_get_path (message); 02973 02974 if (msg_path == NULL) 02975 { 02976 if (path == NULL) 02977 return TRUE; 02978 else 02979 return FALSE; 02980 } 02981 02982 if (path == NULL) 02983 return FALSE; 02984 02985 if (strcmp (msg_path, path) == 0) 02986 return TRUE; 02987 02988 return FALSE; 02989 } 02990 03011 dbus_bool_t 03012 dbus_message_get_path_decomposed (DBusMessage *message, 03013 char ***path) 03014 { 03015 const char *v; 03016 03017 _dbus_return_val_if_fail (message != NULL, FALSE); 03018 _dbus_return_val_if_fail (path != NULL, FALSE); 03019 03020 *path = NULL; 03021 03022 v = dbus_message_get_path (message); 03023 if (v != NULL) 03024 { 03025 if (!_dbus_decompose_path (v, strlen (v), 03026 path, NULL)) 03027 return FALSE; 03028 } 03029 return TRUE; 03030 } 03031 03045 dbus_bool_t 03046 dbus_message_set_interface (DBusMessage *message, 03047 const char *interface) 03048 { 03049 _dbus_return_val_if_fail (message != NULL, FALSE); 03050 _dbus_return_val_if_fail (!message->locked, FALSE); 03051 _dbus_return_val_if_fail (interface == NULL || 03052 _dbus_check_is_valid_interface (interface), 03053 FALSE); 03054 03055 return set_or_delete_string_field (message, 03056 DBUS_HEADER_FIELD_INTERFACE, 03057 DBUS_TYPE_STRING, 03058 interface); 03059 } 03060 03074 const char* 03075 dbus_message_get_interface (DBusMessage *message) 03076 { 03077 const char *v; 03078 03079 _dbus_return_val_if_fail (message != NULL, NULL); 03080 03081 v = NULL; /* in case field doesn't exist */ 03082 _dbus_header_get_field_basic (&message->header, 03083 DBUS_HEADER_FIELD_INTERFACE, 03084 DBUS_TYPE_STRING, 03085 (void *) &v); 03086 return v; 03087 } 03088 03096 dbus_bool_t 03097 dbus_message_has_interface (DBusMessage *message, 03098 const char *interface) 03099 { 03100 const char *msg_interface; 03101 msg_interface = dbus_message_get_interface (message); 03102 03103 if (msg_interface == NULL) 03104 { 03105 if (interface == NULL) 03106 return TRUE; 03107 else 03108 return FALSE; 03109 } 03110 03111 if (interface == NULL) 03112 return FALSE; 03113 03114 if (strcmp (msg_interface, interface) == 0) 03115 return TRUE; 03116 03117 return FALSE; 03118 03119 } 03120 03133 dbus_bool_t 03134 dbus_message_set_member (DBusMessage *message, 03135 const char *member) 03136 { 03137 _dbus_return_val_if_fail (message != NULL, FALSE); 03138 _dbus_return_val_if_fail (!message->locked, FALSE); 03139 _dbus_return_val_if_fail (member == NULL || 03140 _dbus_check_is_valid_member (member), 03141 FALSE); 03142 03143 return set_or_delete_string_field (message, 03144 DBUS_HEADER_FIELD_MEMBER, 03145 DBUS_TYPE_STRING, 03146 member); 03147 } 03148 03160 const char* 03161 dbus_message_get_member (DBusMessage *message) 03162 { 03163 const char *v; 03164 03165 _dbus_return_val_if_fail (message != NULL, NULL); 03166 03167 v = NULL; /* in case field doesn't exist */ 03168 _dbus_header_get_field_basic (&message->header, 03169 DBUS_HEADER_FIELD_MEMBER, 03170 DBUS_TYPE_STRING, 03171 (void *) &v); 03172 return v; 03173 } 03174 03182 dbus_bool_t 03183 dbus_message_has_member (DBusMessage *message, 03184 const char *member) 03185 { 03186 const char *msg_member; 03187 msg_member = dbus_message_get_member (message); 03188 03189 if (msg_member == NULL) 03190 { 03191 if (member == NULL) 03192 return TRUE; 03193 else 03194 return FALSE; 03195 } 03196 03197 if (member == NULL) 03198 return FALSE; 03199 03200 if (strcmp (msg_member, member) == 0) 03201 return TRUE; 03202 03203 return FALSE; 03204 03205 } 03206 03218 dbus_bool_t 03219 dbus_message_set_error_name (DBusMessage *message, 03220 const char *error_name) 03221 { 03222 _dbus_return_val_if_fail (message != NULL, FALSE); 03223 _dbus_return_val_if_fail (!message->locked, FALSE); 03224 _dbus_return_val_if_fail (error_name == NULL || 03225 _dbus_check_is_valid_error_name (error_name), 03226 FALSE); 03227 03228 return set_or_delete_string_field (message, 03229 DBUS_HEADER_FIELD_ERROR_NAME, 03230 DBUS_TYPE_STRING, 03231 error_name); 03232 } 03233 03244 const char* 03245 dbus_message_get_error_name (DBusMessage *message) 03246 { 03247 const char *v; 03248 03249 _dbus_return_val_if_fail (message != NULL, NULL); 03250 03251 v = NULL; /* in case field doesn't exist */ 03252 _dbus_header_get_field_basic (&message->header, 03253 DBUS_HEADER_FIELD_ERROR_NAME, 03254 DBUS_TYPE_STRING, 03255 (void *) &v); 03256 return v; 03257 } 03258 03272 dbus_bool_t 03273 dbus_message_set_destination (DBusMessage *message, 03274 const char *destination) 03275 { 03276 _dbus_return_val_if_fail (message != NULL, FALSE); 03277 _dbus_return_val_if_fail (!message->locked, FALSE); 03278 _dbus_return_val_if_fail (destination == NULL || 03279 _dbus_check_is_valid_bus_name (destination), 03280 FALSE); 03281 03282 return set_or_delete_string_field (message, 03283 DBUS_HEADER_FIELD_DESTINATION, 03284 DBUS_TYPE_STRING, 03285 destination); 03286 } 03287 03297 const char* 03298 dbus_message_get_destination (DBusMessage *message) 03299 { 03300 const char *v; 03301 03302 _dbus_return_val_if_fail (message != NULL, NULL); 03303 03304 v = NULL; /* in case field doesn't exist */ 03305 _dbus_header_get_field_basic (&message->header, 03306 DBUS_HEADER_FIELD_DESTINATION, 03307 DBUS_TYPE_STRING, 03308 (void *) &v); 03309 return v; 03310 } 03311 03326 dbus_bool_t 03327 dbus_message_set_sender (DBusMessage *message, 03328 const char *sender) 03329 { 03330 _dbus_return_val_if_fail (message != NULL, FALSE); 03331 _dbus_return_val_if_fail (!message->locked, FALSE); 03332 _dbus_return_val_if_fail (sender == NULL || 03333 _dbus_check_is_valid_bus_name (sender), 03334 FALSE); 03335 03336 return set_or_delete_string_field (message, 03337 DBUS_HEADER_FIELD_SENDER, 03338 DBUS_TYPE_STRING, 03339 sender); 03340 } 03341 03357 const char* 03358 dbus_message_get_sender (DBusMessage *message) 03359 { 03360 const char *v; 03361 03362 _dbus_return_val_if_fail (message != NULL, NULL); 03363 03364 v = NULL; /* in case field doesn't exist */ 03365 _dbus_header_get_field_basic (&message->header, 03366 DBUS_HEADER_FIELD_SENDER, 03367 DBUS_TYPE_STRING, 03368 (void *) &v); 03369 return v; 03370 } 03371 03390 const char* 03391 dbus_message_get_signature (DBusMessage *message) 03392 { 03393 const DBusString *type_str; 03394 int type_pos; 03395 03396 _dbus_return_val_if_fail (message != NULL, NULL); 03397 03398 get_const_signature (&message->header, &type_str, &type_pos); 03399 03400 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03401 } 03402 03403 static dbus_bool_t 03404 _dbus_message_has_type_interface_member (DBusMessage *message, 03405 int type, 03406 const char *interface, 03407 const char *member) 03408 { 03409 const char *n; 03410 03411 _dbus_assert (message != NULL); 03412 _dbus_assert (interface != NULL); 03413 _dbus_assert (member != NULL); 03414 03415 if (dbus_message_get_type (message) != type) 03416 return FALSE; 03417 03418 /* Optimize by checking the short member name first 03419 * instead of the longer interface name 03420 */ 03421 03422 n = dbus_message_get_member (message); 03423 03424 if (n && strcmp (n, member) == 0) 03425 { 03426 n = dbus_message_get_interface (message); 03427 03428 if (n == NULL || strcmp (n, interface) == 0) 03429 return TRUE; 03430 } 03431 03432 return FALSE; 03433 } 03434 03449 dbus_bool_t 03450 dbus_message_is_method_call (DBusMessage *message, 03451 const char *interface, 03452 const char *method) 03453 { 03454 _dbus_return_val_if_fail (message != NULL, FALSE); 03455 _dbus_return_val_if_fail (interface != NULL, FALSE); 03456 _dbus_return_val_if_fail (method != NULL, FALSE); 03457 /* don't check that interface/method are valid since it would be 03458 * expensive, and not catch many common errors 03459 */ 03460 03461 return _dbus_message_has_type_interface_member (message, 03462 DBUS_MESSAGE_TYPE_METHOD_CALL, 03463 interface, method); 03464 } 03465 03477 dbus_bool_t 03478 dbus_message_is_signal (DBusMessage *message, 03479 const char *interface, 03480 const char *signal_name) 03481 { 03482 _dbus_return_val_if_fail (message != NULL, FALSE); 03483 _dbus_return_val_if_fail (interface != NULL, FALSE); 03484 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03485 /* don't check that interface/name are valid since it would be 03486 * expensive, and not catch many common errors 03487 */ 03488 03489 return _dbus_message_has_type_interface_member (message, 03490 DBUS_MESSAGE_TYPE_SIGNAL, 03491 interface, signal_name); 03492 } 03493 03504 dbus_bool_t 03505 dbus_message_is_error (DBusMessage *message, 03506 const char *error_name) 03507 { 03508 const char *n; 03509 03510 _dbus_return_val_if_fail (message != NULL, FALSE); 03511 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03512 /* don't check that error_name is valid since it would be expensive, 03513 * and not catch many common errors 03514 */ 03515 03516 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03517 return FALSE; 03518 03519 n = dbus_message_get_error_name (message); 03520 03521 if (n && strcmp (n, error_name) == 0) 03522 return TRUE; 03523 else 03524 return FALSE; 03525 } 03526 03537 dbus_bool_t 03538 dbus_message_has_destination (DBusMessage *message, 03539 const char *name) 03540 { 03541 const char *s; 03542 03543 _dbus_return_val_if_fail (message != NULL, FALSE); 03544 _dbus_return_val_if_fail (name != NULL, FALSE); 03545 /* don't check that name is valid since it would be expensive, and 03546 * not catch many common errors 03547 */ 03548 03549 s = dbus_message_get_destination (message); 03550 03551 if (s && strcmp (s, name) == 0) 03552 return TRUE; 03553 else 03554 return FALSE; 03555 } 03556 03572 dbus_bool_t 03573 dbus_message_has_sender (DBusMessage *message, 03574 const char *name) 03575 { 03576 const char *s; 03577 03578 _dbus_return_val_if_fail (message != NULL, FALSE); 03579 _dbus_return_val_if_fail (name != NULL, FALSE); 03580 /* don't check that name is valid since it would be expensive, and 03581 * not catch many common errors 03582 */ 03583 03584 s = dbus_message_get_sender (message); 03585 03586 if (s && strcmp (s, name) == 0) 03587 return TRUE; 03588 else 03589 return FALSE; 03590 } 03591 03601 dbus_bool_t 03602 dbus_message_has_signature (DBusMessage *message, 03603 const char *signature) 03604 { 03605 const char *s; 03606 03607 _dbus_return_val_if_fail (message != NULL, FALSE); 03608 _dbus_return_val_if_fail (signature != NULL, FALSE); 03609 /* don't check that signature is valid since it would be expensive, 03610 * and not catch many common errors 03611 */ 03612 03613 s = dbus_message_get_signature (message); 03614 03615 if (s && strcmp (s, signature) == 0) 03616 return TRUE; 03617 else 03618 return FALSE; 03619 } 03620 03643 dbus_bool_t 03644 dbus_set_error_from_message (DBusError *error, 03645 DBusMessage *message) 03646 { 03647 const char *str; 03648 03649 _dbus_return_val_if_fail (message != NULL, FALSE); 03650 _dbus_return_val_if_error_is_set (error, FALSE); 03651 03652 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03653 return FALSE; 03654 03655 str = NULL; 03656 dbus_message_get_args (message, NULL, 03657 DBUS_TYPE_STRING, &str, 03658 DBUS_TYPE_INVALID); 03659 03660 dbus_set_error (error, dbus_message_get_error_name (message), 03661 str ? "%s" : NULL, str); 03662 03663 return TRUE; 03664 } 03665 03672 dbus_bool_t 03673 dbus_message_contains_unix_fds(DBusMessage *message) 03674 { 03675 #ifdef HAVE_UNIX_FD_PASSING 03676 _dbus_assert(message); 03677 03678 return message->n_unix_fds > 0; 03679 #else 03680 return FALSE; 03681 #endif 03682 } 03683 03702 #define INITIAL_LOADER_DATA_LEN 32 03703 03710 DBusMessageLoader* 03711 _dbus_message_loader_new (void) 03712 { 03713 DBusMessageLoader *loader; 03714 03715 loader = dbus_new0 (DBusMessageLoader, 1); 03716 if (loader == NULL) 03717 return NULL; 03718 03719 loader->refcount = 1; 03720 03721 loader->corrupted = FALSE; 03722 loader->corruption_reason = DBUS_VALID; 03723 03724 /* this can be configured by the app, but defaults to the protocol max */ 03725 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03726 03727 /* We set a very relatively conservative default here since due to how 03728 SCM_RIGHTS works we need to preallocate an fd array of the maximum 03729 number of unix fds we want to receive in advance. A 03730 try-and-reallocate loop is not possible. */ 03731 loader->max_message_unix_fds = 1024; 03732 03733 if (!_dbus_string_init (&loader->data)) 03734 { 03735 dbus_free (loader); 03736 return NULL; 03737 } 03738 03739 /* preallocate the buffer for speed, ignore failure */ 03740 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03741 _dbus_string_set_length (&loader->data, 0); 03742 03743 #ifdef HAVE_UNIX_FD_PASSING 03744 loader->unix_fds = NULL; 03745 loader->n_unix_fds = loader->n_unix_fds_allocated = 0; 03746 loader->unix_fds_outstanding = FALSE; 03747 #endif 03748 03749 return loader; 03750 } 03751 03758 DBusMessageLoader * 03759 _dbus_message_loader_ref (DBusMessageLoader *loader) 03760 { 03761 loader->refcount += 1; 03762 03763 return loader; 03764 } 03765 03772 void 03773 _dbus_message_loader_unref (DBusMessageLoader *loader) 03774 { 03775 loader->refcount -= 1; 03776 if (loader->refcount == 0) 03777 { 03778 #ifdef HAVE_UNIX_FD_PASSING 03779 close_unix_fds(loader->unix_fds, &loader->n_unix_fds); 03780 dbus_free(loader->unix_fds); 03781 #endif 03782 _dbus_list_foreach (&loader->messages, 03783 (DBusForeachFunction) dbus_message_unref, 03784 NULL); 03785 _dbus_list_clear (&loader->messages); 03786 _dbus_string_free (&loader->data); 03787 dbus_free (loader); 03788 } 03789 } 03790 03809 void 03810 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 03811 DBusString **buffer) 03812 { 03813 _dbus_assert (!loader->buffer_outstanding); 03814 03815 *buffer = &loader->data; 03816 03817 loader->buffer_outstanding = TRUE; 03818 } 03819 03830 void 03831 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 03832 DBusString *buffer, 03833 int bytes_read) 03834 { 03835 _dbus_assert (loader->buffer_outstanding); 03836 _dbus_assert (buffer == &loader->data); 03837 03838 loader->buffer_outstanding = FALSE; 03839 } 03840 03851 dbus_bool_t 03852 _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, 03853 int **fds, 03854 unsigned *max_n_fds) 03855 { 03856 #ifdef HAVE_UNIX_FD_PASSING 03857 _dbus_assert (!loader->unix_fds_outstanding); 03858 03859 /* Allocate space where we can put the fds we read. We allocate 03860 space for max_message_unix_fds since this is an 03861 upper limit how many fds can be received within a single 03862 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic 03863 we are allocating the maximum possible array size right from the 03864 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed 03865 there is no better way. */ 03866 03867 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds) 03868 { 03869 int *a = dbus_realloc(loader->unix_fds, 03870 loader->max_message_unix_fds * sizeof(loader->unix_fds[0])); 03871 03872 if (!a) 03873 return FALSE; 03874 03875 loader->unix_fds = a; 03876 loader->n_unix_fds_allocated = loader->max_message_unix_fds; 03877 } 03878 03879 *fds = loader->unix_fds + loader->n_unix_fds; 03880 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds; 03881 03882 loader->unix_fds_outstanding = TRUE; 03883 return TRUE; 03884 #else 03885 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03886 return FALSE; 03887 #endif 03888 } 03889 03900 void 03901 _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, 03902 int *fds, 03903 unsigned n_fds) 03904 { 03905 #ifdef HAVE_UNIX_FD_PASSING 03906 _dbus_assert(loader->unix_fds_outstanding); 03907 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds); 03908 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated); 03909 03910 loader->n_unix_fds += n_fds; 03911 loader->unix_fds_outstanding = FALSE; 03912 #else 03913 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03914 #endif 03915 } 03916 03917 /* 03918 * FIXME when we move the header out of the buffer, that memmoves all 03919 * buffered messages. Kind of crappy. 03920 * 03921 * Also we copy the header and body, which is kind of crappy. To 03922 * avoid this, we have to allow header and body to be in a single 03923 * memory block, which is good for messages we read and bad for 03924 * messages we are creating. But we could move_len() the buffer into 03925 * this single memory block, and move_len() will just swap the buffers 03926 * if you're moving the entire buffer replacing the dest string. 03927 * 03928 * We could also have the message loader tell the transport how many 03929 * bytes to read; so it would first ask for some arbitrary number like 03930 * 256, then if the message was incomplete it would use the 03931 * header/body len to ask for exactly the size of the message (or 03932 * blocks the size of a typical kernel buffer for the socket). That 03933 * way we don't get trailing bytes in the buffer that have to be 03934 * memmoved. Though I suppose we also don't have a chance of reading a 03935 * bunch of small messages at once, so the optimization may be stupid. 03936 * 03937 * Another approach would be to keep a "start" index into 03938 * loader->data and only delete it occasionally, instead of after 03939 * each message is loaded. 03940 * 03941 * load_message() returns FALSE if not enough memory OR the loader was corrupted 03942 */ 03943 static dbus_bool_t 03944 load_message (DBusMessageLoader *loader, 03945 DBusMessage *message, 03946 int byte_order, 03947 int fields_array_len, 03948 int header_len, 03949 int body_len) 03950 { 03951 dbus_bool_t oom; 03952 DBusValidity validity; 03953 const DBusString *type_str; 03954 int type_pos; 03955 DBusValidationMode mode; 03956 dbus_uint32_t n_unix_fds = 0; 03957 03958 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 03959 03960 oom = FALSE; 03961 03962 #if 0 03963 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 03964 #endif 03965 03966 /* 1. VALIDATE AND COPY OVER HEADER */ 03967 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 03968 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 03969 03970 if (!_dbus_header_load (&message->header, 03971 mode, 03972 &validity, 03973 byte_order, 03974 fields_array_len, 03975 header_len, 03976 body_len, 03977 &loader->data, 0, 03978 _dbus_string_get_length (&loader->data))) 03979 { 03980 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 03981 03982 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 03983 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 03984 _dbus_assert (validity != DBUS_VALID); 03985 03986 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 03987 oom = TRUE; 03988 else 03989 { 03990 loader->corrupted = TRUE; 03991 loader->corruption_reason = validity; 03992 } 03993 goto failed; 03994 } 03995 03996 _dbus_assert (validity == DBUS_VALID); 03997 03998 message->byte_order = byte_order; 03999 04000 /* 2. VALIDATE BODY */ 04001 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 04002 { 04003 get_const_signature (&message->header, &type_str, &type_pos); 04004 04005 /* Because the bytes_remaining arg is NULL, this validates that the 04006 * body is the right length 04007 */ 04008 validity = _dbus_validate_body_with_reason (type_str, 04009 type_pos, 04010 byte_order, 04011 NULL, 04012 &loader->data, 04013 header_len, 04014 body_len); 04015 if (validity != DBUS_VALID) 04016 { 04017 _dbus_verbose ("Failed to validate message body code %d\n", validity); 04018 04019 loader->corrupted = TRUE; 04020 loader->corruption_reason = validity; 04021 04022 goto failed; 04023 } 04024 } 04025 04026 /* 3. COPY OVER UNIX FDS */ 04027 _dbus_header_get_field_basic(&message->header, 04028 DBUS_HEADER_FIELD_UNIX_FDS, 04029 DBUS_TYPE_UINT32, 04030 &n_unix_fds); 04031 04032 #ifdef HAVE_UNIX_FD_PASSING 04033 04034 if (n_unix_fds > loader->n_unix_fds) 04035 { 04036 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n", 04037 n_unix_fds, loader->n_unix_fds); 04038 04039 loader->corrupted = TRUE; 04040 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04041 goto failed; 04042 } 04043 04044 /* If this was a recycled message there might still be 04045 some memory allocated for the fds */ 04046 dbus_free(message->unix_fds); 04047 04048 if (n_unix_fds > 0) 04049 { 04050 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0])); 04051 if (message->unix_fds == NULL) 04052 { 04053 _dbus_verbose ("Failed to allocate file descriptor array\n"); 04054 oom = TRUE; 04055 goto failed; 04056 } 04057 04058 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; 04059 loader->n_unix_fds -= n_unix_fds; 04060 memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds); 04061 } 04062 else 04063 message->unix_fds = NULL; 04064 04065 #else 04066 04067 if (n_unix_fds > 0) 04068 { 04069 _dbus_verbose ("Hmm, message claims to come with file descriptors " 04070 "but that's not supported on our platform, disconnecting.\n"); 04071 04072 loader->corrupted = TRUE; 04073 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04074 goto failed; 04075 } 04076 04077 #endif 04078 04079 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 04080 04081 if (!_dbus_list_append (&loader->messages, message)) 04082 { 04083 _dbus_verbose ("Failed to append new message to loader queue\n"); 04084 oom = TRUE; 04085 goto failed; 04086 } 04087 04088 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 04089 _dbus_assert (_dbus_string_get_length (&loader->data) >= 04090 (header_len + body_len)); 04091 04092 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 04093 { 04094 _dbus_verbose ("Failed to move body into new message\n"); 04095 oom = TRUE; 04096 goto failed; 04097 } 04098 04099 _dbus_string_delete (&loader->data, 0, header_len + body_len); 04100 04101 /* don't waste more than 2k of memory */ 04102 _dbus_string_compact (&loader->data, 2048); 04103 04104 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 04105 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 04106 04107 _dbus_verbose ("Loaded message %p\n", message); 04108 04109 _dbus_assert (!oom); 04110 _dbus_assert (!loader->corrupted); 04111 _dbus_assert (loader->messages != NULL); 04112 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04113 04114 return TRUE; 04115 04116 failed: 04117 04118 /* Clean up */ 04119 04120 /* does nothing if the message isn't in the list */ 04121 _dbus_list_remove_last (&loader->messages, message); 04122 04123 if (oom) 04124 _dbus_assert (!loader->corrupted); 04125 else 04126 _dbus_assert (loader->corrupted); 04127 04128 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 04129 04130 return FALSE; 04131 } 04132 04147 dbus_bool_t 04148 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 04149 { 04150 while (!loader->corrupted && 04151 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 04152 { 04153 DBusValidity validity; 04154 int byte_order, fields_array_len, header_len, body_len; 04155 04156 if (_dbus_header_have_message_untrusted (loader->max_message_size, 04157 &validity, 04158 &byte_order, 04159 &fields_array_len, 04160 &header_len, 04161 &body_len, 04162 &loader->data, 0, 04163 _dbus_string_get_length (&loader->data))) 04164 { 04165 DBusMessage *message; 04166 04167 _dbus_assert (validity == DBUS_VALID); 04168 04169 message = dbus_message_new_empty_header (); 04170 if (message == NULL) 04171 return FALSE; 04172 04173 if (!load_message (loader, message, 04174 byte_order, fields_array_len, 04175 header_len, body_len)) 04176 { 04177 dbus_message_unref (message); 04178 /* load_message() returns false if corrupted or OOM; if 04179 * corrupted then return TRUE for not OOM 04180 */ 04181 return loader->corrupted; 04182 } 04183 04184 _dbus_assert (loader->messages != NULL); 04185 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04186 } 04187 else 04188 { 04189 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 04190 validity); 04191 if (validity != DBUS_VALID) 04192 { 04193 loader->corrupted = TRUE; 04194 loader->corruption_reason = validity; 04195 } 04196 return TRUE; 04197 } 04198 } 04199 04200 return TRUE; 04201 } 04202 04210 DBusMessage* 04211 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 04212 { 04213 if (loader->messages) 04214 return loader->messages->data; 04215 else 04216 return NULL; 04217 } 04218 04227 DBusMessage* 04228 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 04229 { 04230 return _dbus_list_pop_first (&loader->messages); 04231 } 04232 04241 DBusList* 04242 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 04243 { 04244 return _dbus_list_pop_first_link (&loader->messages); 04245 } 04246 04253 void 04254 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 04255 DBusList *link) 04256 { 04257 _dbus_list_prepend_link (&loader->messages, link); 04258 } 04259 04269 dbus_bool_t 04270 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 04271 { 04272 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04273 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04274 return loader->corrupted; 04275 } 04276 04283 DBusValidity 04284 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 04285 { 04286 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04287 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04288 04289 return loader->corruption_reason; 04290 } 04291 04298 void 04299 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 04300 long size) 04301 { 04302 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 04303 { 04304 _dbus_verbose ("clamping requested max message size %ld to %d\n", 04305 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 04306 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 04307 } 04308 loader->max_message_size = size; 04309 } 04310 04317 long 04318 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 04319 { 04320 return loader->max_message_size; 04321 } 04322 04329 void 04330 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, 04331 long n) 04332 { 04333 if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS) 04334 { 04335 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n", 04336 n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS); 04337 n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS; 04338 } 04339 loader->max_message_unix_fds = n; 04340 } 04341 04348 long 04349 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) 04350 { 04351 return loader->max_message_unix_fds; 04352 } 04353 04354 static DBusDataSlotAllocator slot_allocator; 04355 _DBUS_DEFINE_GLOBAL_LOCK (message_slots); 04356 04371 dbus_bool_t 04372 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 04373 { 04374 return _dbus_data_slot_allocator_alloc (&slot_allocator, 04375 &_DBUS_LOCK_NAME (message_slots), 04376 slot_p); 04377 } 04378 04390 void 04391 dbus_message_free_data_slot (dbus_int32_t *slot_p) 04392 { 04393 _dbus_return_if_fail (*slot_p >= 0); 04394 04395 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 04396 } 04397 04411 dbus_bool_t 04412 dbus_message_set_data (DBusMessage *message, 04413 dbus_int32_t slot, 04414 void *data, 04415 DBusFreeFunction free_data_func) 04416 { 04417 DBusFreeFunction old_free_func; 04418 void *old_data; 04419 dbus_bool_t retval; 04420 04421 _dbus_return_val_if_fail (message != NULL, FALSE); 04422 _dbus_return_val_if_fail (slot >= 0, FALSE); 04423 04424 retval = _dbus_data_slot_list_set (&slot_allocator, 04425 &message->slot_list, 04426 slot, data, free_data_func, 04427 &old_free_func, &old_data); 04428 04429 if (retval) 04430 { 04431 /* Do the actual free outside the message lock */ 04432 if (old_free_func) 04433 (* old_free_func) (old_data); 04434 } 04435 04436 return retval; 04437 } 04438 04447 void* 04448 dbus_message_get_data (DBusMessage *message, 04449 dbus_int32_t slot) 04450 { 04451 void *res; 04452 04453 _dbus_return_val_if_fail (message != NULL, NULL); 04454 04455 res = _dbus_data_slot_list_get (&slot_allocator, 04456 &message->slot_list, 04457 slot); 04458 04459 return res; 04460 } 04461 04475 int 04476 dbus_message_type_from_string (const char *type_str) 04477 { 04478 if (strcmp (type_str, "method_call") == 0) 04479 return DBUS_MESSAGE_TYPE_METHOD_CALL; 04480 if (strcmp (type_str, "method_return") == 0) 04481 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 04482 else if (strcmp (type_str, "signal") == 0) 04483 return DBUS_MESSAGE_TYPE_SIGNAL; 04484 else if (strcmp (type_str, "error") == 0) 04485 return DBUS_MESSAGE_TYPE_ERROR; 04486 else 04487 return DBUS_MESSAGE_TYPE_INVALID; 04488 } 04489 04503 const char * 04504 dbus_message_type_to_string (int type) 04505 { 04506 switch (type) 04507 { 04508 case DBUS_MESSAGE_TYPE_METHOD_CALL: 04509 return "method_call"; 04510 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 04511 return "method_return"; 04512 case DBUS_MESSAGE_TYPE_SIGNAL: 04513 return "signal"; 04514 case DBUS_MESSAGE_TYPE_ERROR: 04515 return "error"; 04516 default: 04517 return "invalid"; 04518 } 04519 } 04520 04533 dbus_bool_t 04534 dbus_message_marshal (DBusMessage *msg, 04535 char **marshalled_data_p, 04536 int *len_p) 04537 { 04538 DBusString tmp; 04539 dbus_bool_t was_locked; 04540 04541 _dbus_return_val_if_fail (msg != NULL, FALSE); 04542 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04543 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04544 04545 if (!_dbus_string_init (&tmp)) 04546 return FALSE; 04547 04548 /* Ensure the message is locked, to ensure the length header is filled in. */ 04549 was_locked = msg->locked; 04550 04551 if (!was_locked) 04552 dbus_message_lock (msg); 04553 04554 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04555 goto fail; 04556 04557 *len_p = _dbus_string_get_length (&tmp); 04558 04559 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04560 goto fail; 04561 04562 *len_p = _dbus_string_get_length (&tmp); 04563 04564 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04565 goto fail; 04566 04567 _dbus_string_free (&tmp); 04568 04569 if (!was_locked) 04570 msg->locked = FALSE; 04571 04572 return TRUE; 04573 04574 fail: 04575 _dbus_string_free (&tmp); 04576 04577 if (!was_locked) 04578 msg->locked = FALSE; 04579 04580 return FALSE; 04581 } 04582 04595 DBusMessage * 04596 dbus_message_demarshal (const char *str, 04597 int len, 04598 DBusError *error) 04599 { 04600 DBusMessageLoader *loader; 04601 DBusString *buffer; 04602 DBusMessage *msg; 04603 04604 _dbus_return_val_if_fail (str != NULL, NULL); 04605 04606 loader = _dbus_message_loader_new (); 04607 04608 if (loader == NULL) 04609 return NULL; 04610 04611 _dbus_message_loader_get_buffer (loader, &buffer); 04612 _dbus_string_append_len (buffer, str, len); 04613 _dbus_message_loader_return_buffer (loader, buffer, len); 04614 04615 if (!_dbus_message_loader_queue_messages (loader)) 04616 goto fail_oom; 04617 04618 if (_dbus_message_loader_get_is_corrupted (loader)) 04619 goto fail_corrupt; 04620 04621 msg = _dbus_message_loader_pop_message (loader); 04622 04623 if (!msg) 04624 goto fail_oom; 04625 04626 _dbus_message_loader_unref (loader); 04627 return msg; 04628 04629 fail_corrupt: 04630 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04631 _dbus_validity_to_error_message (loader->corruption_reason)); 04632 _dbus_message_loader_unref (loader); 04633 return NULL; 04634 04635 fail_oom: 04636 _DBUS_SET_OOM (error); 04637 _dbus_message_loader_unref (loader); 04638 return NULL; 04639 } 04640 04654 int 04655 dbus_message_demarshal_bytes_needed(const char *buf, 04656 int len) 04657 { 04658 DBusString str; 04659 int byte_order, fields_array_len, header_len, body_len; 04660 DBusValidity validity = DBUS_VALID; 04661 int have_message; 04662 04663 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04664 return 0; 04665 04666 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04667 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04668 _dbus_string_init_const_len (&str, buf, len); 04669 04670 validity = DBUS_VALID; 04671 have_message 04672 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04673 &validity, &byte_order, 04674 &fields_array_len, 04675 &header_len, 04676 &body_len, 04677 &str, 0, 04678 len); 04679 _dbus_string_free (&str); 04680 04681 if (validity == DBUS_VALID) 04682 { 04683 _dbus_assert(have_message); 04684 return header_len + body_len; 04685 } 04686 else 04687 { 04688 return -1; /* broken! */ 04689 } 04690 } 04691 04694 /* tests in dbus-message-util.c */