D-Bus 1.4.6
|
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 if (!_dbus_message_iter_open_signature (real)) 02519 return FALSE; 02520 02521 if (type == DBUS_TYPE_UNIX_FD) 02522 { 02523 #ifdef HAVE_UNIX_FD_PASSING 02524 int *fds; 02525 dbus_uint32_t u; 02526 02527 /* First step, include the fd in the fd list of this message */ 02528 if (!(fds = expand_fd_array(real->message, 1))) 02529 return FALSE; 02530 02531 *fds = _dbus_dup(*(int*) value, NULL); 02532 if (*fds < 0) 02533 return FALSE; 02534 02535 u = real->message->n_unix_fds; 02536 02537 /* Second step, write the index to the fd */ 02538 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) { 02539 _dbus_close(*fds, NULL); 02540 return FALSE; 02541 } 02542 02543 real->message->n_unix_fds += 1; 02544 u += 1; 02545 02546 /* Final step, update the header accordingly */ 02547 ret = _dbus_header_set_field_basic (&real->message->header, 02548 DBUS_HEADER_FIELD_UNIX_FDS, 02549 DBUS_TYPE_UINT32, 02550 &u); 02551 02552 /* If any of these operations fail the message is 02553 hosed. However, no memory or fds should be leaked since what 02554 has been added to message has been added to the message, and 02555 can hence be accounted for when the message is being 02556 freed. */ 02557 #else 02558 ret = FALSE; 02559 #endif 02560 } 02561 else 02562 { 02563 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02564 } 02565 02566 if (!_dbus_message_iter_close_signature (real)) 02567 ret = FALSE; 02568 02569 return ret; 02570 } 02571 02611 dbus_bool_t 02612 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02613 int element_type, 02614 const void *value, 02615 int n_elements) 02616 { 02617 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02618 dbus_bool_t ret; 02619 02620 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02621 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02622 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); 02623 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02624 _dbus_return_val_if_fail (value != NULL, FALSE); 02625 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02626 _dbus_return_val_if_fail (n_elements <= 02627 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02628 FALSE); 02629 02630 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02631 02632 return ret; 02633 } 02634 02656 dbus_bool_t 02657 dbus_message_iter_open_container (DBusMessageIter *iter, 02658 int type, 02659 const char *contained_signature, 02660 DBusMessageIter *sub) 02661 { 02662 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02663 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02664 DBusString contained_str; 02665 02666 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02667 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02668 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02669 _dbus_return_val_if_fail (sub != NULL, FALSE); 02670 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02671 contained_signature == NULL) || 02672 (type == DBUS_TYPE_DICT_ENTRY && 02673 contained_signature == NULL) || 02674 (type == DBUS_TYPE_VARIANT && 02675 contained_signature != NULL) || 02676 (type == DBUS_TYPE_ARRAY && 02677 contained_signature != NULL), FALSE); 02678 02679 /* this would fail if the contained_signature is a dict entry, since 02680 * dict entries are invalid signatures standalone (they must be in 02681 * an array) 02682 */ 02683 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02684 (contained_signature == NULL || 02685 _dbus_check_is_valid_signature (contained_signature)), 02686 FALSE); 02687 02688 if (!_dbus_message_iter_open_signature (real)) 02689 return FALSE; 02690 02691 *real_sub = *real; 02692 02693 if (contained_signature != NULL) 02694 { 02695 _dbus_string_init_const (&contained_str, contained_signature); 02696 02697 return _dbus_type_writer_recurse (&real->u.writer, 02698 type, 02699 &contained_str, 0, 02700 &real_sub->u.writer); 02701 } 02702 else 02703 { 02704 return _dbus_type_writer_recurse (&real->u.writer, 02705 type, 02706 NULL, 0, 02707 &real_sub->u.writer); 02708 } 02709 } 02710 02711 02725 dbus_bool_t 02726 dbus_message_iter_close_container (DBusMessageIter *iter, 02727 DBusMessageIter *sub) 02728 { 02729 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02730 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02731 dbus_bool_t ret; 02732 02733 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02734 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02735 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 02736 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02737 02738 ret = _dbus_type_writer_unrecurse (&real->u.writer, 02739 &real_sub->u.writer); 02740 02741 if (!_dbus_message_iter_close_signature (real)) 02742 ret = FALSE; 02743 02744 return ret; 02745 } 02746 02758 void 02759 dbus_message_iter_abandon_container (DBusMessageIter *iter, 02760 DBusMessageIter *sub) 02761 { 02762 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02763 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02764 02765 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 02766 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02767 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 02768 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02769 02770 _dbus_message_iter_abandon_signature (real); 02771 } 02772 02789 void 02790 dbus_message_set_no_reply (DBusMessage *message, 02791 dbus_bool_t no_reply) 02792 { 02793 _dbus_return_if_fail (message != NULL); 02794 _dbus_return_if_fail (!message->locked); 02795 02796 _dbus_header_toggle_flag (&message->header, 02797 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 02798 no_reply); 02799 } 02800 02808 dbus_bool_t 02809 dbus_message_get_no_reply (DBusMessage *message) 02810 { 02811 _dbus_return_val_if_fail (message != NULL, FALSE); 02812 02813 return _dbus_header_get_flag (&message->header, 02814 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 02815 } 02816 02831 void 02832 dbus_message_set_auto_start (DBusMessage *message, 02833 dbus_bool_t auto_start) 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_AUTO_START, 02840 !auto_start); 02841 } 02842 02850 dbus_bool_t 02851 dbus_message_get_auto_start (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_AUTO_START); 02857 } 02858 02859 02872 dbus_bool_t 02873 dbus_message_set_path (DBusMessage *message, 02874 const char *object_path) 02875 { 02876 _dbus_return_val_if_fail (message != NULL, FALSE); 02877 _dbus_return_val_if_fail (!message->locked, FALSE); 02878 _dbus_return_val_if_fail (object_path == NULL || 02879 _dbus_check_is_valid_path (object_path), 02880 FALSE); 02881 02882 return set_or_delete_string_field (message, 02883 DBUS_HEADER_FIELD_PATH, 02884 DBUS_TYPE_OBJECT_PATH, 02885 object_path); 02886 } 02887 02901 const char* 02902 dbus_message_get_path (DBusMessage *message) 02903 { 02904 const char *v; 02905 02906 _dbus_return_val_if_fail (message != NULL, NULL); 02907 02908 v = NULL; /* in case field doesn't exist */ 02909 _dbus_header_get_field_basic (&message->header, 02910 DBUS_HEADER_FIELD_PATH, 02911 DBUS_TYPE_OBJECT_PATH, 02912 (void *) &v); 02913 return v; 02914 } 02915 02925 dbus_bool_t 02926 dbus_message_has_path (DBusMessage *message, 02927 const char *path) 02928 { 02929 const char *msg_path; 02930 msg_path = dbus_message_get_path (message); 02931 02932 if (msg_path == NULL) 02933 { 02934 if (path == NULL) 02935 return TRUE; 02936 else 02937 return FALSE; 02938 } 02939 02940 if (path == NULL) 02941 return FALSE; 02942 02943 if (strcmp (msg_path, path) == 0) 02944 return TRUE; 02945 02946 return FALSE; 02947 } 02948 02969 dbus_bool_t 02970 dbus_message_get_path_decomposed (DBusMessage *message, 02971 char ***path) 02972 { 02973 const char *v; 02974 02975 _dbus_return_val_if_fail (message != NULL, FALSE); 02976 _dbus_return_val_if_fail (path != NULL, FALSE); 02977 02978 *path = NULL; 02979 02980 v = dbus_message_get_path (message); 02981 if (v != NULL) 02982 { 02983 if (!_dbus_decompose_path (v, strlen (v), 02984 path, NULL)) 02985 return FALSE; 02986 } 02987 return TRUE; 02988 } 02989 03003 dbus_bool_t 03004 dbus_message_set_interface (DBusMessage *message, 03005 const char *interface) 03006 { 03007 _dbus_return_val_if_fail (message != NULL, FALSE); 03008 _dbus_return_val_if_fail (!message->locked, FALSE); 03009 _dbus_return_val_if_fail (interface == NULL || 03010 _dbus_check_is_valid_interface (interface), 03011 FALSE); 03012 03013 return set_or_delete_string_field (message, 03014 DBUS_HEADER_FIELD_INTERFACE, 03015 DBUS_TYPE_STRING, 03016 interface); 03017 } 03018 03032 const char* 03033 dbus_message_get_interface (DBusMessage *message) 03034 { 03035 const char *v; 03036 03037 _dbus_return_val_if_fail (message != NULL, NULL); 03038 03039 v = NULL; /* in case field doesn't exist */ 03040 _dbus_header_get_field_basic (&message->header, 03041 DBUS_HEADER_FIELD_INTERFACE, 03042 DBUS_TYPE_STRING, 03043 (void *) &v); 03044 return v; 03045 } 03046 03054 dbus_bool_t 03055 dbus_message_has_interface (DBusMessage *message, 03056 const char *interface) 03057 { 03058 const char *msg_interface; 03059 msg_interface = dbus_message_get_interface (message); 03060 03061 if (msg_interface == NULL) 03062 { 03063 if (interface == NULL) 03064 return TRUE; 03065 else 03066 return FALSE; 03067 } 03068 03069 if (interface == NULL) 03070 return FALSE; 03071 03072 if (strcmp (msg_interface, interface) == 0) 03073 return TRUE; 03074 03075 return FALSE; 03076 03077 } 03078 03091 dbus_bool_t 03092 dbus_message_set_member (DBusMessage *message, 03093 const char *member) 03094 { 03095 _dbus_return_val_if_fail (message != NULL, FALSE); 03096 _dbus_return_val_if_fail (!message->locked, FALSE); 03097 _dbus_return_val_if_fail (member == NULL || 03098 _dbus_check_is_valid_member (member), 03099 FALSE); 03100 03101 return set_or_delete_string_field (message, 03102 DBUS_HEADER_FIELD_MEMBER, 03103 DBUS_TYPE_STRING, 03104 member); 03105 } 03106 03118 const char* 03119 dbus_message_get_member (DBusMessage *message) 03120 { 03121 const char *v; 03122 03123 _dbus_return_val_if_fail (message != NULL, NULL); 03124 03125 v = NULL; /* in case field doesn't exist */ 03126 _dbus_header_get_field_basic (&message->header, 03127 DBUS_HEADER_FIELD_MEMBER, 03128 DBUS_TYPE_STRING, 03129 (void *) &v); 03130 return v; 03131 } 03132 03140 dbus_bool_t 03141 dbus_message_has_member (DBusMessage *message, 03142 const char *member) 03143 { 03144 const char *msg_member; 03145 msg_member = dbus_message_get_member (message); 03146 03147 if (msg_member == NULL) 03148 { 03149 if (member == NULL) 03150 return TRUE; 03151 else 03152 return FALSE; 03153 } 03154 03155 if (member == NULL) 03156 return FALSE; 03157 03158 if (strcmp (msg_member, member) == 0) 03159 return TRUE; 03160 03161 return FALSE; 03162 03163 } 03164 03176 dbus_bool_t 03177 dbus_message_set_error_name (DBusMessage *message, 03178 const char *error_name) 03179 { 03180 _dbus_return_val_if_fail (message != NULL, FALSE); 03181 _dbus_return_val_if_fail (!message->locked, FALSE); 03182 _dbus_return_val_if_fail (error_name == NULL || 03183 _dbus_check_is_valid_error_name (error_name), 03184 FALSE); 03185 03186 return set_or_delete_string_field (message, 03187 DBUS_HEADER_FIELD_ERROR_NAME, 03188 DBUS_TYPE_STRING, 03189 error_name); 03190 } 03191 03202 const char* 03203 dbus_message_get_error_name (DBusMessage *message) 03204 { 03205 const char *v; 03206 03207 _dbus_return_val_if_fail (message != NULL, NULL); 03208 03209 v = NULL; /* in case field doesn't exist */ 03210 _dbus_header_get_field_basic (&message->header, 03211 DBUS_HEADER_FIELD_ERROR_NAME, 03212 DBUS_TYPE_STRING, 03213 (void *) &v); 03214 return v; 03215 } 03216 03230 dbus_bool_t 03231 dbus_message_set_destination (DBusMessage *message, 03232 const char *destination) 03233 { 03234 _dbus_return_val_if_fail (message != NULL, FALSE); 03235 _dbus_return_val_if_fail (!message->locked, FALSE); 03236 _dbus_return_val_if_fail (destination == NULL || 03237 _dbus_check_is_valid_bus_name (destination), 03238 FALSE); 03239 03240 return set_or_delete_string_field (message, 03241 DBUS_HEADER_FIELD_DESTINATION, 03242 DBUS_TYPE_STRING, 03243 destination); 03244 } 03245 03255 const char* 03256 dbus_message_get_destination (DBusMessage *message) 03257 { 03258 const char *v; 03259 03260 _dbus_return_val_if_fail (message != NULL, NULL); 03261 03262 v = NULL; /* in case field doesn't exist */ 03263 _dbus_header_get_field_basic (&message->header, 03264 DBUS_HEADER_FIELD_DESTINATION, 03265 DBUS_TYPE_STRING, 03266 (void *) &v); 03267 return v; 03268 } 03269 03284 dbus_bool_t 03285 dbus_message_set_sender (DBusMessage *message, 03286 const char *sender) 03287 { 03288 _dbus_return_val_if_fail (message != NULL, FALSE); 03289 _dbus_return_val_if_fail (!message->locked, FALSE); 03290 _dbus_return_val_if_fail (sender == NULL || 03291 _dbus_check_is_valid_bus_name (sender), 03292 FALSE); 03293 03294 return set_or_delete_string_field (message, 03295 DBUS_HEADER_FIELD_SENDER, 03296 DBUS_TYPE_STRING, 03297 sender); 03298 } 03299 03315 const char* 03316 dbus_message_get_sender (DBusMessage *message) 03317 { 03318 const char *v; 03319 03320 _dbus_return_val_if_fail (message != NULL, NULL); 03321 03322 v = NULL; /* in case field doesn't exist */ 03323 _dbus_header_get_field_basic (&message->header, 03324 DBUS_HEADER_FIELD_SENDER, 03325 DBUS_TYPE_STRING, 03326 (void *) &v); 03327 return v; 03328 } 03329 03348 const char* 03349 dbus_message_get_signature (DBusMessage *message) 03350 { 03351 const DBusString *type_str; 03352 int type_pos; 03353 03354 _dbus_return_val_if_fail (message != NULL, NULL); 03355 03356 get_const_signature (&message->header, &type_str, &type_pos); 03357 03358 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03359 } 03360 03361 static dbus_bool_t 03362 _dbus_message_has_type_interface_member (DBusMessage *message, 03363 int type, 03364 const char *interface, 03365 const char *member) 03366 { 03367 const char *n; 03368 03369 _dbus_assert (message != NULL); 03370 _dbus_assert (interface != NULL); 03371 _dbus_assert (member != NULL); 03372 03373 if (dbus_message_get_type (message) != type) 03374 return FALSE; 03375 03376 /* Optimize by checking the short member name first 03377 * instead of the longer interface name 03378 */ 03379 03380 n = dbus_message_get_member (message); 03381 03382 if (n && strcmp (n, member) == 0) 03383 { 03384 n = dbus_message_get_interface (message); 03385 03386 if (n == NULL || strcmp (n, interface) == 0) 03387 return TRUE; 03388 } 03389 03390 return FALSE; 03391 } 03392 03407 dbus_bool_t 03408 dbus_message_is_method_call (DBusMessage *message, 03409 const char *interface, 03410 const char *method) 03411 { 03412 _dbus_return_val_if_fail (message != NULL, FALSE); 03413 _dbus_return_val_if_fail (interface != NULL, FALSE); 03414 _dbus_return_val_if_fail (method != NULL, FALSE); 03415 /* don't check that interface/method are valid since it would be 03416 * expensive, and not catch many common errors 03417 */ 03418 03419 return _dbus_message_has_type_interface_member (message, 03420 DBUS_MESSAGE_TYPE_METHOD_CALL, 03421 interface, method); 03422 } 03423 03435 dbus_bool_t 03436 dbus_message_is_signal (DBusMessage *message, 03437 const char *interface, 03438 const char *signal_name) 03439 { 03440 _dbus_return_val_if_fail (message != NULL, FALSE); 03441 _dbus_return_val_if_fail (interface != NULL, FALSE); 03442 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03443 /* don't check that interface/name are valid since it would be 03444 * expensive, and not catch many common errors 03445 */ 03446 03447 return _dbus_message_has_type_interface_member (message, 03448 DBUS_MESSAGE_TYPE_SIGNAL, 03449 interface, signal_name); 03450 } 03451 03462 dbus_bool_t 03463 dbus_message_is_error (DBusMessage *message, 03464 const char *error_name) 03465 { 03466 const char *n; 03467 03468 _dbus_return_val_if_fail (message != NULL, FALSE); 03469 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03470 /* don't check that error_name is valid since it would be expensive, 03471 * and not catch many common errors 03472 */ 03473 03474 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03475 return FALSE; 03476 03477 n = dbus_message_get_error_name (message); 03478 03479 if (n && strcmp (n, error_name) == 0) 03480 return TRUE; 03481 else 03482 return FALSE; 03483 } 03484 03495 dbus_bool_t 03496 dbus_message_has_destination (DBusMessage *message, 03497 const char *name) 03498 { 03499 const char *s; 03500 03501 _dbus_return_val_if_fail (message != NULL, FALSE); 03502 _dbus_return_val_if_fail (name != NULL, FALSE); 03503 /* don't check that name is valid since it would be expensive, and 03504 * not catch many common errors 03505 */ 03506 03507 s = dbus_message_get_destination (message); 03508 03509 if (s && strcmp (s, name) == 0) 03510 return TRUE; 03511 else 03512 return FALSE; 03513 } 03514 03530 dbus_bool_t 03531 dbus_message_has_sender (DBusMessage *message, 03532 const char *name) 03533 { 03534 const char *s; 03535 03536 _dbus_return_val_if_fail (message != NULL, FALSE); 03537 _dbus_return_val_if_fail (name != NULL, FALSE); 03538 /* don't check that name is valid since it would be expensive, and 03539 * not catch many common errors 03540 */ 03541 03542 s = dbus_message_get_sender (message); 03543 03544 if (s && strcmp (s, name) == 0) 03545 return TRUE; 03546 else 03547 return FALSE; 03548 } 03549 03559 dbus_bool_t 03560 dbus_message_has_signature (DBusMessage *message, 03561 const char *signature) 03562 { 03563 const char *s; 03564 03565 _dbus_return_val_if_fail (message != NULL, FALSE); 03566 _dbus_return_val_if_fail (signature != NULL, FALSE); 03567 /* don't check that signature is valid since it would be expensive, 03568 * and not catch many common errors 03569 */ 03570 03571 s = dbus_message_get_signature (message); 03572 03573 if (s && strcmp (s, signature) == 0) 03574 return TRUE; 03575 else 03576 return FALSE; 03577 } 03578 03601 dbus_bool_t 03602 dbus_set_error_from_message (DBusError *error, 03603 DBusMessage *message) 03604 { 03605 const char *str; 03606 03607 _dbus_return_val_if_fail (message != NULL, FALSE); 03608 _dbus_return_val_if_error_is_set (error, FALSE); 03609 03610 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03611 return FALSE; 03612 03613 str = NULL; 03614 dbus_message_get_args (message, NULL, 03615 DBUS_TYPE_STRING, &str, 03616 DBUS_TYPE_INVALID); 03617 03618 dbus_set_error (error, dbus_message_get_error_name (message), 03619 str ? "%s" : NULL, str); 03620 03621 return TRUE; 03622 } 03623 03630 dbus_bool_t 03631 dbus_message_contains_unix_fds(DBusMessage *message) 03632 { 03633 #ifdef HAVE_UNIX_FD_PASSING 03634 _dbus_assert(message); 03635 03636 return message->n_unix_fds > 0; 03637 #else 03638 return FALSE; 03639 #endif 03640 } 03641 03660 #define INITIAL_LOADER_DATA_LEN 32 03661 03668 DBusMessageLoader* 03669 _dbus_message_loader_new (void) 03670 { 03671 DBusMessageLoader *loader; 03672 03673 loader = dbus_new0 (DBusMessageLoader, 1); 03674 if (loader == NULL) 03675 return NULL; 03676 03677 loader->refcount = 1; 03678 03679 loader->corrupted = FALSE; 03680 loader->corruption_reason = DBUS_VALID; 03681 03682 /* this can be configured by the app, but defaults to the protocol max */ 03683 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03684 03685 /* We set a very relatively conservative default here since due to how 03686 SCM_RIGHTS works we need to preallocate an fd array of the maximum 03687 number of unix fds we want to receive in advance. A 03688 try-and-reallocate loop is not possible. */ 03689 loader->max_message_unix_fds = 1024; 03690 03691 if (!_dbus_string_init (&loader->data)) 03692 { 03693 dbus_free (loader); 03694 return NULL; 03695 } 03696 03697 /* preallocate the buffer for speed, ignore failure */ 03698 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03699 _dbus_string_set_length (&loader->data, 0); 03700 03701 #ifdef HAVE_UNIX_FD_PASSING 03702 loader->unix_fds = NULL; 03703 loader->n_unix_fds = loader->n_unix_fds_allocated = 0; 03704 loader->unix_fds_outstanding = FALSE; 03705 #endif 03706 03707 return loader; 03708 } 03709 03716 DBusMessageLoader * 03717 _dbus_message_loader_ref (DBusMessageLoader *loader) 03718 { 03719 loader->refcount += 1; 03720 03721 return loader; 03722 } 03723 03730 void 03731 _dbus_message_loader_unref (DBusMessageLoader *loader) 03732 { 03733 loader->refcount -= 1; 03734 if (loader->refcount == 0) 03735 { 03736 #ifdef HAVE_UNIX_FD_PASSING 03737 close_unix_fds(loader->unix_fds, &loader->n_unix_fds); 03738 dbus_free(loader->unix_fds); 03739 #endif 03740 _dbus_list_foreach (&loader->messages, 03741 (DBusForeachFunction) dbus_message_unref, 03742 NULL); 03743 _dbus_list_clear (&loader->messages); 03744 _dbus_string_free (&loader->data); 03745 dbus_free (loader); 03746 } 03747 } 03748 03767 void 03768 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 03769 DBusString **buffer) 03770 { 03771 _dbus_assert (!loader->buffer_outstanding); 03772 03773 *buffer = &loader->data; 03774 03775 loader->buffer_outstanding = TRUE; 03776 } 03777 03788 void 03789 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 03790 DBusString *buffer, 03791 int bytes_read) 03792 { 03793 _dbus_assert (loader->buffer_outstanding); 03794 _dbus_assert (buffer == &loader->data); 03795 03796 loader->buffer_outstanding = FALSE; 03797 } 03798 03809 dbus_bool_t 03810 _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, 03811 int **fds, 03812 unsigned *max_n_fds) 03813 { 03814 #ifdef HAVE_UNIX_FD_PASSING 03815 _dbus_assert (!loader->unix_fds_outstanding); 03816 03817 /* Allocate space where we can put the fds we read. We allocate 03818 space for max_message_unix_fds since this is an 03819 upper limit how many fds can be received within a single 03820 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic 03821 we are allocating the maximum possible array size right from the 03822 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed 03823 there is no better way. */ 03824 03825 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds) 03826 { 03827 int *a = dbus_realloc(loader->unix_fds, 03828 loader->max_message_unix_fds * sizeof(loader->unix_fds[0])); 03829 03830 if (!a) 03831 return FALSE; 03832 03833 loader->unix_fds = a; 03834 loader->n_unix_fds_allocated = loader->max_message_unix_fds; 03835 } 03836 03837 *fds = loader->unix_fds + loader->n_unix_fds; 03838 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds; 03839 03840 loader->unix_fds_outstanding = TRUE; 03841 return TRUE; 03842 #else 03843 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03844 return FALSE; 03845 #endif 03846 } 03847 03858 void 03859 _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, 03860 int *fds, 03861 unsigned n_fds) 03862 { 03863 #ifdef HAVE_UNIX_FD_PASSING 03864 _dbus_assert(loader->unix_fds_outstanding); 03865 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds); 03866 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated); 03867 03868 loader->n_unix_fds += n_fds; 03869 loader->unix_fds_outstanding = FALSE; 03870 #else 03871 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03872 #endif 03873 } 03874 03875 /* 03876 * FIXME when we move the header out of the buffer, that memmoves all 03877 * buffered messages. Kind of crappy. 03878 * 03879 * Also we copy the header and body, which is kind of crappy. To 03880 * avoid this, we have to allow header and body to be in a single 03881 * memory block, which is good for messages we read and bad for 03882 * messages we are creating. But we could move_len() the buffer into 03883 * this single memory block, and move_len() will just swap the buffers 03884 * if you're moving the entire buffer replacing the dest string. 03885 * 03886 * We could also have the message loader tell the transport how many 03887 * bytes to read; so it would first ask for some arbitrary number like 03888 * 256, then if the message was incomplete it would use the 03889 * header/body len to ask for exactly the size of the message (or 03890 * blocks the size of a typical kernel buffer for the socket). That 03891 * way we don't get trailing bytes in the buffer that have to be 03892 * memmoved. Though I suppose we also don't have a chance of reading a 03893 * bunch of small messages at once, so the optimization may be stupid. 03894 * 03895 * Another approach would be to keep a "start" index into 03896 * loader->data and only delete it occasionally, instead of after 03897 * each message is loaded. 03898 * 03899 * load_message() returns FALSE if not enough memory OR the loader was corrupted 03900 */ 03901 static dbus_bool_t 03902 load_message (DBusMessageLoader *loader, 03903 DBusMessage *message, 03904 int byte_order, 03905 int fields_array_len, 03906 int header_len, 03907 int body_len) 03908 { 03909 dbus_bool_t oom; 03910 DBusValidity validity; 03911 const DBusString *type_str; 03912 int type_pos; 03913 DBusValidationMode mode; 03914 dbus_uint32_t n_unix_fds = 0; 03915 03916 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 03917 03918 oom = FALSE; 03919 03920 #if 0 03921 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 03922 #endif 03923 03924 /* 1. VALIDATE AND COPY OVER HEADER */ 03925 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 03926 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 03927 03928 if (!_dbus_header_load (&message->header, 03929 mode, 03930 &validity, 03931 byte_order, 03932 fields_array_len, 03933 header_len, 03934 body_len, 03935 &loader->data, 0, 03936 _dbus_string_get_length (&loader->data))) 03937 { 03938 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 03939 03940 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 03941 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 03942 _dbus_assert (validity != DBUS_VALID); 03943 03944 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 03945 oom = TRUE; 03946 else 03947 { 03948 loader->corrupted = TRUE; 03949 loader->corruption_reason = validity; 03950 } 03951 goto failed; 03952 } 03953 03954 _dbus_assert (validity == DBUS_VALID); 03955 03956 message->byte_order = byte_order; 03957 03958 /* 2. VALIDATE BODY */ 03959 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 03960 { 03961 get_const_signature (&message->header, &type_str, &type_pos); 03962 03963 /* Because the bytes_remaining arg is NULL, this validates that the 03964 * body is the right length 03965 */ 03966 validity = _dbus_validate_body_with_reason (type_str, 03967 type_pos, 03968 byte_order, 03969 NULL, 03970 &loader->data, 03971 header_len, 03972 body_len); 03973 if (validity != DBUS_VALID) 03974 { 03975 _dbus_verbose ("Failed to validate message body code %d\n", validity); 03976 03977 loader->corrupted = TRUE; 03978 loader->corruption_reason = validity; 03979 03980 goto failed; 03981 } 03982 } 03983 03984 /* 3. COPY OVER UNIX FDS */ 03985 _dbus_header_get_field_basic(&message->header, 03986 DBUS_HEADER_FIELD_UNIX_FDS, 03987 DBUS_TYPE_UINT32, 03988 &n_unix_fds); 03989 03990 #ifdef HAVE_UNIX_FD_PASSING 03991 03992 if (n_unix_fds > loader->n_unix_fds) 03993 { 03994 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n", 03995 n_unix_fds, loader->n_unix_fds); 03996 03997 loader->corrupted = TRUE; 03998 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 03999 goto failed; 04000 } 04001 04002 /* If this was a recycled message there might still be 04003 some memory allocated for the fds */ 04004 dbus_free(message->unix_fds); 04005 04006 if (n_unix_fds > 0) 04007 { 04008 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0])); 04009 if (message->unix_fds == NULL) 04010 { 04011 _dbus_verbose ("Failed to allocate file descriptor array\n"); 04012 oom = TRUE; 04013 goto failed; 04014 } 04015 04016 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; 04017 loader->n_unix_fds -= n_unix_fds; 04018 memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds); 04019 } 04020 else 04021 message->unix_fds = NULL; 04022 04023 #else 04024 04025 if (n_unix_fds > 0) 04026 { 04027 _dbus_verbose ("Hmm, message claims to come with file descriptors " 04028 "but that's not supported on our platform, disconnecting.\n"); 04029 04030 loader->corrupted = TRUE; 04031 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04032 goto failed; 04033 } 04034 04035 #endif 04036 04037 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 04038 04039 if (!_dbus_list_append (&loader->messages, message)) 04040 { 04041 _dbus_verbose ("Failed to append new message to loader queue\n"); 04042 oom = TRUE; 04043 goto failed; 04044 } 04045 04046 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 04047 _dbus_assert (_dbus_string_get_length (&loader->data) >= 04048 (header_len + body_len)); 04049 04050 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 04051 { 04052 _dbus_verbose ("Failed to move body into new message\n"); 04053 oom = TRUE; 04054 goto failed; 04055 } 04056 04057 _dbus_string_delete (&loader->data, 0, header_len + body_len); 04058 04059 /* don't waste more than 2k of memory */ 04060 _dbus_string_compact (&loader->data, 2048); 04061 04062 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 04063 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 04064 04065 _dbus_verbose ("Loaded message %p\n", message); 04066 04067 _dbus_assert (!oom); 04068 _dbus_assert (!loader->corrupted); 04069 _dbus_assert (loader->messages != NULL); 04070 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04071 04072 return TRUE; 04073 04074 failed: 04075 04076 /* Clean up */ 04077 04078 /* does nothing if the message isn't in the list */ 04079 _dbus_list_remove_last (&loader->messages, message); 04080 04081 if (oom) 04082 _dbus_assert (!loader->corrupted); 04083 else 04084 _dbus_assert (loader->corrupted); 04085 04086 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 04087 04088 return FALSE; 04089 } 04090 04105 dbus_bool_t 04106 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 04107 { 04108 while (!loader->corrupted && 04109 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 04110 { 04111 DBusValidity validity; 04112 int byte_order, fields_array_len, header_len, body_len; 04113 04114 if (_dbus_header_have_message_untrusted (loader->max_message_size, 04115 &validity, 04116 &byte_order, 04117 &fields_array_len, 04118 &header_len, 04119 &body_len, 04120 &loader->data, 0, 04121 _dbus_string_get_length (&loader->data))) 04122 { 04123 DBusMessage *message; 04124 04125 _dbus_assert (validity == DBUS_VALID); 04126 04127 message = dbus_message_new_empty_header (); 04128 if (message == NULL) 04129 return FALSE; 04130 04131 if (!load_message (loader, message, 04132 byte_order, fields_array_len, 04133 header_len, body_len)) 04134 { 04135 dbus_message_unref (message); 04136 /* load_message() returns false if corrupted or OOM; if 04137 * corrupted then return TRUE for not OOM 04138 */ 04139 return loader->corrupted; 04140 } 04141 04142 _dbus_assert (loader->messages != NULL); 04143 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04144 } 04145 else 04146 { 04147 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 04148 validity); 04149 if (validity != DBUS_VALID) 04150 { 04151 loader->corrupted = TRUE; 04152 loader->corruption_reason = validity; 04153 } 04154 return TRUE; 04155 } 04156 } 04157 04158 return TRUE; 04159 } 04160 04168 DBusMessage* 04169 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 04170 { 04171 if (loader->messages) 04172 return loader->messages->data; 04173 else 04174 return NULL; 04175 } 04176 04185 DBusMessage* 04186 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 04187 { 04188 return _dbus_list_pop_first (&loader->messages); 04189 } 04190 04199 DBusList* 04200 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 04201 { 04202 return _dbus_list_pop_first_link (&loader->messages); 04203 } 04204 04211 void 04212 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 04213 DBusList *link) 04214 { 04215 _dbus_list_prepend_link (&loader->messages, link); 04216 } 04217 04227 dbus_bool_t 04228 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 04229 { 04230 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04231 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04232 return loader->corrupted; 04233 } 04234 04241 DBusValidity 04242 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 04243 { 04244 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04245 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04246 04247 return loader->corruption_reason; 04248 } 04249 04256 void 04257 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 04258 long size) 04259 { 04260 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 04261 { 04262 _dbus_verbose ("clamping requested max message size %ld to %d\n", 04263 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 04264 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 04265 } 04266 loader->max_message_size = size; 04267 } 04268 04275 long 04276 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 04277 { 04278 return loader->max_message_size; 04279 } 04280 04287 void 04288 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, 04289 long n) 04290 { 04291 if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS) 04292 { 04293 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n", 04294 n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS); 04295 n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS; 04296 } 04297 loader->max_message_unix_fds = n; 04298 } 04299 04306 long 04307 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) 04308 { 04309 return loader->max_message_unix_fds; 04310 } 04311 04312 static DBusDataSlotAllocator slot_allocator; 04313 _DBUS_DEFINE_GLOBAL_LOCK (message_slots); 04314 04329 dbus_bool_t 04330 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 04331 { 04332 return _dbus_data_slot_allocator_alloc (&slot_allocator, 04333 &_DBUS_LOCK_NAME (message_slots), 04334 slot_p); 04335 } 04336 04348 void 04349 dbus_message_free_data_slot (dbus_int32_t *slot_p) 04350 { 04351 _dbus_return_if_fail (*slot_p >= 0); 04352 04353 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 04354 } 04355 04369 dbus_bool_t 04370 dbus_message_set_data (DBusMessage *message, 04371 dbus_int32_t slot, 04372 void *data, 04373 DBusFreeFunction free_data_func) 04374 { 04375 DBusFreeFunction old_free_func; 04376 void *old_data; 04377 dbus_bool_t retval; 04378 04379 _dbus_return_val_if_fail (message != NULL, FALSE); 04380 _dbus_return_val_if_fail (slot >= 0, FALSE); 04381 04382 retval = _dbus_data_slot_list_set (&slot_allocator, 04383 &message->slot_list, 04384 slot, data, free_data_func, 04385 &old_free_func, &old_data); 04386 04387 if (retval) 04388 { 04389 /* Do the actual free outside the message lock */ 04390 if (old_free_func) 04391 (* old_free_func) (old_data); 04392 } 04393 04394 return retval; 04395 } 04396 04405 void* 04406 dbus_message_get_data (DBusMessage *message, 04407 dbus_int32_t slot) 04408 { 04409 void *res; 04410 04411 _dbus_return_val_if_fail (message != NULL, NULL); 04412 04413 res = _dbus_data_slot_list_get (&slot_allocator, 04414 &message->slot_list, 04415 slot); 04416 04417 return res; 04418 } 04419 04433 int 04434 dbus_message_type_from_string (const char *type_str) 04435 { 04436 if (strcmp (type_str, "method_call") == 0) 04437 return DBUS_MESSAGE_TYPE_METHOD_CALL; 04438 if (strcmp (type_str, "method_return") == 0) 04439 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 04440 else if (strcmp (type_str, "signal") == 0) 04441 return DBUS_MESSAGE_TYPE_SIGNAL; 04442 else if (strcmp (type_str, "error") == 0) 04443 return DBUS_MESSAGE_TYPE_ERROR; 04444 else 04445 return DBUS_MESSAGE_TYPE_INVALID; 04446 } 04447 04461 const char * 04462 dbus_message_type_to_string (int type) 04463 { 04464 switch (type) 04465 { 04466 case DBUS_MESSAGE_TYPE_METHOD_CALL: 04467 return "method_call"; 04468 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 04469 return "method_return"; 04470 case DBUS_MESSAGE_TYPE_SIGNAL: 04471 return "signal"; 04472 case DBUS_MESSAGE_TYPE_ERROR: 04473 return "error"; 04474 default: 04475 return "invalid"; 04476 } 04477 } 04478 04491 dbus_bool_t 04492 dbus_message_marshal (DBusMessage *msg, 04493 char **marshalled_data_p, 04494 int *len_p) 04495 { 04496 DBusString tmp; 04497 dbus_bool_t was_locked; 04498 04499 _dbus_return_val_if_fail (msg != NULL, FALSE); 04500 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04501 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04502 04503 if (!_dbus_string_init (&tmp)) 04504 return FALSE; 04505 04506 /* Ensure the message is locked, to ensure the length header is filled in. */ 04507 was_locked = msg->locked; 04508 04509 if (!was_locked) 04510 dbus_message_lock (msg); 04511 04512 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04513 goto fail; 04514 04515 *len_p = _dbus_string_get_length (&tmp); 04516 04517 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04518 goto fail; 04519 04520 *len_p = _dbus_string_get_length (&tmp); 04521 04522 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04523 goto fail; 04524 04525 _dbus_string_free (&tmp); 04526 04527 if (!was_locked) 04528 msg->locked = FALSE; 04529 04530 return TRUE; 04531 04532 fail: 04533 _dbus_string_free (&tmp); 04534 04535 if (!was_locked) 04536 msg->locked = FALSE; 04537 04538 return FALSE; 04539 } 04540 04553 DBusMessage * 04554 dbus_message_demarshal (const char *str, 04555 int len, 04556 DBusError *error) 04557 { 04558 DBusMessageLoader *loader; 04559 DBusString *buffer; 04560 DBusMessage *msg; 04561 04562 _dbus_return_val_if_fail (str != NULL, NULL); 04563 04564 loader = _dbus_message_loader_new (); 04565 04566 if (loader == NULL) 04567 return NULL; 04568 04569 _dbus_message_loader_get_buffer (loader, &buffer); 04570 _dbus_string_append_len (buffer, str, len); 04571 _dbus_message_loader_return_buffer (loader, buffer, len); 04572 04573 if (!_dbus_message_loader_queue_messages (loader)) 04574 goto fail_oom; 04575 04576 if (_dbus_message_loader_get_is_corrupted (loader)) 04577 goto fail_corrupt; 04578 04579 msg = _dbus_message_loader_pop_message (loader); 04580 04581 if (!msg) 04582 goto fail_oom; 04583 04584 _dbus_message_loader_unref (loader); 04585 return msg; 04586 04587 fail_corrupt: 04588 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04589 _dbus_validity_to_error_message (loader->corruption_reason)); 04590 _dbus_message_loader_unref (loader); 04591 return NULL; 04592 04593 fail_oom: 04594 _DBUS_SET_OOM (error); 04595 _dbus_message_loader_unref (loader); 04596 return NULL; 04597 } 04598 04612 int 04613 dbus_message_demarshal_bytes_needed(const char *buf, 04614 int len) 04615 { 04616 DBusString str; 04617 int byte_order, fields_array_len, header_len, body_len; 04618 DBusValidity validity = DBUS_VALID; 04619 int have_message; 04620 04621 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04622 return 0; 04623 04624 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04625 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04626 _dbus_string_init_const_len (&str, buf, len); 04627 04628 validity = DBUS_VALID; 04629 have_message 04630 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04631 &validity, &byte_order, 04632 &fields_array_len, 04633 &header_len, 04634 &body_len, 04635 &str, 0, 04636 len); 04637 _dbus_string_free (&str); 04638 04639 if (validity == DBUS_VALID) 04640 { 04641 _dbus_assert(have_message); 04642 return header_len + body_len; 04643 } 04644 else 04645 { 04646 return -1; /* broken! */ 04647 } 04648 } 04649 04652 /* tests in dbus-message-util.c */