D-Bus
1.4.18
|
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 (_dbus_atomic_get (&message->refcount) == 0); 00530 00531 _dbus_assert (message->counters == NULL); 00532 00533 _DBUS_UNLOCK (message_cache); 00534 00535 return message; 00536 } 00537 00538 #ifdef HAVE_UNIX_FD_PASSING 00539 static void 00540 close_unix_fds(int *fds, unsigned *n_fds) 00541 { 00542 DBusError e; 00543 int i; 00544 00545 if (*n_fds <= 0) 00546 return; 00547 00548 dbus_error_init(&e); 00549 00550 for (i = 0; i < *n_fds; i++) 00551 { 00552 if (!_dbus_close(fds[i], &e)) 00553 { 00554 _dbus_warn("Failed to close file descriptor: %s\n", e.message); 00555 dbus_error_free(&e); 00556 } 00557 } 00558 00559 *n_fds = 0; 00560 00561 /* We don't free the array here, in case we can recycle it later */ 00562 } 00563 #endif 00564 00565 static void 00566 free_counter (void *element, 00567 void *data) 00568 { 00569 DBusCounter *counter = element; 00570 DBusMessage *message = data; 00571 00572 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00573 #ifdef HAVE_UNIX_FD_PASSING 00574 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00575 #endif 00576 00577 _dbus_counter_unref (counter); 00578 } 00579 00585 static void 00586 dbus_message_cache_or_finalize (DBusMessage *message) 00587 { 00588 dbus_bool_t was_cached; 00589 int i; 00590 00591 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00592 00593 /* This calls application code and has to be done first thing 00594 * without holding the lock 00595 */ 00596 _dbus_data_slot_list_clear (&message->slot_list); 00597 00598 _dbus_list_foreach (&message->counters, 00599 free_counter, message); 00600 _dbus_list_clear (&message->counters); 00601 00602 #ifdef HAVE_UNIX_FD_PASSING 00603 close_unix_fds(message->unix_fds, &message->n_unix_fds); 00604 #endif 00605 00606 was_cached = FALSE; 00607 00608 _DBUS_LOCK (message_cache); 00609 00610 if (!message_cache_shutdown_registered) 00611 { 00612 _dbus_assert (message_cache_count == 0); 00613 00614 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL)) 00615 goto out; 00616 00617 i = 0; 00618 while (i < MAX_MESSAGE_CACHE_SIZE) 00619 { 00620 message_cache[i] = NULL; 00621 ++i; 00622 } 00623 00624 message_cache_shutdown_registered = TRUE; 00625 } 00626 00627 _dbus_assert (message_cache_count >= 0); 00628 00629 if ((_dbus_string_get_length (&message->header.data) + 00630 _dbus_string_get_length (&message->body)) > 00631 MAX_MESSAGE_SIZE_TO_CACHE) 00632 goto out; 00633 00634 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE) 00635 goto out; 00636 00637 /* Find empty slot */ 00638 i = 0; 00639 while (message_cache[i] != NULL) 00640 ++i; 00641 00642 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00643 00644 _dbus_assert (message_cache[i] == NULL); 00645 message_cache[i] = message; 00646 message_cache_count += 1; 00647 was_cached = TRUE; 00648 #ifndef DBUS_DISABLE_CHECKS 00649 message->in_cache = TRUE; 00650 #endif 00651 00652 out: 00653 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00654 00655 _DBUS_UNLOCK (message_cache); 00656 00657 if (!was_cached) 00658 dbus_message_finalize (message); 00659 } 00660 00661 #ifndef DBUS_DISABLE_CHECKS 00662 static dbus_bool_t 00663 _dbus_message_iter_check (DBusMessageRealIter *iter) 00664 { 00665 if (iter == NULL) 00666 { 00667 _dbus_warn_check_failed ("dbus message iterator is NULL\n"); 00668 return FALSE; 00669 } 00670 00671 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER) 00672 { 00673 if (iter->u.reader.byte_order != iter->message->byte_order) 00674 { 00675 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n"); 00676 return FALSE; 00677 } 00678 /* because we swap the message into compiler order when you init an iter */ 00679 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); 00680 } 00681 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) 00682 { 00683 if (iter->u.writer.byte_order != iter->message->byte_order) 00684 { 00685 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n"); 00686 return FALSE; 00687 } 00688 /* because we swap the message into compiler order when you init an iter */ 00689 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); 00690 } 00691 else 00692 { 00693 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n"); 00694 return FALSE; 00695 } 00696 00697 if (iter->changed_stamp != iter->message->changed_stamp) 00698 { 00699 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); 00700 return FALSE; 00701 } 00702 00703 return TRUE; 00704 } 00705 #endif /* DBUS_DISABLE_CHECKS */ 00706 00721 dbus_bool_t 00722 _dbus_message_iter_get_args_valist (DBusMessageIter *iter, 00723 DBusError *error, 00724 int first_arg_type, 00725 va_list var_args) 00726 { 00727 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 00728 int spec_type, msg_type, i; 00729 dbus_bool_t retval; 00730 00731 _dbus_assert (_dbus_message_iter_check (real)); 00732 00733 retval = FALSE; 00734 00735 spec_type = first_arg_type; 00736 i = 0; 00737 00738 while (spec_type != DBUS_TYPE_INVALID) 00739 { 00740 msg_type = dbus_message_iter_get_arg_type (iter); 00741 00742 if (msg_type != spec_type) 00743 { 00744 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00745 "Argument %d is specified to be of type \"%s\", but " 00746 "is actually of type \"%s\"\n", i, 00747 _dbus_type_to_string (spec_type), 00748 _dbus_type_to_string (msg_type)); 00749 00750 goto out; 00751 } 00752 00753 if (spec_type == DBUS_TYPE_UNIX_FD) 00754 { 00755 #ifdef HAVE_UNIX_FD_PASSING 00756 DBusBasicValue idx; 00757 int *pfd, nfd; 00758 00759 pfd = va_arg (var_args, int*); 00760 _dbus_assert(pfd); 00761 00762 _dbus_type_reader_read_basic(&real->u.reader, &idx); 00763 00764 if (idx.u32 >= real->message->n_unix_fds) 00765 { 00766 dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE, 00767 "Message refers to file descriptor at index %i," 00768 "but has only %i descriptors attached.\n", 00769 idx.u32, 00770 real->message->n_unix_fds); 00771 goto out; 00772 } 00773 00774 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0) 00775 goto out; 00776 00777 *pfd = nfd; 00778 #else 00779 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00780 "Platform does not support file desciptor passing.\n"); 00781 goto out; 00782 #endif 00783 } 00784 else if (dbus_type_is_basic (spec_type)) 00785 { 00786 DBusBasicValue *ptr; 00787 00788 ptr = va_arg (var_args, DBusBasicValue*); 00789 00790 _dbus_assert (ptr != NULL); 00791 00792 _dbus_type_reader_read_basic (&real->u.reader, 00793 ptr); 00794 } 00795 else if (spec_type == DBUS_TYPE_ARRAY) 00796 { 00797 int element_type; 00798 int spec_element_type; 00799 const DBusBasicValue **ptr; 00800 int *n_elements_p; 00801 DBusTypeReader array; 00802 00803 spec_element_type = va_arg (var_args, int); 00804 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 00805 00806 if (spec_element_type != element_type) 00807 { 00808 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00809 "Argument %d is specified to be an array of \"%s\", but " 00810 "is actually an array of \"%s\"\n", 00811 i, 00812 _dbus_type_to_string (spec_element_type), 00813 _dbus_type_to_string (element_type)); 00814 00815 goto out; 00816 } 00817 00818 if (dbus_type_is_fixed (spec_element_type) && 00819 element_type != DBUS_TYPE_UNIX_FD) 00820 { 00821 ptr = va_arg (var_args, const DBusBasicValue**); 00822 n_elements_p = va_arg (var_args, int*); 00823 00824 _dbus_assert (ptr != NULL); 00825 _dbus_assert (n_elements_p != NULL); 00826 00827 _dbus_type_reader_recurse (&real->u.reader, &array); 00828 00829 _dbus_type_reader_read_fixed_multi (&array, 00830 (void *) ptr, n_elements_p); 00831 } 00832 else if (spec_element_type == DBUS_TYPE_STRING || 00833 spec_element_type == DBUS_TYPE_SIGNATURE || 00834 spec_element_type == DBUS_TYPE_OBJECT_PATH) 00835 { 00836 char ***str_array_p; 00837 int n_elements; 00838 char **str_array; 00839 00840 str_array_p = va_arg (var_args, char***); 00841 n_elements_p = va_arg (var_args, int*); 00842 00843 _dbus_assert (str_array_p != NULL); 00844 _dbus_assert (n_elements_p != NULL); 00845 00846 /* Count elements in the array */ 00847 _dbus_type_reader_recurse (&real->u.reader, &array); 00848 00849 n_elements = 0; 00850 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 00851 { 00852 ++n_elements; 00853 _dbus_type_reader_next (&array); 00854 } 00855 00856 str_array = dbus_new0 (char*, n_elements + 1); 00857 if (str_array == NULL) 00858 { 00859 _DBUS_SET_OOM (error); 00860 goto out; 00861 } 00862 00863 /* Now go through and dup each string */ 00864 _dbus_type_reader_recurse (&real->u.reader, &array); 00865 00866 i = 0; 00867 while (i < n_elements) 00868 { 00869 const char *s; 00870 _dbus_type_reader_read_basic (&array, 00871 (void *) &s); 00872 00873 str_array[i] = _dbus_strdup (s); 00874 if (str_array[i] == NULL) 00875 { 00876 dbus_free_string_array (str_array); 00877 _DBUS_SET_OOM (error); 00878 goto out; 00879 } 00880 00881 ++i; 00882 00883 if (!_dbus_type_reader_next (&array)) 00884 _dbus_assert (i == n_elements); 00885 } 00886 00887 _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); 00888 _dbus_assert (i == n_elements); 00889 _dbus_assert (str_array[i] == NULL); 00890 00891 *str_array_p = str_array; 00892 *n_elements_p = n_elements; 00893 } 00894 #ifndef DBUS_DISABLE_CHECKS 00895 else 00896 { 00897 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", 00898 _DBUS_FUNCTION_NAME); 00899 goto out; 00900 } 00901 #endif 00902 } 00903 #ifndef DBUS_DISABLE_CHECKS 00904 else 00905 { 00906 _dbus_warn ("you can only read arrays and basic types with %s for now\n", 00907 _DBUS_FUNCTION_NAME); 00908 goto out; 00909 } 00910 #endif 00911 00912 spec_type = va_arg (var_args, int); 00913 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) 00914 { 00915 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00916 "Message has only %d arguments, but more were expected", i); 00917 goto out; 00918 } 00919 00920 i++; 00921 } 00922 00923 retval = TRUE; 00924 00925 out: 00926 00927 return retval; 00928 } 00929 00988 dbus_uint32_t 00989 dbus_message_get_serial (DBusMessage *message) 00990 { 00991 _dbus_return_val_if_fail (message != NULL, 0); 00992 00993 return _dbus_header_get_serial (&message->header); 00994 } 00995 01004 dbus_bool_t 01005 dbus_message_set_reply_serial (DBusMessage *message, 01006 dbus_uint32_t reply_serial) 01007 { 01008 _dbus_return_val_if_fail (message != NULL, FALSE); 01009 _dbus_return_val_if_fail (!message->locked, FALSE); 01010 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */ 01011 01012 return _dbus_header_set_field_basic (&message->header, 01013 DBUS_HEADER_FIELD_REPLY_SERIAL, 01014 DBUS_TYPE_UINT32, 01015 &reply_serial); 01016 } 01017 01024 dbus_uint32_t 01025 dbus_message_get_reply_serial (DBusMessage *message) 01026 { 01027 dbus_uint32_t v_UINT32; 01028 01029 _dbus_return_val_if_fail (message != NULL, 0); 01030 01031 if (_dbus_header_get_field_basic (&message->header, 01032 DBUS_HEADER_FIELD_REPLY_SERIAL, 01033 DBUS_TYPE_UINT32, 01034 &v_UINT32)) 01035 return v_UINT32; 01036 else 01037 return 0; 01038 } 01039 01040 static void 01041 dbus_message_finalize (DBusMessage *message) 01042 { 01043 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01044 01045 /* This calls application callbacks! */ 01046 _dbus_data_slot_list_free (&message->slot_list); 01047 01048 _dbus_list_foreach (&message->counters, 01049 free_counter, message); 01050 _dbus_list_clear (&message->counters); 01051 01052 _dbus_header_free (&message->header); 01053 _dbus_string_free (&message->body); 01054 01055 #ifdef HAVE_UNIX_FD_PASSING 01056 close_unix_fds(message->unix_fds, &message->n_unix_fds); 01057 dbus_free(message->unix_fds); 01058 #endif 01059 01060 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01061 01062 dbus_free (message); 01063 } 01064 01065 static DBusMessage* 01066 dbus_message_new_empty_header (void) 01067 { 01068 DBusMessage *message; 01069 dbus_bool_t from_cache; 01070 01071 message = dbus_message_get_cached (); 01072 01073 if (message != NULL) 01074 { 01075 from_cache = TRUE; 01076 } 01077 else 01078 { 01079 from_cache = FALSE; 01080 message = dbus_new0 (DBusMessage, 1); 01081 if (message == NULL) 01082 return NULL; 01083 #ifndef DBUS_DISABLE_CHECKS 01084 message->generation = _dbus_current_generation; 01085 #endif 01086 01087 #ifdef HAVE_UNIX_FD_PASSING 01088 message->unix_fds = NULL; 01089 message->n_unix_fds_allocated = 0; 01090 #endif 01091 } 01092 01093 _dbus_atomic_inc (&message->refcount); 01094 01095 message->byte_order = DBUS_COMPILER_BYTE_ORDER; 01096 message->locked = FALSE; 01097 #ifndef DBUS_DISABLE_CHECKS 01098 message->in_cache = FALSE; 01099 #endif 01100 message->counters = NULL; 01101 message->size_counter_delta = 0; 01102 message->changed_stamp = 0; 01103 01104 #ifdef HAVE_UNIX_FD_PASSING 01105 message->n_unix_fds = 0; 01106 message->n_unix_fds_allocated = 0; 01107 message->unix_fd_counter_delta = 0; 01108 #endif 01109 01110 if (!from_cache) 01111 _dbus_data_slot_list_init (&message->slot_list); 01112 01113 if (from_cache) 01114 { 01115 _dbus_header_reinit (&message->header, message->byte_order); 01116 _dbus_string_set_length (&message->body, 0); 01117 } 01118 else 01119 { 01120 if (!_dbus_header_init (&message->header, message->byte_order)) 01121 { 01122 dbus_free (message); 01123 return NULL; 01124 } 01125 01126 if (!_dbus_string_init_preallocated (&message->body, 32)) 01127 { 01128 _dbus_header_free (&message->header); 01129 dbus_free (message); 01130 return NULL; 01131 } 01132 } 01133 01134 return message; 01135 } 01136 01149 DBusMessage* 01150 dbus_message_new (int message_type) 01151 { 01152 DBusMessage *message; 01153 01154 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL); 01155 01156 message = dbus_message_new_empty_header (); 01157 if (message == NULL) 01158 return NULL; 01159 01160 if (!_dbus_header_create (&message->header, 01161 message_type, 01162 NULL, NULL, NULL, NULL, NULL)) 01163 { 01164 dbus_message_unref (message); 01165 return NULL; 01166 } 01167 01168 return message; 01169 } 01170 01192 DBusMessage* 01193 dbus_message_new_method_call (const char *destination, 01194 const char *path, 01195 const char *interface, 01196 const char *method) 01197 { 01198 DBusMessage *message; 01199 01200 _dbus_return_val_if_fail (path != NULL, NULL); 01201 _dbus_return_val_if_fail (method != NULL, NULL); 01202 _dbus_return_val_if_fail (destination == NULL || 01203 _dbus_check_is_valid_bus_name (destination), NULL); 01204 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01205 _dbus_return_val_if_fail (interface == NULL || 01206 _dbus_check_is_valid_interface (interface), NULL); 01207 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); 01208 01209 message = dbus_message_new_empty_header (); 01210 if (message == NULL) 01211 return NULL; 01212 01213 if (!_dbus_header_create (&message->header, 01214 DBUS_MESSAGE_TYPE_METHOD_CALL, 01215 destination, path, interface, method, NULL)) 01216 { 01217 dbus_message_unref (message); 01218 return NULL; 01219 } 01220 01221 return message; 01222 } 01223 01231 DBusMessage* 01232 dbus_message_new_method_return (DBusMessage *method_call) 01233 { 01234 DBusMessage *message; 01235 const char *sender; 01236 01237 _dbus_return_val_if_fail (method_call != NULL, NULL); 01238 01239 sender = dbus_message_get_sender (method_call); 01240 01241 /* sender is allowed to be null here in peer-to-peer case */ 01242 01243 message = dbus_message_new_empty_header (); 01244 if (message == NULL) 01245 return NULL; 01246 01247 if (!_dbus_header_create (&message->header, 01248 DBUS_MESSAGE_TYPE_METHOD_RETURN, 01249 sender, NULL, NULL, NULL, NULL)) 01250 { 01251 dbus_message_unref (message); 01252 return NULL; 01253 } 01254 01255 dbus_message_set_no_reply (message, TRUE); 01256 01257 if (!dbus_message_set_reply_serial (message, 01258 dbus_message_get_serial (method_call))) 01259 { 01260 dbus_message_unref (message); 01261 return NULL; 01262 } 01263 01264 return message; 01265 } 01266 01281 DBusMessage* 01282 dbus_message_new_signal (const char *path, 01283 const char *interface, 01284 const char *name) 01285 { 01286 DBusMessage *message; 01287 01288 _dbus_return_val_if_fail (path != NULL, NULL); 01289 _dbus_return_val_if_fail (interface != NULL, NULL); 01290 _dbus_return_val_if_fail (name != NULL, NULL); 01291 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01292 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL); 01293 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); 01294 01295 message = dbus_message_new_empty_header (); 01296 if (message == NULL) 01297 return NULL; 01298 01299 if (!_dbus_header_create (&message->header, 01300 DBUS_MESSAGE_TYPE_SIGNAL, 01301 NULL, path, interface, name, NULL)) 01302 { 01303 dbus_message_unref (message); 01304 return NULL; 01305 } 01306 01307 dbus_message_set_no_reply (message, TRUE); 01308 01309 return message; 01310 } 01311 01326 DBusMessage* 01327 dbus_message_new_error (DBusMessage *reply_to, 01328 const char *error_name, 01329 const char *error_message) 01330 { 01331 DBusMessage *message; 01332 const char *sender; 01333 DBusMessageIter iter; 01334 01335 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01336 _dbus_return_val_if_fail (error_name != NULL, NULL); 01337 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01338 01339 sender = dbus_message_get_sender (reply_to); 01340 01341 /* sender may be NULL for non-message-bus case or 01342 * when the message bus is dealing with an unregistered 01343 * connection. 01344 */ 01345 message = dbus_message_new_empty_header (); 01346 if (message == NULL) 01347 return NULL; 01348 01349 if (!_dbus_header_create (&message->header, 01350 DBUS_MESSAGE_TYPE_ERROR, 01351 sender, NULL, NULL, NULL, error_name)) 01352 { 01353 dbus_message_unref (message); 01354 return NULL; 01355 } 01356 01357 dbus_message_set_no_reply (message, TRUE); 01358 01359 if (!dbus_message_set_reply_serial (message, 01360 dbus_message_get_serial (reply_to))) 01361 { 01362 dbus_message_unref (message); 01363 return NULL; 01364 } 01365 01366 if (error_message != NULL) 01367 { 01368 dbus_message_iter_init_append (message, &iter); 01369 if (!dbus_message_iter_append_basic (&iter, 01370 DBUS_TYPE_STRING, 01371 &error_message)) 01372 { 01373 dbus_message_unref (message); 01374 return NULL; 01375 } 01376 } 01377 01378 return message; 01379 } 01380 01397 DBusMessage* 01398 dbus_message_new_error_printf (DBusMessage *reply_to, 01399 const char *error_name, 01400 const char *error_format, 01401 ...) 01402 { 01403 va_list args; 01404 DBusString str; 01405 DBusMessage *message; 01406 01407 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01408 _dbus_return_val_if_fail (error_name != NULL, NULL); 01409 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01410 01411 if (!_dbus_string_init (&str)) 01412 return NULL; 01413 01414 va_start (args, error_format); 01415 01416 if (_dbus_string_append_printf_valist (&str, error_format, args)) 01417 message = dbus_message_new_error (reply_to, error_name, 01418 _dbus_string_get_const_data (&str)); 01419 else 01420 message = NULL; 01421 01422 _dbus_string_free (&str); 01423 01424 va_end (args); 01425 01426 return message; 01427 } 01428 01429 01442 DBusMessage * 01443 dbus_message_copy (const DBusMessage *message) 01444 { 01445 DBusMessage *retval; 01446 01447 _dbus_return_val_if_fail (message != NULL, NULL); 01448 01449 retval = dbus_new0 (DBusMessage, 1); 01450 if (retval == NULL) 01451 return NULL; 01452 01453 _dbus_atomic_inc (&retval->refcount); 01454 retval->byte_order = message->byte_order; 01455 retval->locked = FALSE; 01456 #ifndef DBUS_DISABLE_CHECKS 01457 retval->generation = message->generation; 01458 #endif 01459 01460 if (!_dbus_header_copy (&message->header, &retval->header)) 01461 { 01462 dbus_free (retval); 01463 return NULL; 01464 } 01465 01466 if (!_dbus_string_init_preallocated (&retval->body, 01467 _dbus_string_get_length (&message->body))) 01468 { 01469 _dbus_header_free (&retval->header); 01470 dbus_free (retval); 01471 return NULL; 01472 } 01473 01474 if (!_dbus_string_copy (&message->body, 0, 01475 &retval->body, 0)) 01476 goto failed_copy; 01477 01478 #ifdef HAVE_UNIX_FD_PASSING 01479 retval->unix_fds = dbus_new(int, message->n_unix_fds); 01480 if (retval->unix_fds == NULL && message->n_unix_fds > 0) 01481 goto failed_copy; 01482 01483 retval->n_unix_fds_allocated = message->n_unix_fds; 01484 01485 for (retval->n_unix_fds = 0; 01486 retval->n_unix_fds < message->n_unix_fds; 01487 retval->n_unix_fds++) 01488 { 01489 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL); 01490 01491 if (retval->unix_fds[retval->n_unix_fds] < 0) 01492 goto failed_copy; 01493 } 01494 01495 #endif 01496 01497 return retval; 01498 01499 failed_copy: 01500 _dbus_header_free (&retval->header); 01501 _dbus_string_free (&retval->body); 01502 01503 #ifdef HAVE_UNIX_FD_PASSING 01504 close_unix_fds(retval->unix_fds, &retval->n_unix_fds); 01505 dbus_free(retval->unix_fds); 01506 #endif 01507 01508 dbus_free (retval); 01509 01510 return NULL; 01511 } 01512 01513 01521 DBusMessage * 01522 dbus_message_ref (DBusMessage *message) 01523 { 01524 #ifndef DBUS_DISABLE_ASSERT 01525 dbus_int32_t old_refcount; 01526 #endif 01527 01528 _dbus_return_val_if_fail (message != NULL, NULL); 01529 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); 01530 _dbus_return_val_if_fail (!message->in_cache, NULL); 01531 01532 #ifdef DBUS_DISABLE_ASSERT 01533 _dbus_atomic_inc (&message->refcount); 01534 #else 01535 old_refcount = _dbus_atomic_inc (&message->refcount); 01536 _dbus_assert (old_refcount >= 1); 01537 #endif 01538 01539 return message; 01540 } 01541 01549 void 01550 dbus_message_unref (DBusMessage *message) 01551 { 01552 dbus_int32_t old_refcount; 01553 01554 _dbus_return_if_fail (message != NULL); 01555 _dbus_return_if_fail (message->generation == _dbus_current_generation); 01556 _dbus_return_if_fail (!message->in_cache); 01557 01558 old_refcount = _dbus_atomic_dec (&message->refcount); 01559 01560 _dbus_assert (old_refcount >= 1); 01561 01562 if (old_refcount == 1) 01563 { 01564 /* Calls application callbacks! */ 01565 dbus_message_cache_or_finalize (message); 01566 } 01567 } 01568 01579 int 01580 dbus_message_get_type (DBusMessage *message) 01581 { 01582 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID); 01583 01584 return _dbus_header_get_message_type (&message->header); 01585 } 01586 01649 dbus_bool_t 01650 dbus_message_append_args (DBusMessage *message, 01651 int first_arg_type, 01652 ...) 01653 { 01654 dbus_bool_t retval; 01655 va_list var_args; 01656 01657 _dbus_return_val_if_fail (message != NULL, FALSE); 01658 01659 va_start (var_args, first_arg_type); 01660 retval = dbus_message_append_args_valist (message, 01661 first_arg_type, 01662 var_args); 01663 va_end (var_args); 01664 01665 return retval; 01666 } 01667 01681 dbus_bool_t 01682 dbus_message_append_args_valist (DBusMessage *message, 01683 int first_arg_type, 01684 va_list var_args) 01685 { 01686 int type; 01687 DBusMessageIter iter; 01688 01689 _dbus_return_val_if_fail (message != NULL, FALSE); 01690 01691 type = first_arg_type; 01692 01693 dbus_message_iter_init_append (message, &iter); 01694 01695 while (type != DBUS_TYPE_INVALID) 01696 { 01697 if (dbus_type_is_basic (type)) 01698 { 01699 const DBusBasicValue *value; 01700 value = va_arg (var_args, const DBusBasicValue*); 01701 01702 if (!dbus_message_iter_append_basic (&iter, 01703 type, 01704 value)) 01705 goto failed; 01706 } 01707 else if (type == DBUS_TYPE_ARRAY) 01708 { 01709 int element_type; 01710 DBusMessageIter array; 01711 char buf[2]; 01712 01713 element_type = va_arg (var_args, int); 01714 01715 buf[0] = element_type; 01716 buf[1] = '\0'; 01717 if (!dbus_message_iter_open_container (&iter, 01718 DBUS_TYPE_ARRAY, 01719 buf, 01720 &array)) 01721 goto failed; 01722 01723 if (dbus_type_is_fixed (element_type) && 01724 element_type != DBUS_TYPE_UNIX_FD) 01725 { 01726 const DBusBasicValue **value; 01727 int n_elements; 01728 01729 value = va_arg (var_args, const DBusBasicValue**); 01730 n_elements = va_arg (var_args, int); 01731 01732 if (!dbus_message_iter_append_fixed_array (&array, 01733 element_type, 01734 value, 01735 n_elements)) { 01736 dbus_message_iter_abandon_container (&iter, &array); 01737 goto failed; 01738 } 01739 } 01740 else if (element_type == DBUS_TYPE_STRING || 01741 element_type == DBUS_TYPE_SIGNATURE || 01742 element_type == DBUS_TYPE_OBJECT_PATH) 01743 { 01744 const char ***value_p; 01745 const char **value; 01746 int n_elements; 01747 int i; 01748 01749 value_p = va_arg (var_args, const char***); 01750 n_elements = va_arg (var_args, int); 01751 01752 value = *value_p; 01753 01754 i = 0; 01755 while (i < n_elements) 01756 { 01757 if (!dbus_message_iter_append_basic (&array, 01758 element_type, 01759 &value[i])) { 01760 dbus_message_iter_abandon_container (&iter, &array); 01761 goto failed; 01762 } 01763 ++i; 01764 } 01765 } 01766 else 01767 { 01768 _dbus_warn ("arrays of %s can't be appended with %s for now\n", 01769 _dbus_type_to_string (element_type), 01770 _DBUS_FUNCTION_NAME); 01771 goto failed; 01772 } 01773 01774 if (!dbus_message_iter_close_container (&iter, &array)) 01775 goto failed; 01776 } 01777 #ifndef DBUS_DISABLE_CHECKS 01778 else 01779 { 01780 _dbus_warn ("type %s isn't supported yet in %s\n", 01781 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME); 01782 goto failed; 01783 } 01784 #endif 01785 01786 type = va_arg (var_args, int); 01787 } 01788 01789 return TRUE; 01790 01791 failed: 01792 return FALSE; 01793 } 01794 01839 dbus_bool_t 01840 dbus_message_get_args (DBusMessage *message, 01841 DBusError *error, 01842 int first_arg_type, 01843 ...) 01844 { 01845 dbus_bool_t retval; 01846 va_list var_args; 01847 01848 _dbus_return_val_if_fail (message != NULL, FALSE); 01849 _dbus_return_val_if_error_is_set (error, FALSE); 01850 01851 va_start (var_args, first_arg_type); 01852 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args); 01853 va_end (var_args); 01854 01855 return retval; 01856 } 01857 01868 dbus_bool_t 01869 dbus_message_get_args_valist (DBusMessage *message, 01870 DBusError *error, 01871 int first_arg_type, 01872 va_list var_args) 01873 { 01874 DBusMessageIter iter; 01875 01876 _dbus_return_val_if_fail (message != NULL, FALSE); 01877 _dbus_return_val_if_error_is_set (error, FALSE); 01878 01879 dbus_message_iter_init (message, &iter); 01880 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); 01881 } 01882 01883 static void 01884 _dbus_message_iter_init_common (DBusMessage *message, 01885 DBusMessageRealIter *real, 01886 int iter_type) 01887 { 01888 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); 01889 01890 /* Since the iterator will read or write who-knows-what from the 01891 * message, we need to get in the right byte order 01892 */ 01893 ensure_byte_order (message); 01894 01895 real->message = message; 01896 real->changed_stamp = message->changed_stamp; 01897 real->iter_type = iter_type; 01898 real->sig_refcount = 0; 01899 } 01900 01923 dbus_bool_t 01924 dbus_message_iter_init (DBusMessage *message, 01925 DBusMessageIter *iter) 01926 { 01927 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01928 const DBusString *type_str; 01929 int type_pos; 01930 01931 _dbus_return_val_if_fail (message != NULL, FALSE); 01932 _dbus_return_val_if_fail (iter != NULL, FALSE); 01933 01934 get_const_signature (&message->header, &type_str, &type_pos); 01935 01936 _dbus_message_iter_init_common (message, real, 01937 DBUS_MESSAGE_ITER_TYPE_READER); 01938 01939 _dbus_type_reader_init (&real->u.reader, 01940 message->byte_order, 01941 type_str, type_pos, 01942 &message->body, 01943 0); 01944 01945 return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID; 01946 } 01947 01954 dbus_bool_t 01955 dbus_message_iter_has_next (DBusMessageIter *iter) 01956 { 01957 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01958 01959 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01960 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01961 01962 return _dbus_type_reader_has_next (&real->u.reader); 01963 } 01964 01973 dbus_bool_t 01974 dbus_message_iter_next (DBusMessageIter *iter) 01975 { 01976 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01977 01978 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01979 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01980 01981 return _dbus_type_reader_next (&real->u.reader); 01982 } 01983 01998 int 01999 dbus_message_iter_get_arg_type (DBusMessageIter *iter) 02000 { 02001 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02002 02003 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02004 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02005 02006 return _dbus_type_reader_get_current_type (&real->u.reader); 02007 } 02008 02017 int 02018 dbus_message_iter_get_element_type (DBusMessageIter *iter) 02019 { 02020 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02021 02022 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02023 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); 02024 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 02025 02026 return _dbus_type_reader_get_element_type (&real->u.reader); 02027 } 02028 02054 void 02055 dbus_message_iter_recurse (DBusMessageIter *iter, 02056 DBusMessageIter *sub) 02057 { 02058 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02059 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02060 02061 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02062 _dbus_return_if_fail (sub != NULL); 02063 02064 *real_sub = *real; 02065 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader); 02066 } 02067 02079 char * 02080 dbus_message_iter_get_signature (DBusMessageIter *iter) 02081 { 02082 const DBusString *sig; 02083 DBusString retstr; 02084 char *ret; 02085 int start, len; 02086 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02087 02088 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL); 02089 02090 if (!_dbus_string_init (&retstr)) 02091 return NULL; 02092 02093 _dbus_type_reader_get_signature (&real->u.reader, &sig, 02094 &start, &len); 02095 if (!_dbus_string_append_len (&retstr, 02096 _dbus_string_get_const_data (sig) + start, 02097 len)) 02098 return NULL; 02099 if (!_dbus_string_steal_data (&retstr, &ret)) 02100 return NULL; 02101 _dbus_string_free (&retstr); 02102 return ret; 02103 } 02104 02152 void 02153 dbus_message_iter_get_basic (DBusMessageIter *iter, 02154 void *value) 02155 { 02156 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02157 02158 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02159 _dbus_return_if_fail (value != NULL); 02160 02161 if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD) 02162 { 02163 #ifdef HAVE_UNIX_FD_PASSING 02164 DBusBasicValue idx; 02165 02166 _dbus_type_reader_read_basic(&real->u.reader, &idx); 02167 02168 if (idx.u32 >= real->message->n_unix_fds) { 02169 /* Hmm, we cannot really signal an error here, so let's make 02170 sure to return an invalid fd. */ 02171 *((int*) value) = -1; 02172 return; 02173 } 02174 02175 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL); 02176 #else 02177 *((int*) value) = -1; 02178 #endif 02179 } 02180 else 02181 { 02182 _dbus_type_reader_read_basic (&real->u.reader, 02183 value); 02184 } 02185 } 02186 02205 int 02206 dbus_message_iter_get_array_len (DBusMessageIter *iter) 02207 { 02208 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02209 02210 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02211 02212 return _dbus_type_reader_get_array_length (&real->u.reader); 02213 } 02214 02250 void 02251 dbus_message_iter_get_fixed_array (DBusMessageIter *iter, 02252 void *value, 02253 int *n_elements) 02254 { 02255 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02256 int subtype = _dbus_type_reader_get_current_type(&real->u.reader); 02257 02258 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02259 _dbus_return_if_fail (value != NULL); 02260 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) || 02261 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD)); 02262 02263 _dbus_type_reader_read_fixed_multi (&real->u.reader, 02264 value, n_elements); 02265 } 02266 02278 void 02279 dbus_message_iter_init_append (DBusMessage *message, 02280 DBusMessageIter *iter) 02281 { 02282 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02283 02284 _dbus_return_if_fail (message != NULL); 02285 _dbus_return_if_fail (iter != NULL); 02286 02287 _dbus_message_iter_init_common (message, real, 02288 DBUS_MESSAGE_ITER_TYPE_WRITER); 02289 02290 /* We create the signature string and point iterators at it "on demand" 02291 * when a value is actually appended. That means that init() never fails 02292 * due to OOM. 02293 */ 02294 _dbus_type_writer_init_types_delayed (&real->u.writer, 02295 message->byte_order, 02296 &message->body, 02297 _dbus_string_get_length (&message->body)); 02298 } 02299 02308 static dbus_bool_t 02309 _dbus_message_iter_open_signature (DBusMessageRealIter *real) 02310 { 02311 DBusString *str; 02312 const DBusString *current_sig; 02313 int current_sig_pos; 02314 02315 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02316 02317 if (real->u.writer.type_str != NULL) 02318 { 02319 _dbus_assert (real->sig_refcount > 0); 02320 real->sig_refcount += 1; 02321 return TRUE; 02322 } 02323 02324 str = dbus_new (DBusString, 1); 02325 if (str == NULL) 02326 return FALSE; 02327 02328 if (!_dbus_header_get_field_raw (&real->message->header, 02329 DBUS_HEADER_FIELD_SIGNATURE, 02330 ¤t_sig, ¤t_sig_pos)) 02331 current_sig = NULL; 02332 02333 if (current_sig) 02334 { 02335 int current_len; 02336 02337 current_len = _dbus_string_get_byte (current_sig, current_sig_pos); 02338 current_sig_pos += 1; /* move on to sig data */ 02339 02340 if (!_dbus_string_init_preallocated (str, current_len + 4)) 02341 { 02342 dbus_free (str); 02343 return FALSE; 02344 } 02345 02346 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len, 02347 str, 0)) 02348 { 02349 _dbus_string_free (str); 02350 dbus_free (str); 02351 return FALSE; 02352 } 02353 } 02354 else 02355 { 02356 if (!_dbus_string_init_preallocated (str, 4)) 02357 { 02358 dbus_free (str); 02359 return FALSE; 02360 } 02361 } 02362 02363 real->sig_refcount = 1; 02364 02365 _dbus_type_writer_add_types (&real->u.writer, 02366 str, _dbus_string_get_length (str)); 02367 return TRUE; 02368 } 02369 02379 static dbus_bool_t 02380 _dbus_message_iter_close_signature (DBusMessageRealIter *real) 02381 { 02382 DBusString *str; 02383 const char *v_STRING; 02384 dbus_bool_t retval; 02385 02386 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02387 _dbus_assert (real->u.writer.type_str != NULL); 02388 _dbus_assert (real->sig_refcount > 0); 02389 02390 real->sig_refcount -= 1; 02391 02392 if (real->sig_refcount > 0) 02393 return TRUE; 02394 _dbus_assert (real->sig_refcount == 0); 02395 02396 retval = TRUE; 02397 02398 str = real->u.writer.type_str; 02399 02400 v_STRING = _dbus_string_get_const_data (str); 02401 if (!_dbus_header_set_field_basic (&real->message->header, 02402 DBUS_HEADER_FIELD_SIGNATURE, 02403 DBUS_TYPE_SIGNATURE, 02404 &v_STRING)) 02405 retval = FALSE; 02406 02407 _dbus_type_writer_remove_types (&real->u.writer); 02408 _dbus_string_free (str); 02409 dbus_free (str); 02410 02411 return retval; 02412 } 02413 02421 static void 02422 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real) 02423 { 02424 DBusString *str; 02425 02426 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02427 _dbus_assert (real->u.writer.type_str != NULL); 02428 _dbus_assert (real->sig_refcount > 0); 02429 02430 real->sig_refcount -= 1; 02431 02432 if (real->sig_refcount > 0) 02433 return; 02434 _dbus_assert (real->sig_refcount == 0); 02435 02436 str = real->u.writer.type_str; 02437 02438 _dbus_type_writer_remove_types (&real->u.writer); 02439 _dbus_string_free (str); 02440 dbus_free (str); 02441 } 02442 02443 #ifndef DBUS_DISABLE_CHECKS 02444 static dbus_bool_t 02445 _dbus_message_iter_append_check (DBusMessageRealIter *iter) 02446 { 02447 if (!_dbus_message_iter_check (iter)) 02448 return FALSE; 02449 02450 if (iter->message->locked) 02451 { 02452 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n"); 02453 return FALSE; 02454 } 02455 02456 return TRUE; 02457 } 02458 #endif /* DBUS_DISABLE_CHECKS */ 02459 02460 #ifdef HAVE_UNIX_FD_PASSING 02461 static int * 02462 expand_fd_array(DBusMessage *m, 02463 unsigned n) 02464 { 02465 _dbus_assert(m); 02466 02467 /* This makes space for adding n new fds to the array and returns a 02468 pointer to the place were the first fd should be put. */ 02469 02470 if (m->n_unix_fds + n > m->n_unix_fds_allocated) 02471 { 02472 unsigned k; 02473 int *p; 02474 02475 /* Make twice as much space as necessary */ 02476 k = (m->n_unix_fds + n) * 2; 02477 02478 /* Allocate at least four */ 02479 if (k < 4) 02480 k = 4; 02481 02482 p = dbus_realloc(m->unix_fds, k * sizeof(int)); 02483 if (p == NULL) 02484 return NULL; 02485 02486 m->unix_fds = p; 02487 m->n_unix_fds_allocated = k; 02488 } 02489 02490 return m->unix_fds + m->n_unix_fds; 02491 } 02492 #endif 02493 02513 dbus_bool_t 02514 dbus_message_iter_append_basic (DBusMessageIter *iter, 02515 int type, 02516 const void *value) 02517 { 02518 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02519 dbus_bool_t ret; 02520 02521 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02522 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02523 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE); 02524 _dbus_return_val_if_fail (value != NULL, FALSE); 02525 02526 #ifndef DBUS_DISABLE_CHECKS 02527 switch (type) 02528 { 02529 const char * const *string_p; 02530 const dbus_bool_t *bool_p; 02531 02532 case DBUS_TYPE_STRING: 02533 string_p = value; 02534 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE); 02535 break; 02536 02537 case DBUS_TYPE_OBJECT_PATH: 02538 string_p = value; 02539 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE); 02540 break; 02541 02542 case DBUS_TYPE_SIGNATURE: 02543 string_p = value; 02544 _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE); 02545 break; 02546 02547 case DBUS_TYPE_BOOLEAN: 02548 bool_p = value; 02549 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE); 02550 break; 02551 02552 default: 02553 { 02554 /* nothing to check, all possible values are allowed */ 02555 } 02556 } 02557 #endif 02558 02559 if (!_dbus_message_iter_open_signature (real)) 02560 return FALSE; 02561 02562 if (type == DBUS_TYPE_UNIX_FD) 02563 { 02564 #ifdef HAVE_UNIX_FD_PASSING 02565 int *fds; 02566 dbus_uint32_t u; 02567 02568 /* First step, include the fd in the fd list of this message */ 02569 if (!(fds = expand_fd_array(real->message, 1))) 02570 return FALSE; 02571 02572 *fds = _dbus_dup(*(int*) value, NULL); 02573 if (*fds < 0) 02574 return FALSE; 02575 02576 u = real->message->n_unix_fds; 02577 02578 /* Second step, write the index to the fd */ 02579 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) { 02580 _dbus_close(*fds, NULL); 02581 return FALSE; 02582 } 02583 02584 real->message->n_unix_fds += 1; 02585 u += 1; 02586 02587 /* Final step, update the header accordingly */ 02588 ret = _dbus_header_set_field_basic (&real->message->header, 02589 DBUS_HEADER_FIELD_UNIX_FDS, 02590 DBUS_TYPE_UINT32, 02591 &u); 02592 02593 /* If any of these operations fail the message is 02594 hosed. However, no memory or fds should be leaked since what 02595 has been added to message has been added to the message, and 02596 can hence be accounted for when the message is being 02597 freed. */ 02598 #else 02599 ret = FALSE; 02600 #endif 02601 } 02602 else 02603 { 02604 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02605 } 02606 02607 if (!_dbus_message_iter_close_signature (real)) 02608 ret = FALSE; 02609 02610 return ret; 02611 } 02612 02648 dbus_bool_t 02649 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02650 int element_type, 02651 const void *value, 02652 int n_elements) 02653 { 02654 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02655 dbus_bool_t ret; 02656 02657 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02658 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02659 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); 02660 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02661 _dbus_return_val_if_fail (value != NULL, FALSE); 02662 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02663 _dbus_return_val_if_fail (n_elements <= 02664 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02665 FALSE); 02666 02667 #ifndef DBUS_DISABLE_CHECKS 02668 if (element_type == DBUS_TYPE_BOOLEAN) 02669 { 02670 const dbus_bool_t * const *bools = value; 02671 int i; 02672 02673 for (i = 0; i < n_elements; i++) 02674 { 02675 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE); 02676 } 02677 } 02678 #endif 02679 02680 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02681 02682 return ret; 02683 } 02684 02706 dbus_bool_t 02707 dbus_message_iter_open_container (DBusMessageIter *iter, 02708 int type, 02709 const char *contained_signature, 02710 DBusMessageIter *sub) 02711 { 02712 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02713 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02714 DBusString contained_str; 02715 02716 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02717 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02718 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02719 _dbus_return_val_if_fail (sub != NULL, FALSE); 02720 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02721 contained_signature == NULL) || 02722 (type == DBUS_TYPE_DICT_ENTRY && 02723 contained_signature == NULL) || 02724 (type == DBUS_TYPE_VARIANT && 02725 contained_signature != NULL) || 02726 (type == DBUS_TYPE_ARRAY && 02727 contained_signature != NULL), FALSE); 02728 02729 /* this would fail if the contained_signature is a dict entry, since 02730 * dict entries are invalid signatures standalone (they must be in 02731 * an array) 02732 */ 02733 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02734 (contained_signature == NULL || 02735 _dbus_check_is_valid_signature (contained_signature)), 02736 FALSE); 02737 02738 if (!_dbus_message_iter_open_signature (real)) 02739 return FALSE; 02740 02741 *real_sub = *real; 02742 02743 if (contained_signature != NULL) 02744 { 02745 _dbus_string_init_const (&contained_str, contained_signature); 02746 02747 return _dbus_type_writer_recurse (&real->u.writer, 02748 type, 02749 &contained_str, 0, 02750 &real_sub->u.writer); 02751 } 02752 else 02753 { 02754 return _dbus_type_writer_recurse (&real->u.writer, 02755 type, 02756 NULL, 0, 02757 &real_sub->u.writer); 02758 } 02759 } 02760 02761 02775 dbus_bool_t 02776 dbus_message_iter_close_container (DBusMessageIter *iter, 02777 DBusMessageIter *sub) 02778 { 02779 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02780 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02781 dbus_bool_t ret; 02782 02783 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02784 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02785 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 02786 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02787 02788 ret = _dbus_type_writer_unrecurse (&real->u.writer, 02789 &real_sub->u.writer); 02790 02791 if (!_dbus_message_iter_close_signature (real)) 02792 ret = FALSE; 02793 02794 return ret; 02795 } 02796 02808 void 02809 dbus_message_iter_abandon_container (DBusMessageIter *iter, 02810 DBusMessageIter *sub) 02811 { 02812 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02813 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02814 02815 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 02816 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02817 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 02818 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02819 02820 _dbus_message_iter_abandon_signature (real); 02821 } 02822 02839 void 02840 dbus_message_set_no_reply (DBusMessage *message, 02841 dbus_bool_t no_reply) 02842 { 02843 _dbus_return_if_fail (message != NULL); 02844 _dbus_return_if_fail (!message->locked); 02845 02846 _dbus_header_toggle_flag (&message->header, 02847 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 02848 no_reply); 02849 } 02850 02858 dbus_bool_t 02859 dbus_message_get_no_reply (DBusMessage *message) 02860 { 02861 _dbus_return_val_if_fail (message != NULL, FALSE); 02862 02863 return _dbus_header_get_flag (&message->header, 02864 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 02865 } 02866 02881 void 02882 dbus_message_set_auto_start (DBusMessage *message, 02883 dbus_bool_t auto_start) 02884 { 02885 _dbus_return_if_fail (message != NULL); 02886 _dbus_return_if_fail (!message->locked); 02887 02888 _dbus_header_toggle_flag (&message->header, 02889 DBUS_HEADER_FLAG_NO_AUTO_START, 02890 !auto_start); 02891 } 02892 02900 dbus_bool_t 02901 dbus_message_get_auto_start (DBusMessage *message) 02902 { 02903 _dbus_return_val_if_fail (message != NULL, FALSE); 02904 02905 return !_dbus_header_get_flag (&message->header, 02906 DBUS_HEADER_FLAG_NO_AUTO_START); 02907 } 02908 02909 02922 dbus_bool_t 02923 dbus_message_set_path (DBusMessage *message, 02924 const char *object_path) 02925 { 02926 _dbus_return_val_if_fail (message != NULL, FALSE); 02927 _dbus_return_val_if_fail (!message->locked, FALSE); 02928 _dbus_return_val_if_fail (object_path == NULL || 02929 _dbus_check_is_valid_path (object_path), 02930 FALSE); 02931 02932 return set_or_delete_string_field (message, 02933 DBUS_HEADER_FIELD_PATH, 02934 DBUS_TYPE_OBJECT_PATH, 02935 object_path); 02936 } 02937 02951 const char* 02952 dbus_message_get_path (DBusMessage *message) 02953 { 02954 const char *v; 02955 02956 _dbus_return_val_if_fail (message != NULL, NULL); 02957 02958 v = NULL; /* in case field doesn't exist */ 02959 _dbus_header_get_field_basic (&message->header, 02960 DBUS_HEADER_FIELD_PATH, 02961 DBUS_TYPE_OBJECT_PATH, 02962 (void *) &v); 02963 return v; 02964 } 02965 02975 dbus_bool_t 02976 dbus_message_has_path (DBusMessage *message, 02977 const char *path) 02978 { 02979 const char *msg_path; 02980 msg_path = dbus_message_get_path (message); 02981 02982 if (msg_path == NULL) 02983 { 02984 if (path == NULL) 02985 return TRUE; 02986 else 02987 return FALSE; 02988 } 02989 02990 if (path == NULL) 02991 return FALSE; 02992 02993 if (strcmp (msg_path, path) == 0) 02994 return TRUE; 02995 02996 return FALSE; 02997 } 02998 03019 dbus_bool_t 03020 dbus_message_get_path_decomposed (DBusMessage *message, 03021 char ***path) 03022 { 03023 const char *v; 03024 03025 _dbus_return_val_if_fail (message != NULL, FALSE); 03026 _dbus_return_val_if_fail (path != NULL, FALSE); 03027 03028 *path = NULL; 03029 03030 v = dbus_message_get_path (message); 03031 if (v != NULL) 03032 { 03033 if (!_dbus_decompose_path (v, strlen (v), 03034 path, NULL)) 03035 return FALSE; 03036 } 03037 return TRUE; 03038 } 03039 03053 dbus_bool_t 03054 dbus_message_set_interface (DBusMessage *message, 03055 const char *interface) 03056 { 03057 _dbus_return_val_if_fail (message != NULL, FALSE); 03058 _dbus_return_val_if_fail (!message->locked, FALSE); 03059 _dbus_return_val_if_fail (interface == NULL || 03060 _dbus_check_is_valid_interface (interface), 03061 FALSE); 03062 03063 return set_or_delete_string_field (message, 03064 DBUS_HEADER_FIELD_INTERFACE, 03065 DBUS_TYPE_STRING, 03066 interface); 03067 } 03068 03082 const char* 03083 dbus_message_get_interface (DBusMessage *message) 03084 { 03085 const char *v; 03086 03087 _dbus_return_val_if_fail (message != NULL, NULL); 03088 03089 v = NULL; /* in case field doesn't exist */ 03090 _dbus_header_get_field_basic (&message->header, 03091 DBUS_HEADER_FIELD_INTERFACE, 03092 DBUS_TYPE_STRING, 03093 (void *) &v); 03094 return v; 03095 } 03096 03104 dbus_bool_t 03105 dbus_message_has_interface (DBusMessage *message, 03106 const char *interface) 03107 { 03108 const char *msg_interface; 03109 msg_interface = dbus_message_get_interface (message); 03110 03111 if (msg_interface == NULL) 03112 { 03113 if (interface == NULL) 03114 return TRUE; 03115 else 03116 return FALSE; 03117 } 03118 03119 if (interface == NULL) 03120 return FALSE; 03121 03122 if (strcmp (msg_interface, interface) == 0) 03123 return TRUE; 03124 03125 return FALSE; 03126 03127 } 03128 03141 dbus_bool_t 03142 dbus_message_set_member (DBusMessage *message, 03143 const char *member) 03144 { 03145 _dbus_return_val_if_fail (message != NULL, FALSE); 03146 _dbus_return_val_if_fail (!message->locked, FALSE); 03147 _dbus_return_val_if_fail (member == NULL || 03148 _dbus_check_is_valid_member (member), 03149 FALSE); 03150 03151 return set_or_delete_string_field (message, 03152 DBUS_HEADER_FIELD_MEMBER, 03153 DBUS_TYPE_STRING, 03154 member); 03155 } 03156 03168 const char* 03169 dbus_message_get_member (DBusMessage *message) 03170 { 03171 const char *v; 03172 03173 _dbus_return_val_if_fail (message != NULL, NULL); 03174 03175 v = NULL; /* in case field doesn't exist */ 03176 _dbus_header_get_field_basic (&message->header, 03177 DBUS_HEADER_FIELD_MEMBER, 03178 DBUS_TYPE_STRING, 03179 (void *) &v); 03180 return v; 03181 } 03182 03190 dbus_bool_t 03191 dbus_message_has_member (DBusMessage *message, 03192 const char *member) 03193 { 03194 const char *msg_member; 03195 msg_member = dbus_message_get_member (message); 03196 03197 if (msg_member == NULL) 03198 { 03199 if (member == NULL) 03200 return TRUE; 03201 else 03202 return FALSE; 03203 } 03204 03205 if (member == NULL) 03206 return FALSE; 03207 03208 if (strcmp (msg_member, member) == 0) 03209 return TRUE; 03210 03211 return FALSE; 03212 03213 } 03214 03226 dbus_bool_t 03227 dbus_message_set_error_name (DBusMessage *message, 03228 const char *error_name) 03229 { 03230 _dbus_return_val_if_fail (message != NULL, FALSE); 03231 _dbus_return_val_if_fail (!message->locked, FALSE); 03232 _dbus_return_val_if_fail (error_name == NULL || 03233 _dbus_check_is_valid_error_name (error_name), 03234 FALSE); 03235 03236 return set_or_delete_string_field (message, 03237 DBUS_HEADER_FIELD_ERROR_NAME, 03238 DBUS_TYPE_STRING, 03239 error_name); 03240 } 03241 03252 const char* 03253 dbus_message_get_error_name (DBusMessage *message) 03254 { 03255 const char *v; 03256 03257 _dbus_return_val_if_fail (message != NULL, NULL); 03258 03259 v = NULL; /* in case field doesn't exist */ 03260 _dbus_header_get_field_basic (&message->header, 03261 DBUS_HEADER_FIELD_ERROR_NAME, 03262 DBUS_TYPE_STRING, 03263 (void *) &v); 03264 return v; 03265 } 03266 03280 dbus_bool_t 03281 dbus_message_set_destination (DBusMessage *message, 03282 const char *destination) 03283 { 03284 _dbus_return_val_if_fail (message != NULL, FALSE); 03285 _dbus_return_val_if_fail (!message->locked, FALSE); 03286 _dbus_return_val_if_fail (destination == NULL || 03287 _dbus_check_is_valid_bus_name (destination), 03288 FALSE); 03289 03290 return set_or_delete_string_field (message, 03291 DBUS_HEADER_FIELD_DESTINATION, 03292 DBUS_TYPE_STRING, 03293 destination); 03294 } 03295 03305 const char* 03306 dbus_message_get_destination (DBusMessage *message) 03307 { 03308 const char *v; 03309 03310 _dbus_return_val_if_fail (message != NULL, NULL); 03311 03312 v = NULL; /* in case field doesn't exist */ 03313 _dbus_header_get_field_basic (&message->header, 03314 DBUS_HEADER_FIELD_DESTINATION, 03315 DBUS_TYPE_STRING, 03316 (void *) &v); 03317 return v; 03318 } 03319 03334 dbus_bool_t 03335 dbus_message_set_sender (DBusMessage *message, 03336 const char *sender) 03337 { 03338 _dbus_return_val_if_fail (message != NULL, FALSE); 03339 _dbus_return_val_if_fail (!message->locked, FALSE); 03340 _dbus_return_val_if_fail (sender == NULL || 03341 _dbus_check_is_valid_bus_name (sender), 03342 FALSE); 03343 03344 return set_or_delete_string_field (message, 03345 DBUS_HEADER_FIELD_SENDER, 03346 DBUS_TYPE_STRING, 03347 sender); 03348 } 03349 03365 const char* 03366 dbus_message_get_sender (DBusMessage *message) 03367 { 03368 const char *v; 03369 03370 _dbus_return_val_if_fail (message != NULL, NULL); 03371 03372 v = NULL; /* in case field doesn't exist */ 03373 _dbus_header_get_field_basic (&message->header, 03374 DBUS_HEADER_FIELD_SENDER, 03375 DBUS_TYPE_STRING, 03376 (void *) &v); 03377 return v; 03378 } 03379 03398 const char* 03399 dbus_message_get_signature (DBusMessage *message) 03400 { 03401 const DBusString *type_str; 03402 int type_pos; 03403 03404 _dbus_return_val_if_fail (message != NULL, NULL); 03405 03406 get_const_signature (&message->header, &type_str, &type_pos); 03407 03408 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03409 } 03410 03411 static dbus_bool_t 03412 _dbus_message_has_type_interface_member (DBusMessage *message, 03413 int type, 03414 const char *interface, 03415 const char *member) 03416 { 03417 const char *n; 03418 03419 _dbus_assert (message != NULL); 03420 _dbus_assert (interface != NULL); 03421 _dbus_assert (member != NULL); 03422 03423 if (dbus_message_get_type (message) != type) 03424 return FALSE; 03425 03426 /* Optimize by checking the short member name first 03427 * instead of the longer interface name 03428 */ 03429 03430 n = dbus_message_get_member (message); 03431 03432 if (n && strcmp (n, member) == 0) 03433 { 03434 n = dbus_message_get_interface (message); 03435 03436 if (n == NULL || strcmp (n, interface) == 0) 03437 return TRUE; 03438 } 03439 03440 return FALSE; 03441 } 03442 03457 dbus_bool_t 03458 dbus_message_is_method_call (DBusMessage *message, 03459 const char *interface, 03460 const char *method) 03461 { 03462 _dbus_return_val_if_fail (message != NULL, FALSE); 03463 _dbus_return_val_if_fail (interface != NULL, FALSE); 03464 _dbus_return_val_if_fail (method != NULL, FALSE); 03465 /* don't check that interface/method are valid since it would be 03466 * expensive, and not catch many common errors 03467 */ 03468 03469 return _dbus_message_has_type_interface_member (message, 03470 DBUS_MESSAGE_TYPE_METHOD_CALL, 03471 interface, method); 03472 } 03473 03485 dbus_bool_t 03486 dbus_message_is_signal (DBusMessage *message, 03487 const char *interface, 03488 const char *signal_name) 03489 { 03490 _dbus_return_val_if_fail (message != NULL, FALSE); 03491 _dbus_return_val_if_fail (interface != NULL, FALSE); 03492 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03493 /* don't check that interface/name are valid since it would be 03494 * expensive, and not catch many common errors 03495 */ 03496 03497 return _dbus_message_has_type_interface_member (message, 03498 DBUS_MESSAGE_TYPE_SIGNAL, 03499 interface, signal_name); 03500 } 03501 03512 dbus_bool_t 03513 dbus_message_is_error (DBusMessage *message, 03514 const char *error_name) 03515 { 03516 const char *n; 03517 03518 _dbus_return_val_if_fail (message != NULL, FALSE); 03519 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03520 /* don't check that error_name is valid since it would be expensive, 03521 * and not catch many common errors 03522 */ 03523 03524 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03525 return FALSE; 03526 03527 n = dbus_message_get_error_name (message); 03528 03529 if (n && strcmp (n, error_name) == 0) 03530 return TRUE; 03531 else 03532 return FALSE; 03533 } 03534 03545 dbus_bool_t 03546 dbus_message_has_destination (DBusMessage *message, 03547 const char *name) 03548 { 03549 const char *s; 03550 03551 _dbus_return_val_if_fail (message != NULL, FALSE); 03552 _dbus_return_val_if_fail (name != NULL, FALSE); 03553 /* don't check that name is valid since it would be expensive, and 03554 * not catch many common errors 03555 */ 03556 03557 s = dbus_message_get_destination (message); 03558 03559 if (s && strcmp (s, name) == 0) 03560 return TRUE; 03561 else 03562 return FALSE; 03563 } 03564 03580 dbus_bool_t 03581 dbus_message_has_sender (DBusMessage *message, 03582 const char *name) 03583 { 03584 const char *s; 03585 03586 _dbus_return_val_if_fail (message != NULL, FALSE); 03587 _dbus_return_val_if_fail (name != NULL, FALSE); 03588 /* don't check that name is valid since it would be expensive, and 03589 * not catch many common errors 03590 */ 03591 03592 s = dbus_message_get_sender (message); 03593 03594 if (s && strcmp (s, name) == 0) 03595 return TRUE; 03596 else 03597 return FALSE; 03598 } 03599 03609 dbus_bool_t 03610 dbus_message_has_signature (DBusMessage *message, 03611 const char *signature) 03612 { 03613 const char *s; 03614 03615 _dbus_return_val_if_fail (message != NULL, FALSE); 03616 _dbus_return_val_if_fail (signature != NULL, FALSE); 03617 /* don't check that signature is valid since it would be expensive, 03618 * and not catch many common errors 03619 */ 03620 03621 s = dbus_message_get_signature (message); 03622 03623 if (s && strcmp (s, signature) == 0) 03624 return TRUE; 03625 else 03626 return FALSE; 03627 } 03628 03651 dbus_bool_t 03652 dbus_set_error_from_message (DBusError *error, 03653 DBusMessage *message) 03654 { 03655 const char *str; 03656 03657 _dbus_return_val_if_fail (message != NULL, FALSE); 03658 _dbus_return_val_if_error_is_set (error, FALSE); 03659 03660 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03661 return FALSE; 03662 03663 str = NULL; 03664 dbus_message_get_args (message, NULL, 03665 DBUS_TYPE_STRING, &str, 03666 DBUS_TYPE_INVALID); 03667 03668 dbus_set_error (error, dbus_message_get_error_name (message), 03669 str ? "%s" : NULL, str); 03670 03671 return TRUE; 03672 } 03673 03680 dbus_bool_t 03681 dbus_message_contains_unix_fds(DBusMessage *message) 03682 { 03683 #ifdef HAVE_UNIX_FD_PASSING 03684 _dbus_assert(message); 03685 03686 return message->n_unix_fds > 0; 03687 #else 03688 return FALSE; 03689 #endif 03690 } 03691 03710 #define INITIAL_LOADER_DATA_LEN 32 03711 03718 DBusMessageLoader* 03719 _dbus_message_loader_new (void) 03720 { 03721 DBusMessageLoader *loader; 03722 03723 loader = dbus_new0 (DBusMessageLoader, 1); 03724 if (loader == NULL) 03725 return NULL; 03726 03727 loader->refcount = 1; 03728 03729 loader->corrupted = FALSE; 03730 loader->corruption_reason = DBUS_VALID; 03731 03732 /* this can be configured by the app, but defaults to the protocol max */ 03733 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03734 03735 /* We set a very relatively conservative default here since due to how 03736 SCM_RIGHTS works we need to preallocate an fd array of the maximum 03737 number of unix fds we want to receive in advance. A 03738 try-and-reallocate loop is not possible. */ 03739 loader->max_message_unix_fds = 1024; 03740 03741 if (!_dbus_string_init (&loader->data)) 03742 { 03743 dbus_free (loader); 03744 return NULL; 03745 } 03746 03747 /* preallocate the buffer for speed, ignore failure */ 03748 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03749 _dbus_string_set_length (&loader->data, 0); 03750 03751 #ifdef HAVE_UNIX_FD_PASSING 03752 loader->unix_fds = NULL; 03753 loader->n_unix_fds = loader->n_unix_fds_allocated = 0; 03754 loader->unix_fds_outstanding = FALSE; 03755 #endif 03756 03757 return loader; 03758 } 03759 03766 DBusMessageLoader * 03767 _dbus_message_loader_ref (DBusMessageLoader *loader) 03768 { 03769 loader->refcount += 1; 03770 03771 return loader; 03772 } 03773 03780 void 03781 _dbus_message_loader_unref (DBusMessageLoader *loader) 03782 { 03783 loader->refcount -= 1; 03784 if (loader->refcount == 0) 03785 { 03786 #ifdef HAVE_UNIX_FD_PASSING 03787 close_unix_fds(loader->unix_fds, &loader->n_unix_fds); 03788 dbus_free(loader->unix_fds); 03789 #endif 03790 _dbus_list_foreach (&loader->messages, 03791 (DBusForeachFunction) dbus_message_unref, 03792 NULL); 03793 _dbus_list_clear (&loader->messages); 03794 _dbus_string_free (&loader->data); 03795 dbus_free (loader); 03796 } 03797 } 03798 03817 void 03818 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 03819 DBusString **buffer) 03820 { 03821 _dbus_assert (!loader->buffer_outstanding); 03822 03823 *buffer = &loader->data; 03824 03825 loader->buffer_outstanding = TRUE; 03826 } 03827 03838 void 03839 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 03840 DBusString *buffer, 03841 int bytes_read) 03842 { 03843 _dbus_assert (loader->buffer_outstanding); 03844 _dbus_assert (buffer == &loader->data); 03845 03846 loader->buffer_outstanding = FALSE; 03847 } 03848 03859 dbus_bool_t 03860 _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, 03861 int **fds, 03862 unsigned *max_n_fds) 03863 { 03864 #ifdef HAVE_UNIX_FD_PASSING 03865 _dbus_assert (!loader->unix_fds_outstanding); 03866 03867 /* Allocate space where we can put the fds we read. We allocate 03868 space for max_message_unix_fds since this is an 03869 upper limit how many fds can be received within a single 03870 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic 03871 we are allocating the maximum possible array size right from the 03872 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed 03873 there is no better way. */ 03874 03875 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds) 03876 { 03877 int *a = dbus_realloc(loader->unix_fds, 03878 loader->max_message_unix_fds * sizeof(loader->unix_fds[0])); 03879 03880 if (!a) 03881 return FALSE; 03882 03883 loader->unix_fds = a; 03884 loader->n_unix_fds_allocated = loader->max_message_unix_fds; 03885 } 03886 03887 *fds = loader->unix_fds + loader->n_unix_fds; 03888 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds; 03889 03890 loader->unix_fds_outstanding = TRUE; 03891 return TRUE; 03892 #else 03893 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03894 return FALSE; 03895 #endif 03896 } 03897 03908 void 03909 _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, 03910 int *fds, 03911 unsigned n_fds) 03912 { 03913 #ifdef HAVE_UNIX_FD_PASSING 03914 _dbus_assert(loader->unix_fds_outstanding); 03915 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds); 03916 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated); 03917 03918 loader->n_unix_fds += n_fds; 03919 loader->unix_fds_outstanding = FALSE; 03920 #else 03921 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03922 #endif 03923 } 03924 03925 /* 03926 * FIXME when we move the header out of the buffer, that memmoves all 03927 * buffered messages. Kind of crappy. 03928 * 03929 * Also we copy the header and body, which is kind of crappy. To 03930 * avoid this, we have to allow header and body to be in a single 03931 * memory block, which is good for messages we read and bad for 03932 * messages we are creating. But we could move_len() the buffer into 03933 * this single memory block, and move_len() will just swap the buffers 03934 * if you're moving the entire buffer replacing the dest string. 03935 * 03936 * We could also have the message loader tell the transport how many 03937 * bytes to read; so it would first ask for some arbitrary number like 03938 * 256, then if the message was incomplete it would use the 03939 * header/body len to ask for exactly the size of the message (or 03940 * blocks the size of a typical kernel buffer for the socket). That 03941 * way we don't get trailing bytes in the buffer that have to be 03942 * memmoved. Though I suppose we also don't have a chance of reading a 03943 * bunch of small messages at once, so the optimization may be stupid. 03944 * 03945 * Another approach would be to keep a "start" index into 03946 * loader->data and only delete it occasionally, instead of after 03947 * each message is loaded. 03948 * 03949 * load_message() returns FALSE if not enough memory OR the loader was corrupted 03950 */ 03951 static dbus_bool_t 03952 load_message (DBusMessageLoader *loader, 03953 DBusMessage *message, 03954 int byte_order, 03955 int fields_array_len, 03956 int header_len, 03957 int body_len) 03958 { 03959 dbus_bool_t oom; 03960 DBusValidity validity; 03961 const DBusString *type_str; 03962 int type_pos; 03963 DBusValidationMode mode; 03964 dbus_uint32_t n_unix_fds = 0; 03965 03966 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 03967 03968 oom = FALSE; 03969 03970 #if 0 03971 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 03972 #endif 03973 03974 /* 1. VALIDATE AND COPY OVER HEADER */ 03975 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 03976 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 03977 03978 if (!_dbus_header_load (&message->header, 03979 mode, 03980 &validity, 03981 byte_order, 03982 fields_array_len, 03983 header_len, 03984 body_len, 03985 &loader->data, 0, 03986 _dbus_string_get_length (&loader->data))) 03987 { 03988 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 03989 03990 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 03991 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 03992 _dbus_assert (validity != DBUS_VALID); 03993 03994 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 03995 oom = TRUE; 03996 else 03997 { 03998 loader->corrupted = TRUE; 03999 loader->corruption_reason = validity; 04000 } 04001 goto failed; 04002 } 04003 04004 _dbus_assert (validity == DBUS_VALID); 04005 04006 message->byte_order = byte_order; 04007 04008 /* 2. VALIDATE BODY */ 04009 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 04010 { 04011 get_const_signature (&message->header, &type_str, &type_pos); 04012 04013 /* Because the bytes_remaining arg is NULL, this validates that the 04014 * body is the right length 04015 */ 04016 validity = _dbus_validate_body_with_reason (type_str, 04017 type_pos, 04018 byte_order, 04019 NULL, 04020 &loader->data, 04021 header_len, 04022 body_len); 04023 if (validity != DBUS_VALID) 04024 { 04025 _dbus_verbose ("Failed to validate message body code %d\n", validity); 04026 04027 loader->corrupted = TRUE; 04028 loader->corruption_reason = validity; 04029 04030 goto failed; 04031 } 04032 } 04033 04034 /* 3. COPY OVER UNIX FDS */ 04035 _dbus_header_get_field_basic(&message->header, 04036 DBUS_HEADER_FIELD_UNIX_FDS, 04037 DBUS_TYPE_UINT32, 04038 &n_unix_fds); 04039 04040 #ifdef HAVE_UNIX_FD_PASSING 04041 04042 if (n_unix_fds > loader->n_unix_fds) 04043 { 04044 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n", 04045 n_unix_fds, loader->n_unix_fds); 04046 04047 loader->corrupted = TRUE; 04048 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04049 goto failed; 04050 } 04051 04052 /* If this was a recycled message there might still be 04053 some memory allocated for the fds */ 04054 dbus_free(message->unix_fds); 04055 04056 if (n_unix_fds > 0) 04057 { 04058 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0])); 04059 if (message->unix_fds == NULL) 04060 { 04061 _dbus_verbose ("Failed to allocate file descriptor array\n"); 04062 oom = TRUE; 04063 goto failed; 04064 } 04065 04066 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; 04067 loader->n_unix_fds -= n_unix_fds; 04068 memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0])); 04069 } 04070 else 04071 message->unix_fds = NULL; 04072 04073 #else 04074 04075 if (n_unix_fds > 0) 04076 { 04077 _dbus_verbose ("Hmm, message claims to come with file descriptors " 04078 "but that's not supported on our platform, disconnecting.\n"); 04079 04080 loader->corrupted = TRUE; 04081 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04082 goto failed; 04083 } 04084 04085 #endif 04086 04087 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 04088 04089 if (!_dbus_list_append (&loader->messages, message)) 04090 { 04091 _dbus_verbose ("Failed to append new message to loader queue\n"); 04092 oom = TRUE; 04093 goto failed; 04094 } 04095 04096 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 04097 _dbus_assert (_dbus_string_get_length (&loader->data) >= 04098 (header_len + body_len)); 04099 04100 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 04101 { 04102 _dbus_verbose ("Failed to move body into new message\n"); 04103 oom = TRUE; 04104 goto failed; 04105 } 04106 04107 _dbus_string_delete (&loader->data, 0, header_len + body_len); 04108 04109 /* don't waste more than 2k of memory */ 04110 _dbus_string_compact (&loader->data, 2048); 04111 04112 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 04113 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 04114 04115 _dbus_verbose ("Loaded message %p\n", message); 04116 04117 _dbus_assert (!oom); 04118 _dbus_assert (!loader->corrupted); 04119 _dbus_assert (loader->messages != NULL); 04120 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04121 04122 return TRUE; 04123 04124 failed: 04125 04126 /* Clean up */ 04127 04128 /* does nothing if the message isn't in the list */ 04129 _dbus_list_remove_last (&loader->messages, message); 04130 04131 if (oom) 04132 _dbus_assert (!loader->corrupted); 04133 else 04134 _dbus_assert (loader->corrupted); 04135 04136 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 04137 04138 return FALSE; 04139 } 04140 04155 dbus_bool_t 04156 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 04157 { 04158 while (!loader->corrupted && 04159 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 04160 { 04161 DBusValidity validity; 04162 int byte_order, fields_array_len, header_len, body_len; 04163 04164 if (_dbus_header_have_message_untrusted (loader->max_message_size, 04165 &validity, 04166 &byte_order, 04167 &fields_array_len, 04168 &header_len, 04169 &body_len, 04170 &loader->data, 0, 04171 _dbus_string_get_length (&loader->data))) 04172 { 04173 DBusMessage *message; 04174 04175 _dbus_assert (validity == DBUS_VALID); 04176 04177 message = dbus_message_new_empty_header (); 04178 if (message == NULL) 04179 return FALSE; 04180 04181 if (!load_message (loader, message, 04182 byte_order, fields_array_len, 04183 header_len, body_len)) 04184 { 04185 dbus_message_unref (message); 04186 /* load_message() returns false if corrupted or OOM; if 04187 * corrupted then return TRUE for not OOM 04188 */ 04189 return loader->corrupted; 04190 } 04191 04192 _dbus_assert (loader->messages != NULL); 04193 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04194 } 04195 else 04196 { 04197 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 04198 validity); 04199 if (validity != DBUS_VALID) 04200 { 04201 loader->corrupted = TRUE; 04202 loader->corruption_reason = validity; 04203 } 04204 return TRUE; 04205 } 04206 } 04207 04208 return TRUE; 04209 } 04210 04218 DBusMessage* 04219 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 04220 { 04221 if (loader->messages) 04222 return loader->messages->data; 04223 else 04224 return NULL; 04225 } 04226 04235 DBusMessage* 04236 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 04237 { 04238 return _dbus_list_pop_first (&loader->messages); 04239 } 04240 04249 DBusList* 04250 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 04251 { 04252 return _dbus_list_pop_first_link (&loader->messages); 04253 } 04254 04261 void 04262 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 04263 DBusList *link) 04264 { 04265 _dbus_list_prepend_link (&loader->messages, link); 04266 } 04267 04277 dbus_bool_t 04278 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 04279 { 04280 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04281 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04282 return loader->corrupted; 04283 } 04284 04291 DBusValidity 04292 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 04293 { 04294 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04295 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04296 04297 return loader->corruption_reason; 04298 } 04299 04306 void 04307 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 04308 long size) 04309 { 04310 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 04311 { 04312 _dbus_verbose ("clamping requested max message size %ld to %d\n", 04313 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 04314 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 04315 } 04316 loader->max_message_size = size; 04317 } 04318 04325 long 04326 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 04327 { 04328 return loader->max_message_size; 04329 } 04330 04337 void 04338 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, 04339 long n) 04340 { 04341 if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS) 04342 { 04343 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n", 04344 n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS); 04345 n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS; 04346 } 04347 loader->max_message_unix_fds = n; 04348 } 04349 04356 long 04357 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) 04358 { 04359 return loader->max_message_unix_fds; 04360 } 04361 04362 static DBusDataSlotAllocator slot_allocator; 04363 _DBUS_DEFINE_GLOBAL_LOCK (message_slots); 04364 04379 dbus_bool_t 04380 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 04381 { 04382 return _dbus_data_slot_allocator_alloc (&slot_allocator, 04383 &_DBUS_LOCK_NAME (message_slots), 04384 slot_p); 04385 } 04386 04398 void 04399 dbus_message_free_data_slot (dbus_int32_t *slot_p) 04400 { 04401 _dbus_return_if_fail (*slot_p >= 0); 04402 04403 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 04404 } 04405 04419 dbus_bool_t 04420 dbus_message_set_data (DBusMessage *message, 04421 dbus_int32_t slot, 04422 void *data, 04423 DBusFreeFunction free_data_func) 04424 { 04425 DBusFreeFunction old_free_func; 04426 void *old_data; 04427 dbus_bool_t retval; 04428 04429 _dbus_return_val_if_fail (message != NULL, FALSE); 04430 _dbus_return_val_if_fail (slot >= 0, FALSE); 04431 04432 retval = _dbus_data_slot_list_set (&slot_allocator, 04433 &message->slot_list, 04434 slot, data, free_data_func, 04435 &old_free_func, &old_data); 04436 04437 if (retval) 04438 { 04439 /* Do the actual free outside the message lock */ 04440 if (old_free_func) 04441 (* old_free_func) (old_data); 04442 } 04443 04444 return retval; 04445 } 04446 04455 void* 04456 dbus_message_get_data (DBusMessage *message, 04457 dbus_int32_t slot) 04458 { 04459 void *res; 04460 04461 _dbus_return_val_if_fail (message != NULL, NULL); 04462 04463 res = _dbus_data_slot_list_get (&slot_allocator, 04464 &message->slot_list, 04465 slot); 04466 04467 return res; 04468 } 04469 04483 int 04484 dbus_message_type_from_string (const char *type_str) 04485 { 04486 if (strcmp (type_str, "method_call") == 0) 04487 return DBUS_MESSAGE_TYPE_METHOD_CALL; 04488 if (strcmp (type_str, "method_return") == 0) 04489 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 04490 else if (strcmp (type_str, "signal") == 0) 04491 return DBUS_MESSAGE_TYPE_SIGNAL; 04492 else if (strcmp (type_str, "error") == 0) 04493 return DBUS_MESSAGE_TYPE_ERROR; 04494 else 04495 return DBUS_MESSAGE_TYPE_INVALID; 04496 } 04497 04511 const char * 04512 dbus_message_type_to_string (int type) 04513 { 04514 switch (type) 04515 { 04516 case DBUS_MESSAGE_TYPE_METHOD_CALL: 04517 return "method_call"; 04518 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 04519 return "method_return"; 04520 case DBUS_MESSAGE_TYPE_SIGNAL: 04521 return "signal"; 04522 case DBUS_MESSAGE_TYPE_ERROR: 04523 return "error"; 04524 default: 04525 return "invalid"; 04526 } 04527 } 04528 04541 dbus_bool_t 04542 dbus_message_marshal (DBusMessage *msg, 04543 char **marshalled_data_p, 04544 int *len_p) 04545 { 04546 DBusString tmp; 04547 dbus_bool_t was_locked; 04548 04549 _dbus_return_val_if_fail (msg != NULL, FALSE); 04550 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04551 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04552 04553 if (!_dbus_string_init (&tmp)) 04554 return FALSE; 04555 04556 /* Ensure the message is locked, to ensure the length header is filled in. */ 04557 was_locked = msg->locked; 04558 04559 if (!was_locked) 04560 dbus_message_lock (msg); 04561 04562 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04563 goto fail; 04564 04565 *len_p = _dbus_string_get_length (&tmp); 04566 04567 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04568 goto fail; 04569 04570 *len_p = _dbus_string_get_length (&tmp); 04571 04572 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04573 goto fail; 04574 04575 _dbus_string_free (&tmp); 04576 04577 if (!was_locked) 04578 msg->locked = FALSE; 04579 04580 return TRUE; 04581 04582 fail: 04583 _dbus_string_free (&tmp); 04584 04585 if (!was_locked) 04586 msg->locked = FALSE; 04587 04588 return FALSE; 04589 } 04590 04603 DBusMessage * 04604 dbus_message_demarshal (const char *str, 04605 int len, 04606 DBusError *error) 04607 { 04608 DBusMessageLoader *loader; 04609 DBusString *buffer; 04610 DBusMessage *msg; 04611 04612 _dbus_return_val_if_fail (str != NULL, NULL); 04613 04614 loader = _dbus_message_loader_new (); 04615 04616 if (loader == NULL) 04617 return NULL; 04618 04619 _dbus_message_loader_get_buffer (loader, &buffer); 04620 _dbus_string_append_len (buffer, str, len); 04621 _dbus_message_loader_return_buffer (loader, buffer, len); 04622 04623 if (!_dbus_message_loader_queue_messages (loader)) 04624 goto fail_oom; 04625 04626 if (_dbus_message_loader_get_is_corrupted (loader)) 04627 goto fail_corrupt; 04628 04629 msg = _dbus_message_loader_pop_message (loader); 04630 04631 if (!msg) 04632 goto fail_oom; 04633 04634 _dbus_message_loader_unref (loader); 04635 return msg; 04636 04637 fail_corrupt: 04638 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04639 _dbus_validity_to_error_message (loader->corruption_reason)); 04640 _dbus_message_loader_unref (loader); 04641 return NULL; 04642 04643 fail_oom: 04644 _DBUS_SET_OOM (error); 04645 _dbus_message_loader_unref (loader); 04646 return NULL; 04647 } 04648 04662 int 04663 dbus_message_demarshal_bytes_needed(const char *buf, 04664 int len) 04665 { 04666 DBusString str; 04667 int byte_order, fields_array_len, header_len, body_len; 04668 DBusValidity validity = DBUS_VALID; 04669 int have_message; 04670 04671 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04672 return 0; 04673 04674 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04675 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04676 _dbus_string_init_const_len (&str, buf, len); 04677 04678 validity = DBUS_VALID; 04679 have_message 04680 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04681 &validity, &byte_order, 04682 &fields_array_len, 04683 &header_len, 04684 &body_len, 04685 &str, 0, 04686 len); 04687 _dbus_string_free (&str); 04688 04689 if (validity == DBUS_VALID) 04690 { 04691 _dbus_assert (have_message || (header_len + body_len) > len); 04692 return header_len + body_len; 04693 } 04694 else 04695 { 04696 return -1; /* broken! */ 04697 } 04698 } 04699 04702 /* tests in dbus-message-util.c */