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.h" 00039 #include "dbus-sysdeps-unix.h" 00040 #endif 00041 00042 #include <string.h> 00043 00044 static void dbus_message_finalize (DBusMessage *message); 00045 00056 /* Not thread locked, but strictly const/read-only so should be OK 00057 */ 00059 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, ""); 00060 00061 /* these have wacky values to help trap uninitialized iterators; 00062 * but has to fit in 3 bits 00063 */ 00064 enum { 00065 DBUS_MESSAGE_ITER_TYPE_READER = 3, 00066 DBUS_MESSAGE_ITER_TYPE_WRITER = 7 00067 }; 00068 00070 typedef struct DBusMessageRealIter DBusMessageRealIter; 00071 00077 struct DBusMessageRealIter 00078 { 00079 DBusMessage *message; 00080 dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 00081 dbus_uint32_t iter_type : 3; 00082 dbus_uint32_t sig_refcount : 8; 00083 union 00084 { 00085 DBusTypeWriter writer; 00086 DBusTypeReader reader; 00087 } u; 00088 }; 00089 00090 static void 00091 get_const_signature (DBusHeader *header, 00092 const DBusString **type_str_p, 00093 int *type_pos_p) 00094 { 00095 if (_dbus_header_get_field_raw (header, 00096 DBUS_HEADER_FIELD_SIGNATURE, 00097 type_str_p, 00098 type_pos_p)) 00099 { 00100 *type_pos_p += 1; /* skip the signature length which is 1 byte */ 00101 } 00102 else 00103 { 00104 *type_str_p = &_dbus_empty_signature_str; 00105 *type_pos_p = 0; 00106 } 00107 } 00108 00114 static void 00115 _dbus_message_byteswap (DBusMessage *message) 00116 { 00117 const DBusString *type_str; 00118 int type_pos; 00119 00120 if (message->byte_order == DBUS_COMPILER_BYTE_ORDER) 00121 return; 00122 00123 _dbus_verbose ("Swapping message into compiler byte order\n"); 00124 00125 get_const_signature (&message->header, &type_str, &type_pos); 00126 00127 _dbus_marshal_byteswap (type_str, type_pos, 00128 message->byte_order, 00129 DBUS_COMPILER_BYTE_ORDER, 00130 &message->body, 0); 00131 00132 message->byte_order = DBUS_COMPILER_BYTE_ORDER; 00133 00134 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER); 00135 } 00136 00143 #define ensure_byte_order(message) \ 00144 if (message->byte_order != DBUS_COMPILER_BYTE_ORDER) \ 00145 _dbus_message_byteswap (message) 00146 00157 void 00158 _dbus_message_get_network_data (DBusMessage *message, 00159 const DBusString **header, 00160 const DBusString **body) 00161 { 00162 _dbus_assert (message->locked); 00163 00164 *header = &message->header.data; 00165 *body = &message->body; 00166 } 00167 00177 void _dbus_message_get_unix_fds(DBusMessage *message, 00178 const int **fds, 00179 unsigned *n_fds) 00180 { 00181 _dbus_assert (message->locked); 00182 00183 #ifdef HAVE_UNIX_FD_PASSING 00184 *fds = message->unix_fds; 00185 *n_fds = message->n_unix_fds; 00186 #else 00187 *fds = NULL; 00188 *n_fds = 0; 00189 #endif 00190 } 00191 00203 void 00204 dbus_message_set_serial (DBusMessage *message, 00205 dbus_uint32_t serial) 00206 { 00207 _dbus_return_if_fail (message != NULL); 00208 _dbus_return_if_fail (!message->locked); 00209 00210 _dbus_header_set_serial (&message->header, serial); 00211 } 00212 00224 void 00225 _dbus_message_add_counter_link (DBusMessage *message, 00226 DBusList *link) 00227 { 00228 /* right now we don't recompute the delta when message 00229 * size changes, and that's OK for current purposes 00230 * I think, but could be important to change later. 00231 * Do recompute it whenever there are no outstanding counters, 00232 * since it's basically free. 00233 */ 00234 if (message->counters == NULL) 00235 { 00236 message->size_counter_delta = 00237 _dbus_string_get_length (&message->header.data) + 00238 _dbus_string_get_length (&message->body); 00239 00240 #ifdef HAVE_UNIX_FD_PASSING 00241 message->unix_fd_counter_delta = message->n_unix_fds; 00242 #endif 00243 00244 #if 0 00245 _dbus_verbose ("message has size %ld\n", 00246 message->size_counter_delta); 00247 #endif 00248 } 00249 00250 _dbus_list_append_link (&message->counters, link); 00251 00252 _dbus_counter_adjust_size (link->data, message->size_counter_delta); 00253 00254 #ifdef HAVE_UNIX_FD_PASSING 00255 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta); 00256 #endif 00257 } 00258 00268 dbus_bool_t 00269 _dbus_message_add_counter (DBusMessage *message, 00270 DBusCounter *counter) 00271 { 00272 DBusList *link; 00273 00274 link = _dbus_list_alloc_link (counter); 00275 if (link == NULL) 00276 return FALSE; 00277 00278 _dbus_counter_ref (counter); 00279 _dbus_message_add_counter_link (message, link); 00280 00281 return TRUE; 00282 } 00283 00292 void 00293 _dbus_message_remove_counter (DBusMessage *message, 00294 DBusCounter *counter, 00295 DBusList **link_return) 00296 { 00297 DBusList *link; 00298 00299 link = _dbus_list_find_last (&message->counters, 00300 counter); 00301 _dbus_assert (link != NULL); 00302 00303 _dbus_list_unlink (&message->counters, 00304 link); 00305 if (link_return) 00306 *link_return = link; 00307 else 00308 _dbus_list_free_link (link); 00309 00310 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00311 00312 #ifdef HAVE_UNIX_FD_PASSING 00313 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00314 #endif 00315 00316 _dbus_counter_unref (counter); 00317 } 00318 00329 void 00330 dbus_message_lock (DBusMessage *message) 00331 { 00332 if (!message->locked) 00333 { 00334 _dbus_header_update_lengths (&message->header, 00335 _dbus_string_get_length (&message->body)); 00336 00337 /* must have a signature if you have a body */ 00338 _dbus_assert (_dbus_string_get_length (&message->body) == 0 || 00339 dbus_message_get_signature (message) != NULL); 00340 00341 message->locked = TRUE; 00342 } 00343 } 00344 00345 static dbus_bool_t 00346 set_or_delete_string_field (DBusMessage *message, 00347 int field, 00348 int typecode, 00349 const char *value) 00350 { 00351 if (value == NULL) 00352 return _dbus_header_delete_field (&message->header, field); 00353 else 00354 return _dbus_header_set_field_basic (&message->header, 00355 field, 00356 typecode, 00357 &value); 00358 } 00359 00360 #if 0 00361 /* Probably we don't need to use this */ 00385 static dbus_bool_t 00386 _dbus_message_set_signature (DBusMessage *message, 00387 const char *signature) 00388 { 00389 _dbus_return_val_if_fail (message != NULL, FALSE); 00390 _dbus_return_val_if_fail (!message->locked, FALSE); 00391 _dbus_return_val_if_fail (signature == NULL || 00392 _dbus_check_is_valid_signature (signature)); 00393 /* can't delete the signature if you have a message body */ 00394 _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || 00395 signature != NULL); 00396 00397 return set_or_delete_string_field (message, 00398 DBUS_HEADER_FIELD_SIGNATURE, 00399 DBUS_TYPE_SIGNATURE, 00400 signature); 00401 } 00402 #endif 00403 00404 /* Message Cache 00405 * 00406 * We cache some DBusMessage to reduce the overhead of allocating 00407 * them. In my profiling this consistently made about an 8% 00408 * difference. It avoids the malloc for the message, the malloc for 00409 * the slot list, the malloc for the header string and body string, 00410 * and the associated free() calls. It does introduce another global 00411 * lock which could be a performance issue in certain cases. 00412 * 00413 * For the echo client/server the round trip time goes from around 00414 * .000077 to .000069 with the message cache on my laptop. The sysprof 00415 * change is as follows (numbers are cumulative percentage): 00416 * 00417 * with message cache implemented as array as it is now (0.000069 per): 00418 * new_empty_header 1.46 00419 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache) 00420 * mutex_unlock 0.25 00421 * self 0.41 00422 * unref 2.24 00423 * self 0.68 00424 * list_clear 0.43 00425 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache) 00426 * mutex_unlock 0.25 00427 * 00428 * with message cache implemented as list (0.000070 per roundtrip): 00429 * new_empty_header 2.72 00430 * list_pop_first 1.88 00431 * unref 3.3 00432 * list_prepend 1.63 00433 * 00434 * without cache (0.000077 per roundtrip): 00435 * new_empty_header 6.7 00436 * string_init_preallocated 3.43 00437 * dbus_malloc 2.43 00438 * dbus_malloc0 2.59 00439 * 00440 * unref 4.02 00441 * string_free 1.82 00442 * dbus_free 1.63 00443 * dbus_free 0.71 00444 * 00445 * If you implement the message_cache with a list, the primary reason 00446 * it's slower is that you add another thread lock (on the DBusList 00447 * mempool). 00448 */ 00449 00451 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE 00452 00454 #define MAX_MESSAGE_CACHE_SIZE 5 00455 00456 _DBUS_DEFINE_GLOBAL_LOCK (message_cache); 00457 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; 00458 static int message_cache_count = 0; 00459 static dbus_bool_t message_cache_shutdown_registered = FALSE; 00460 00461 static void 00462 dbus_message_cache_shutdown (void *data) 00463 { 00464 int i; 00465 00466 _DBUS_LOCK (message_cache); 00467 00468 i = 0; 00469 while (i < MAX_MESSAGE_CACHE_SIZE) 00470 { 00471 if (message_cache[i]) 00472 dbus_message_finalize (message_cache[i]); 00473 00474 ++i; 00475 } 00476 00477 message_cache_count = 0; 00478 message_cache_shutdown_registered = FALSE; 00479 00480 _DBUS_UNLOCK (message_cache); 00481 } 00482 00490 static DBusMessage* 00491 dbus_message_get_cached (void) 00492 { 00493 DBusMessage *message; 00494 int i; 00495 00496 message = NULL; 00497 00498 _DBUS_LOCK (message_cache); 00499 00500 _dbus_assert (message_cache_count >= 0); 00501 00502 if (message_cache_count == 0) 00503 { 00504 _DBUS_UNLOCK (message_cache); 00505 return NULL; 00506 } 00507 00508 /* This is not necessarily true unless count > 0, and 00509 * message_cache is uninitialized until the shutdown is 00510 * registered 00511 */ 00512 _dbus_assert (message_cache_shutdown_registered); 00513 00514 i = 0; 00515 while (i < MAX_MESSAGE_CACHE_SIZE) 00516 { 00517 if (message_cache[i]) 00518 { 00519 message = message_cache[i]; 00520 message_cache[i] = NULL; 00521 message_cache_count -= 1; 00522 break; 00523 } 00524 ++i; 00525 } 00526 _dbus_assert (message_cache_count >= 0); 00527 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00528 _dbus_assert (message != NULL); 00529 00530 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00531 00532 _dbus_assert (message->counters == NULL); 00533 00534 _DBUS_UNLOCK (message_cache); 00535 00536 return message; 00537 } 00538 00539 #ifdef HAVE_UNIX_FD_PASSING 00540 static void 00541 close_unix_fds(int *fds, unsigned *n_fds) 00542 { 00543 DBusError e; 00544 int i; 00545 00546 if (*n_fds <= 0) 00547 return; 00548 00549 dbus_error_init(&e); 00550 00551 for (i = 0; i < *n_fds; i++) 00552 { 00553 if (!_dbus_close(fds[i], &e)) 00554 { 00555 _dbus_warn("Failed to close file descriptor: %s\n", e.message); 00556 dbus_error_free(&e); 00557 } 00558 } 00559 00560 *n_fds = 0; 00561 00562 /* We don't free the array here, in case we can recycle it later */ 00563 } 00564 #endif 00565 00566 static void 00567 free_counter (void *element, 00568 void *data) 00569 { 00570 DBusCounter *counter = element; 00571 DBusMessage *message = data; 00572 00573 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00574 #ifdef HAVE_UNIX_FD_PASSING 00575 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00576 #endif 00577 00578 _dbus_counter_unref (counter); 00579 } 00580 00586 static void 00587 dbus_message_cache_or_finalize (DBusMessage *message) 00588 { 00589 dbus_bool_t was_cached; 00590 int i; 00591 00592 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00593 00594 /* This calls application code and has to be done first thing 00595 * without holding the lock 00596 */ 00597 _dbus_data_slot_list_clear (&message->slot_list); 00598 00599 _dbus_list_foreach (&message->counters, 00600 free_counter, message); 00601 _dbus_list_clear (&message->counters); 00602 00603 #ifdef HAVE_UNIX_FD_PASSING 00604 close_unix_fds(message->unix_fds, &message->n_unix_fds); 00605 #endif 00606 00607 was_cached = FALSE; 00608 00609 _DBUS_LOCK (message_cache); 00610 00611 if (!message_cache_shutdown_registered) 00612 { 00613 _dbus_assert (message_cache_count == 0); 00614 00615 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL)) 00616 goto out; 00617 00618 i = 0; 00619 while (i < MAX_MESSAGE_CACHE_SIZE) 00620 { 00621 message_cache[i] = NULL; 00622 ++i; 00623 } 00624 00625 message_cache_shutdown_registered = TRUE; 00626 } 00627 00628 _dbus_assert (message_cache_count >= 0); 00629 00630 if ((_dbus_string_get_length (&message->header.data) + 00631 _dbus_string_get_length (&message->body)) > 00632 MAX_MESSAGE_SIZE_TO_CACHE) 00633 goto out; 00634 00635 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE) 00636 goto out; 00637 00638 /* Find empty slot */ 00639 i = 0; 00640 while (message_cache[i] != NULL) 00641 ++i; 00642 00643 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00644 00645 _dbus_assert (message_cache[i] == NULL); 00646 message_cache[i] = message; 00647 message_cache_count += 1; 00648 was_cached = TRUE; 00649 #ifndef DBUS_DISABLE_CHECKS 00650 message->in_cache = TRUE; 00651 #endif 00652 00653 out: 00654 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00655 00656 _DBUS_UNLOCK (message_cache); 00657 00658 if (!was_cached) 00659 dbus_message_finalize (message); 00660 } 00661 00662 #ifndef DBUS_DISABLE_CHECKS 00663 static dbus_bool_t 00664 _dbus_message_iter_check (DBusMessageRealIter *iter) 00665 { 00666 if (iter == NULL) 00667 { 00668 _dbus_warn_check_failed ("dbus message iterator is NULL\n"); 00669 return FALSE; 00670 } 00671 00672 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER) 00673 { 00674 if (iter->u.reader.byte_order != iter->message->byte_order) 00675 { 00676 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n"); 00677 return FALSE; 00678 } 00679 /* because we swap the message into compiler order when you init an iter */ 00680 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); 00681 } 00682 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) 00683 { 00684 if (iter->u.writer.byte_order != iter->message->byte_order) 00685 { 00686 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n"); 00687 return FALSE; 00688 } 00689 /* because we swap the message into compiler order when you init an iter */ 00690 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); 00691 } 00692 else 00693 { 00694 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n"); 00695 return FALSE; 00696 } 00697 00698 if (iter->changed_stamp != iter->message->changed_stamp) 00699 { 00700 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); 00701 return FALSE; 00702 } 00703 00704 return TRUE; 00705 } 00706 #endif /* DBUS_DISABLE_CHECKS */ 00707 00722 dbus_bool_t 00723 _dbus_message_iter_get_args_valist (DBusMessageIter *iter, 00724 DBusError *error, 00725 int first_arg_type, 00726 va_list var_args) 00727 { 00728 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 00729 int spec_type, msg_type, i; 00730 dbus_bool_t retval; 00731 00732 _dbus_assert (_dbus_message_iter_check (real)); 00733 00734 retval = FALSE; 00735 00736 spec_type = first_arg_type; 00737 i = 0; 00738 00739 while (spec_type != DBUS_TYPE_INVALID) 00740 { 00741 msg_type = dbus_message_iter_get_arg_type (iter); 00742 00743 if (msg_type != spec_type) 00744 { 00745 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00746 "Argument %d is specified to be of type \"%s\", but " 00747 "is actually of type \"%s\"\n", i, 00748 _dbus_type_to_string (spec_type), 00749 _dbus_type_to_string (msg_type)); 00750 00751 goto out; 00752 } 00753 00754 if (spec_type == DBUS_TYPE_UNIX_FD) 00755 { 00756 #ifdef HAVE_UNIX_FD_PASSING 00757 DBusBasicValue idx; 00758 int *pfd, nfd; 00759 00760 pfd = va_arg (var_args, int*); 00761 _dbus_assert(pfd); 00762 00763 _dbus_type_reader_read_basic(&real->u.reader, &idx); 00764 00765 if (idx.u32 >= real->message->n_unix_fds) 00766 { 00767 dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE, 00768 "Message refers to file descriptor at index %i," 00769 "but has only %i descriptors attached.\n", 00770 idx.u32, 00771 real->message->n_unix_fds); 00772 goto out; 00773 } 00774 00775 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0) 00776 goto out; 00777 00778 *pfd = nfd; 00779 #else 00780 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00781 "Platform does not support file desciptor passing.\n"); 00782 goto out; 00783 #endif 00784 } 00785 else if (dbus_type_is_basic (spec_type)) 00786 { 00787 DBusBasicValue *ptr; 00788 00789 ptr = va_arg (var_args, DBusBasicValue*); 00790 00791 _dbus_assert (ptr != NULL); 00792 00793 _dbus_type_reader_read_basic (&real->u.reader, 00794 ptr); 00795 } 00796 else if (spec_type == DBUS_TYPE_ARRAY) 00797 { 00798 int element_type; 00799 int spec_element_type; 00800 const DBusBasicValue **ptr; 00801 int *n_elements_p; 00802 DBusTypeReader array; 00803 00804 spec_element_type = va_arg (var_args, int); 00805 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 00806 00807 if (spec_element_type != element_type) 00808 { 00809 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00810 "Argument %d is specified to be an array of \"%s\", but " 00811 "is actually an array of \"%s\"\n", 00812 i, 00813 _dbus_type_to_string (spec_element_type), 00814 _dbus_type_to_string (element_type)); 00815 00816 goto out; 00817 } 00818 00819 if (dbus_type_is_fixed (spec_element_type) && 00820 element_type != DBUS_TYPE_UNIX_FD) 00821 { 00822 ptr = va_arg (var_args, const DBusBasicValue**); 00823 n_elements_p = va_arg (var_args, int*); 00824 00825 _dbus_assert (ptr != NULL); 00826 _dbus_assert (n_elements_p != NULL); 00827 00828 _dbus_type_reader_recurse (&real->u.reader, &array); 00829 00830 _dbus_type_reader_read_fixed_multi (&array, 00831 (void *) ptr, n_elements_p); 00832 } 00833 else if (spec_element_type == DBUS_TYPE_STRING || 00834 spec_element_type == DBUS_TYPE_SIGNATURE || 00835 spec_element_type == DBUS_TYPE_OBJECT_PATH) 00836 { 00837 char ***str_array_p; 00838 int n_elements; 00839 char **str_array; 00840 00841 str_array_p = va_arg (var_args, char***); 00842 n_elements_p = va_arg (var_args, int*); 00843 00844 _dbus_assert (str_array_p != NULL); 00845 _dbus_assert (n_elements_p != NULL); 00846 00847 /* Count elements in the array */ 00848 _dbus_type_reader_recurse (&real->u.reader, &array); 00849 00850 n_elements = 0; 00851 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 00852 { 00853 ++n_elements; 00854 _dbus_type_reader_next (&array); 00855 } 00856 00857 str_array = dbus_new0 (char*, n_elements + 1); 00858 if (str_array == NULL) 00859 { 00860 _DBUS_SET_OOM (error); 00861 goto out; 00862 } 00863 00864 /* Now go through and dup each string */ 00865 _dbus_type_reader_recurse (&real->u.reader, &array); 00866 00867 i = 0; 00868 while (i < n_elements) 00869 { 00870 const char *s; 00871 _dbus_type_reader_read_basic (&array, 00872 (void *) &s); 00873 00874 str_array[i] = _dbus_strdup (s); 00875 if (str_array[i] == NULL) 00876 { 00877 dbus_free_string_array (str_array); 00878 _DBUS_SET_OOM (error); 00879 goto out; 00880 } 00881 00882 ++i; 00883 00884 if (!_dbus_type_reader_next (&array)) 00885 _dbus_assert (i == n_elements); 00886 } 00887 00888 _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); 00889 _dbus_assert (i == n_elements); 00890 _dbus_assert (str_array[i] == NULL); 00891 00892 *str_array_p = str_array; 00893 *n_elements_p = n_elements; 00894 } 00895 #ifndef DBUS_DISABLE_CHECKS 00896 else 00897 { 00898 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", 00899 _DBUS_FUNCTION_NAME); 00900 goto out; 00901 } 00902 #endif 00903 } 00904 #ifndef DBUS_DISABLE_CHECKS 00905 else 00906 { 00907 _dbus_warn ("you can only read arrays and basic types with %s for now\n", 00908 _DBUS_FUNCTION_NAME); 00909 goto out; 00910 } 00911 #endif 00912 00913 spec_type = va_arg (var_args, int); 00914 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) 00915 { 00916 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00917 "Message has only %d arguments, but more were expected", i); 00918 goto out; 00919 } 00920 00921 i++; 00922 } 00923 00924 retval = TRUE; 00925 00926 out: 00927 00928 return retval; 00929 } 00930 00989 dbus_uint32_t 00990 dbus_message_get_serial (DBusMessage *message) 00991 { 00992 _dbus_return_val_if_fail (message != NULL, 0); 00993 00994 return _dbus_header_get_serial (&message->header); 00995 } 00996 01005 dbus_bool_t 01006 dbus_message_set_reply_serial (DBusMessage *message, 01007 dbus_uint32_t reply_serial) 01008 { 01009 _dbus_return_val_if_fail (message != NULL, FALSE); 01010 _dbus_return_val_if_fail (!message->locked, FALSE); 01011 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */ 01012 01013 return _dbus_header_set_field_basic (&message->header, 01014 DBUS_HEADER_FIELD_REPLY_SERIAL, 01015 DBUS_TYPE_UINT32, 01016 &reply_serial); 01017 } 01018 01025 dbus_uint32_t 01026 dbus_message_get_reply_serial (DBusMessage *message) 01027 { 01028 dbus_uint32_t v_UINT32; 01029 01030 _dbus_return_val_if_fail (message != NULL, 0); 01031 01032 if (_dbus_header_get_field_basic (&message->header, 01033 DBUS_HEADER_FIELD_REPLY_SERIAL, 01034 DBUS_TYPE_UINT32, 01035 &v_UINT32)) 01036 return v_UINT32; 01037 else 01038 return 0; 01039 } 01040 01041 static void 01042 dbus_message_finalize (DBusMessage *message) 01043 { 01044 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01045 01046 /* This calls application callbacks! */ 01047 _dbus_data_slot_list_free (&message->slot_list); 01048 01049 _dbus_list_foreach (&message->counters, 01050 free_counter, message); 01051 _dbus_list_clear (&message->counters); 01052 01053 _dbus_header_free (&message->header); 01054 _dbus_string_free (&message->body); 01055 01056 #ifdef HAVE_UNIX_FD_PASSING 01057 close_unix_fds(message->unix_fds, &message->n_unix_fds); 01058 dbus_free(message->unix_fds); 01059 #endif 01060 01061 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01062 01063 dbus_free (message); 01064 } 01065 01066 static DBusMessage* 01067 dbus_message_new_empty_header (void) 01068 { 01069 DBusMessage *message; 01070 dbus_bool_t from_cache; 01071 01072 message = dbus_message_get_cached (); 01073 01074 if (message != NULL) 01075 { 01076 from_cache = TRUE; 01077 } 01078 else 01079 { 01080 from_cache = FALSE; 01081 message = dbus_new0 (DBusMessage, 1); 01082 if (message == NULL) 01083 return NULL; 01084 #ifndef DBUS_DISABLE_CHECKS 01085 message->generation = _dbus_current_generation; 01086 #endif 01087 01088 #ifdef HAVE_UNIX_FD_PASSING 01089 message->unix_fds = NULL; 01090 message->n_unix_fds_allocated = 0; 01091 #endif 01092 } 01093 01094 _dbus_atomic_inc (&message->refcount); 01095 01096 message->byte_order = DBUS_COMPILER_BYTE_ORDER; 01097 message->locked = FALSE; 01098 #ifndef DBUS_DISABLE_CHECKS 01099 message->in_cache = FALSE; 01100 #endif 01101 message->counters = NULL; 01102 message->size_counter_delta = 0; 01103 message->changed_stamp = 0; 01104 01105 #ifdef HAVE_UNIX_FD_PASSING 01106 message->n_unix_fds = 0; 01107 message->n_unix_fds_allocated = 0; 01108 message->unix_fd_counter_delta = 0; 01109 #endif 01110 01111 if (!from_cache) 01112 _dbus_data_slot_list_init (&message->slot_list); 01113 01114 if (from_cache) 01115 { 01116 _dbus_header_reinit (&message->header, message->byte_order); 01117 _dbus_string_set_length (&message->body, 0); 01118 } 01119 else 01120 { 01121 if (!_dbus_header_init (&message->header, message->byte_order)) 01122 { 01123 dbus_free (message); 01124 return NULL; 01125 } 01126 01127 if (!_dbus_string_init_preallocated (&message->body, 32)) 01128 { 01129 _dbus_header_free (&message->header); 01130 dbus_free (message); 01131 return NULL; 01132 } 01133 } 01134 01135 return message; 01136 } 01137 01150 DBusMessage* 01151 dbus_message_new (int message_type) 01152 { 01153 DBusMessage *message; 01154 01155 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL); 01156 01157 message = dbus_message_new_empty_header (); 01158 if (message == NULL) 01159 return NULL; 01160 01161 if (!_dbus_header_create (&message->header, 01162 message_type, 01163 NULL, NULL, NULL, NULL, NULL)) 01164 { 01165 dbus_message_unref (message); 01166 return NULL; 01167 } 01168 01169 return message; 01170 } 01171 01193 DBusMessage* 01194 dbus_message_new_method_call (const char *destination, 01195 const char *path, 01196 const char *interface, 01197 const char *method) 01198 { 01199 DBusMessage *message; 01200 01201 _dbus_return_val_if_fail (path != NULL, NULL); 01202 _dbus_return_val_if_fail (method != NULL, NULL); 01203 _dbus_return_val_if_fail (destination == NULL || 01204 _dbus_check_is_valid_bus_name (destination), NULL); 01205 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01206 _dbus_return_val_if_fail (interface == NULL || 01207 _dbus_check_is_valid_interface (interface), NULL); 01208 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); 01209 01210 message = dbus_message_new_empty_header (); 01211 if (message == NULL) 01212 return NULL; 01213 01214 if (!_dbus_header_create (&message->header, 01215 DBUS_MESSAGE_TYPE_METHOD_CALL, 01216 destination, path, interface, method, NULL)) 01217 { 01218 dbus_message_unref (message); 01219 return NULL; 01220 } 01221 01222 return message; 01223 } 01224 01232 DBusMessage* 01233 dbus_message_new_method_return (DBusMessage *method_call) 01234 { 01235 DBusMessage *message; 01236 const char *sender; 01237 01238 _dbus_return_val_if_fail (method_call != NULL, NULL); 01239 01240 sender = dbus_message_get_sender (method_call); 01241 01242 /* sender is allowed to be null here in peer-to-peer case */ 01243 01244 message = dbus_message_new_empty_header (); 01245 if (message == NULL) 01246 return NULL; 01247 01248 if (!_dbus_header_create (&message->header, 01249 DBUS_MESSAGE_TYPE_METHOD_RETURN, 01250 sender, NULL, NULL, NULL, NULL)) 01251 { 01252 dbus_message_unref (message); 01253 return NULL; 01254 } 01255 01256 dbus_message_set_no_reply (message, TRUE); 01257 01258 if (!dbus_message_set_reply_serial (message, 01259 dbus_message_get_serial (method_call))) 01260 { 01261 dbus_message_unref (message); 01262 return NULL; 01263 } 01264 01265 return message; 01266 } 01267 01282 DBusMessage* 01283 dbus_message_new_signal (const char *path, 01284 const char *interface, 01285 const char *name) 01286 { 01287 DBusMessage *message; 01288 01289 _dbus_return_val_if_fail (path != NULL, NULL); 01290 _dbus_return_val_if_fail (interface != NULL, NULL); 01291 _dbus_return_val_if_fail (name != NULL, NULL); 01292 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01293 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL); 01294 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); 01295 01296 message = dbus_message_new_empty_header (); 01297 if (message == NULL) 01298 return NULL; 01299 01300 if (!_dbus_header_create (&message->header, 01301 DBUS_MESSAGE_TYPE_SIGNAL, 01302 NULL, path, interface, name, NULL)) 01303 { 01304 dbus_message_unref (message); 01305 return NULL; 01306 } 01307 01308 dbus_message_set_no_reply (message, TRUE); 01309 01310 return message; 01311 } 01312 01327 DBusMessage* 01328 dbus_message_new_error (DBusMessage *reply_to, 01329 const char *error_name, 01330 const char *error_message) 01331 { 01332 DBusMessage *message; 01333 const char *sender; 01334 DBusMessageIter iter; 01335 01336 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01337 _dbus_return_val_if_fail (error_name != NULL, NULL); 01338 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01339 01340 sender = dbus_message_get_sender (reply_to); 01341 01342 /* sender may be NULL for non-message-bus case or 01343 * when the message bus is dealing with an unregistered 01344 * connection. 01345 */ 01346 message = dbus_message_new_empty_header (); 01347 if (message == NULL) 01348 return NULL; 01349 01350 if (!_dbus_header_create (&message->header, 01351 DBUS_MESSAGE_TYPE_ERROR, 01352 sender, NULL, NULL, NULL, error_name)) 01353 { 01354 dbus_message_unref (message); 01355 return NULL; 01356 } 01357 01358 dbus_message_set_no_reply (message, TRUE); 01359 01360 if (!dbus_message_set_reply_serial (message, 01361 dbus_message_get_serial (reply_to))) 01362 { 01363 dbus_message_unref (message); 01364 return NULL; 01365 } 01366 01367 if (error_message != NULL) 01368 { 01369 dbus_message_iter_init_append (message, &iter); 01370 if (!dbus_message_iter_append_basic (&iter, 01371 DBUS_TYPE_STRING, 01372 &error_message)) 01373 { 01374 dbus_message_unref (message); 01375 return NULL; 01376 } 01377 } 01378 01379 return message; 01380 } 01381 01398 DBusMessage* 01399 dbus_message_new_error_printf (DBusMessage *reply_to, 01400 const char *error_name, 01401 const char *error_format, 01402 ...) 01403 { 01404 va_list args; 01405 DBusString str; 01406 DBusMessage *message; 01407 01408 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01409 _dbus_return_val_if_fail (error_name != NULL, NULL); 01410 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01411 01412 if (!_dbus_string_init (&str)) 01413 return NULL; 01414 01415 va_start (args, error_format); 01416 01417 if (_dbus_string_append_printf_valist (&str, error_format, args)) 01418 message = dbus_message_new_error (reply_to, error_name, 01419 _dbus_string_get_const_data (&str)); 01420 else 01421 message = NULL; 01422 01423 _dbus_string_free (&str); 01424 01425 va_end (args); 01426 01427 return message; 01428 } 01429 01430 01443 DBusMessage * 01444 dbus_message_copy (const DBusMessage *message) 01445 { 01446 DBusMessage *retval; 01447 01448 _dbus_return_val_if_fail (message != NULL, NULL); 01449 01450 retval = dbus_new0 (DBusMessage, 1); 01451 if (retval == NULL) 01452 return NULL; 01453 01454 _dbus_atomic_inc (&retval->refcount); 01455 retval->byte_order = message->byte_order; 01456 retval->locked = FALSE; 01457 #ifndef DBUS_DISABLE_CHECKS 01458 retval->generation = message->generation; 01459 #endif 01460 01461 if (!_dbus_header_copy (&message->header, &retval->header)) 01462 { 01463 dbus_free (retval); 01464 return NULL; 01465 } 01466 01467 if (!_dbus_string_init_preallocated (&retval->body, 01468 _dbus_string_get_length (&message->body))) 01469 { 01470 _dbus_header_free (&retval->header); 01471 dbus_free (retval); 01472 return NULL; 01473 } 01474 01475 if (!_dbus_string_copy (&message->body, 0, 01476 &retval->body, 0)) 01477 goto failed_copy; 01478 01479 #ifdef HAVE_UNIX_FD_PASSING 01480 retval->unix_fds = dbus_new(int, message->n_unix_fds); 01481 if (retval->unix_fds == NULL && message->n_unix_fds > 0) 01482 goto failed_copy; 01483 01484 retval->n_unix_fds_allocated = message->n_unix_fds; 01485 01486 for (retval->n_unix_fds = 0; 01487 retval->n_unix_fds < message->n_unix_fds; 01488 retval->n_unix_fds++) 01489 { 01490 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL); 01491 01492 if (retval->unix_fds[retval->n_unix_fds] < 0) 01493 goto failed_copy; 01494 } 01495 01496 #endif 01497 01498 return retval; 01499 01500 failed_copy: 01501 _dbus_header_free (&retval->header); 01502 _dbus_string_free (&retval->body); 01503 01504 #ifdef HAVE_UNIX_FD_PASSING 01505 close_unix_fds(retval->unix_fds, &retval->n_unix_fds); 01506 dbus_free(retval->unix_fds); 01507 #endif 01508 01509 dbus_free (retval); 01510 01511 return NULL; 01512 } 01513 01514 01522 DBusMessage * 01523 dbus_message_ref (DBusMessage *message) 01524 { 01525 #ifndef DBUS_DISABLE_ASSERT 01526 dbus_int32_t old_refcount; 01527 #endif 01528 01529 _dbus_return_val_if_fail (message != NULL, NULL); 01530 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); 01531 _dbus_return_val_if_fail (!message->in_cache, NULL); 01532 01533 #ifdef DBUS_DISABLE_ASSERT 01534 _dbus_atomic_inc (&message->refcount); 01535 #else 01536 old_refcount = _dbus_atomic_inc (&message->refcount); 01537 _dbus_assert (old_refcount >= 1); 01538 #endif 01539 01540 return message; 01541 } 01542 01550 void 01551 dbus_message_unref (DBusMessage *message) 01552 { 01553 dbus_int32_t old_refcount; 01554 01555 _dbus_return_if_fail (message != NULL); 01556 _dbus_return_if_fail (message->generation == _dbus_current_generation); 01557 _dbus_return_if_fail (!message->in_cache); 01558 01559 old_refcount = _dbus_atomic_dec (&message->refcount); 01560 01561 _dbus_assert (old_refcount >= 1); 01562 01563 if (old_refcount == 1) 01564 { 01565 /* Calls application callbacks! */ 01566 dbus_message_cache_or_finalize (message); 01567 } 01568 } 01569 01580 int 01581 dbus_message_get_type (DBusMessage *message) 01582 { 01583 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID); 01584 01585 return _dbus_header_get_message_type (&message->header); 01586 } 01587 01650 dbus_bool_t 01651 dbus_message_append_args (DBusMessage *message, 01652 int first_arg_type, 01653 ...) 01654 { 01655 dbus_bool_t retval; 01656 va_list var_args; 01657 01658 _dbus_return_val_if_fail (message != NULL, FALSE); 01659 01660 va_start (var_args, first_arg_type); 01661 retval = dbus_message_append_args_valist (message, 01662 first_arg_type, 01663 var_args); 01664 va_end (var_args); 01665 01666 return retval; 01667 } 01668 01682 dbus_bool_t 01683 dbus_message_append_args_valist (DBusMessage *message, 01684 int first_arg_type, 01685 va_list var_args) 01686 { 01687 int type; 01688 DBusMessageIter iter; 01689 01690 _dbus_return_val_if_fail (message != NULL, FALSE); 01691 01692 type = first_arg_type; 01693 01694 dbus_message_iter_init_append (message, &iter); 01695 01696 while (type != DBUS_TYPE_INVALID) 01697 { 01698 if (dbus_type_is_basic (type)) 01699 { 01700 const DBusBasicValue *value; 01701 value = va_arg (var_args, const DBusBasicValue*); 01702 01703 if (!dbus_message_iter_append_basic (&iter, 01704 type, 01705 value)) 01706 goto failed; 01707 } 01708 else if (type == DBUS_TYPE_ARRAY) 01709 { 01710 int element_type; 01711 DBusMessageIter array; 01712 char buf[2]; 01713 01714 element_type = va_arg (var_args, int); 01715 01716 buf[0] = element_type; 01717 buf[1] = '\0'; 01718 if (!dbus_message_iter_open_container (&iter, 01719 DBUS_TYPE_ARRAY, 01720 buf, 01721 &array)) 01722 goto failed; 01723 01724 if (dbus_type_is_fixed (element_type) && 01725 element_type != DBUS_TYPE_UNIX_FD) 01726 { 01727 const DBusBasicValue **value; 01728 int n_elements; 01729 01730 value = va_arg (var_args, const DBusBasicValue**); 01731 n_elements = va_arg (var_args, int); 01732 01733 if (!dbus_message_iter_append_fixed_array (&array, 01734 element_type, 01735 value, 01736 n_elements)) { 01737 dbus_message_iter_abandon_container (&iter, &array); 01738 goto failed; 01739 } 01740 } 01741 else if (element_type == DBUS_TYPE_STRING || 01742 element_type == DBUS_TYPE_SIGNATURE || 01743 element_type == DBUS_TYPE_OBJECT_PATH) 01744 { 01745 const char ***value_p; 01746 const char **value; 01747 int n_elements; 01748 int i; 01749 01750 value_p = va_arg (var_args, const char***); 01751 n_elements = va_arg (var_args, int); 01752 01753 value = *value_p; 01754 01755 i = 0; 01756 while (i < n_elements) 01757 { 01758 if (!dbus_message_iter_append_basic (&array, 01759 element_type, 01760 &value[i])) { 01761 dbus_message_iter_abandon_container (&iter, &array); 01762 goto failed; 01763 } 01764 ++i; 01765 } 01766 } 01767 else 01768 { 01769 _dbus_warn ("arrays of %s can't be appended with %s for now\n", 01770 _dbus_type_to_string (element_type), 01771 _DBUS_FUNCTION_NAME); 01772 goto failed; 01773 } 01774 01775 if (!dbus_message_iter_close_container (&iter, &array)) 01776 goto failed; 01777 } 01778 #ifndef DBUS_DISABLE_CHECKS 01779 else 01780 { 01781 _dbus_warn ("type %s isn't supported yet in %s\n", 01782 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME); 01783 goto failed; 01784 } 01785 #endif 01786 01787 type = va_arg (var_args, int); 01788 } 01789 01790 return TRUE; 01791 01792 failed: 01793 return FALSE; 01794 } 01795 01840 dbus_bool_t 01841 dbus_message_get_args (DBusMessage *message, 01842 DBusError *error, 01843 int first_arg_type, 01844 ...) 01845 { 01846 dbus_bool_t retval; 01847 va_list var_args; 01848 01849 _dbus_return_val_if_fail (message != NULL, FALSE); 01850 _dbus_return_val_if_error_is_set (error, FALSE); 01851 01852 va_start (var_args, first_arg_type); 01853 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args); 01854 va_end (var_args); 01855 01856 return retval; 01857 } 01858 01869 dbus_bool_t 01870 dbus_message_get_args_valist (DBusMessage *message, 01871 DBusError *error, 01872 int first_arg_type, 01873 va_list var_args) 01874 { 01875 DBusMessageIter iter; 01876 01877 _dbus_return_val_if_fail (message != NULL, FALSE); 01878 _dbus_return_val_if_error_is_set (error, FALSE); 01879 01880 dbus_message_iter_init (message, &iter); 01881 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); 01882 } 01883 01884 static void 01885 _dbus_message_iter_init_common (DBusMessage *message, 01886 DBusMessageRealIter *real, 01887 int iter_type) 01888 { 01889 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); 01890 01891 /* Since the iterator will read or write who-knows-what from the 01892 * message, we need to get in the right byte order 01893 */ 01894 ensure_byte_order (message); 01895 01896 real->message = message; 01897 real->changed_stamp = message->changed_stamp; 01898 real->iter_type = iter_type; 01899 real->sig_refcount = 0; 01900 } 01901 01924 dbus_bool_t 01925 dbus_message_iter_init (DBusMessage *message, 01926 DBusMessageIter *iter) 01927 { 01928 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01929 const DBusString *type_str; 01930 int type_pos; 01931 01932 _dbus_return_val_if_fail (message != NULL, FALSE); 01933 _dbus_return_val_if_fail (iter != NULL, FALSE); 01934 01935 get_const_signature (&message->header, &type_str, &type_pos); 01936 01937 _dbus_message_iter_init_common (message, real, 01938 DBUS_MESSAGE_ITER_TYPE_READER); 01939 01940 _dbus_type_reader_init (&real->u.reader, 01941 message->byte_order, 01942 type_str, type_pos, 01943 &message->body, 01944 0); 01945 01946 return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID; 01947 } 01948 01955 dbus_bool_t 01956 dbus_message_iter_has_next (DBusMessageIter *iter) 01957 { 01958 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01959 01960 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01961 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01962 01963 return _dbus_type_reader_has_next (&real->u.reader); 01964 } 01965 01974 dbus_bool_t 01975 dbus_message_iter_next (DBusMessageIter *iter) 01976 { 01977 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01978 01979 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01980 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01981 01982 return _dbus_type_reader_next (&real->u.reader); 01983 } 01984 01999 int 02000 dbus_message_iter_get_arg_type (DBusMessageIter *iter) 02001 { 02002 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02003 02004 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02005 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02006 02007 return _dbus_type_reader_get_current_type (&real->u.reader); 02008 } 02009 02018 int 02019 dbus_message_iter_get_element_type (DBusMessageIter *iter) 02020 { 02021 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02022 02023 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02024 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); 02025 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 02026 02027 return _dbus_type_reader_get_element_type (&real->u.reader); 02028 } 02029 02055 void 02056 dbus_message_iter_recurse (DBusMessageIter *iter, 02057 DBusMessageIter *sub) 02058 { 02059 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02060 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02061 02062 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02063 _dbus_return_if_fail (sub != NULL); 02064 02065 *real_sub = *real; 02066 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader); 02067 } 02068 02080 char * 02081 dbus_message_iter_get_signature (DBusMessageIter *iter) 02082 { 02083 const DBusString *sig; 02084 DBusString retstr; 02085 char *ret; 02086 int start, len; 02087 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02088 02089 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL); 02090 02091 if (!_dbus_string_init (&retstr)) 02092 return NULL; 02093 02094 _dbus_type_reader_get_signature (&real->u.reader, &sig, 02095 &start, &len); 02096 if (!_dbus_string_append_len (&retstr, 02097 _dbus_string_get_const_data (sig) + start, 02098 len)) 02099 return NULL; 02100 if (!_dbus_string_steal_data (&retstr, &ret)) 02101 return NULL; 02102 _dbus_string_free (&retstr); 02103 return ret; 02104 } 02105 02153 void 02154 dbus_message_iter_get_basic (DBusMessageIter *iter, 02155 void *value) 02156 { 02157 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02158 02159 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02160 _dbus_return_if_fail (value != NULL); 02161 02162 if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD) 02163 { 02164 #ifdef HAVE_UNIX_FD_PASSING 02165 DBusBasicValue idx; 02166 02167 _dbus_type_reader_read_basic(&real->u.reader, &idx); 02168 02169 if (idx.u32 >= real->message->n_unix_fds) { 02170 /* Hmm, we cannot really signal an error here, so let's make 02171 sure to return an invalid fd. */ 02172 *((int*) value) = -1; 02173 return; 02174 } 02175 02176 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL); 02177 #else 02178 *((int*) value) = -1; 02179 #endif 02180 } 02181 else 02182 { 02183 _dbus_type_reader_read_basic (&real->u.reader, 02184 value); 02185 } 02186 } 02187 02206 int 02207 dbus_message_iter_get_array_len (DBusMessageIter *iter) 02208 { 02209 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02210 02211 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02212 02213 return _dbus_type_reader_get_array_length (&real->u.reader); 02214 } 02215 02251 void 02252 dbus_message_iter_get_fixed_array (DBusMessageIter *iter, 02253 void *value, 02254 int *n_elements) 02255 { 02256 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02257 int subtype = _dbus_type_reader_get_current_type(&real->u.reader); 02258 02259 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02260 _dbus_return_if_fail (value != NULL); 02261 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) || 02262 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD)); 02263 02264 _dbus_type_reader_read_fixed_multi (&real->u.reader, 02265 value, n_elements); 02266 } 02267 02279 void 02280 dbus_message_iter_init_append (DBusMessage *message, 02281 DBusMessageIter *iter) 02282 { 02283 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02284 02285 _dbus_return_if_fail (message != NULL); 02286 _dbus_return_if_fail (iter != NULL); 02287 02288 _dbus_message_iter_init_common (message, real, 02289 DBUS_MESSAGE_ITER_TYPE_WRITER); 02290 02291 /* We create the signature string and point iterators at it "on demand" 02292 * when a value is actually appended. That means that init() never fails 02293 * due to OOM. 02294 */ 02295 _dbus_type_writer_init_types_delayed (&real->u.writer, 02296 message->byte_order, 02297 &message->body, 02298 _dbus_string_get_length (&message->body)); 02299 } 02300 02309 static dbus_bool_t 02310 _dbus_message_iter_open_signature (DBusMessageRealIter *real) 02311 { 02312 DBusString *str; 02313 const DBusString *current_sig; 02314 int current_sig_pos; 02315 02316 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02317 02318 if (real->u.writer.type_str != NULL) 02319 { 02320 _dbus_assert (real->sig_refcount > 0); 02321 real->sig_refcount += 1; 02322 return TRUE; 02323 } 02324 02325 str = dbus_new (DBusString, 1); 02326 if (str == NULL) 02327 return FALSE; 02328 02329 if (!_dbus_header_get_field_raw (&real->message->header, 02330 DBUS_HEADER_FIELD_SIGNATURE, 02331 ¤t_sig, ¤t_sig_pos)) 02332 current_sig = NULL; 02333 02334 if (current_sig) 02335 { 02336 int current_len; 02337 02338 current_len = _dbus_string_get_byte (current_sig, current_sig_pos); 02339 current_sig_pos += 1; /* move on to sig data */ 02340 02341 if (!_dbus_string_init_preallocated (str, current_len + 4)) 02342 { 02343 dbus_free (str); 02344 return FALSE; 02345 } 02346 02347 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len, 02348 str, 0)) 02349 { 02350 _dbus_string_free (str); 02351 dbus_free (str); 02352 return FALSE; 02353 } 02354 } 02355 else 02356 { 02357 if (!_dbus_string_init_preallocated (str, 4)) 02358 { 02359 dbus_free (str); 02360 return FALSE; 02361 } 02362 } 02363 02364 real->sig_refcount = 1; 02365 02366 _dbus_type_writer_add_types (&real->u.writer, 02367 str, _dbus_string_get_length (str)); 02368 return TRUE; 02369 } 02370 02380 static dbus_bool_t 02381 _dbus_message_iter_close_signature (DBusMessageRealIter *real) 02382 { 02383 DBusString *str; 02384 const char *v_STRING; 02385 dbus_bool_t retval; 02386 02387 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02388 _dbus_assert (real->u.writer.type_str != NULL); 02389 _dbus_assert (real->sig_refcount > 0); 02390 02391 real->sig_refcount -= 1; 02392 02393 if (real->sig_refcount > 0) 02394 return TRUE; 02395 _dbus_assert (real->sig_refcount == 0); 02396 02397 retval = TRUE; 02398 02399 str = real->u.writer.type_str; 02400 02401 v_STRING = _dbus_string_get_const_data (str); 02402 if (!_dbus_header_set_field_basic (&real->message->header, 02403 DBUS_HEADER_FIELD_SIGNATURE, 02404 DBUS_TYPE_SIGNATURE, 02405 &v_STRING)) 02406 retval = FALSE; 02407 02408 _dbus_type_writer_remove_types (&real->u.writer); 02409 _dbus_string_free (str); 02410 dbus_free (str); 02411 02412 return retval; 02413 } 02414 02422 static void 02423 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real) 02424 { 02425 DBusString *str; 02426 02427 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02428 _dbus_assert (real->u.writer.type_str != NULL); 02429 _dbus_assert (real->sig_refcount > 0); 02430 02431 real->sig_refcount -= 1; 02432 02433 if (real->sig_refcount > 0) 02434 return; 02435 _dbus_assert (real->sig_refcount == 0); 02436 02437 str = real->u.writer.type_str; 02438 02439 _dbus_type_writer_remove_types (&real->u.writer); 02440 _dbus_string_free (str); 02441 dbus_free (str); 02442 } 02443 02444 #ifndef DBUS_DISABLE_CHECKS 02445 static dbus_bool_t 02446 _dbus_message_iter_append_check (DBusMessageRealIter *iter) 02447 { 02448 if (!_dbus_message_iter_check (iter)) 02449 return FALSE; 02450 02451 if (iter->message->locked) 02452 { 02453 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n"); 02454 return FALSE; 02455 } 02456 02457 return TRUE; 02458 } 02459 #endif /* DBUS_DISABLE_CHECKS */ 02460 02461 #ifdef HAVE_UNIX_FD_PASSING 02462 static int * 02463 expand_fd_array(DBusMessage *m, 02464 unsigned n) 02465 { 02466 _dbus_assert(m); 02467 02468 /* This makes space for adding n new fds to the array and returns a 02469 pointer to the place were the first fd should be put. */ 02470 02471 if (m->n_unix_fds + n > m->n_unix_fds_allocated) 02472 { 02473 unsigned k; 02474 int *p; 02475 02476 /* Make twice as much space as necessary */ 02477 k = (m->n_unix_fds + n) * 2; 02478 02479 /* Allocate at least four */ 02480 if (k < 4) 02481 k = 4; 02482 02483 p = dbus_realloc(m->unix_fds, k * sizeof(int)); 02484 if (p == NULL) 02485 return NULL; 02486 02487 m->unix_fds = p; 02488 m->n_unix_fds_allocated = k; 02489 } 02490 02491 return m->unix_fds + m->n_unix_fds; 02492 } 02493 #endif 02494 02514 dbus_bool_t 02515 dbus_message_iter_append_basic (DBusMessageIter *iter, 02516 int type, 02517 const void *value) 02518 { 02519 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02520 dbus_bool_t ret; 02521 02522 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02523 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02524 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE); 02525 _dbus_return_val_if_fail (value != NULL, FALSE); 02526 02527 #ifndef DBUS_DISABLE_CHECKS 02528 switch (type) 02529 { 02530 const char * const *string_p; 02531 const dbus_bool_t *bool_p; 02532 02533 case DBUS_TYPE_STRING: 02534 string_p = value; 02535 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE); 02536 break; 02537 02538 case DBUS_TYPE_OBJECT_PATH: 02539 string_p = value; 02540 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE); 02541 break; 02542 02543 case DBUS_TYPE_SIGNATURE: 02544 string_p = value; 02545 _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE); 02546 break; 02547 02548 case DBUS_TYPE_BOOLEAN: 02549 bool_p = value; 02550 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE); 02551 break; 02552 02553 default: 02554 { 02555 /* nothing to check, all possible values are allowed */ 02556 } 02557 } 02558 #endif 02559 02560 if (!_dbus_message_iter_open_signature (real)) 02561 return FALSE; 02562 02563 if (type == DBUS_TYPE_UNIX_FD) 02564 { 02565 #ifdef HAVE_UNIX_FD_PASSING 02566 int *fds; 02567 dbus_uint32_t u; 02568 02569 /* First step, include the fd in the fd list of this message */ 02570 if (!(fds = expand_fd_array(real->message, 1))) 02571 return FALSE; 02572 02573 *fds = _dbus_dup(*(int*) value, NULL); 02574 if (*fds < 0) 02575 return FALSE; 02576 02577 u = real->message->n_unix_fds; 02578 02579 /* Second step, write the index to the fd */ 02580 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) { 02581 _dbus_close(*fds, NULL); 02582 return FALSE; 02583 } 02584 02585 real->message->n_unix_fds += 1; 02586 u += 1; 02587 02588 /* Final step, update the header accordingly */ 02589 ret = _dbus_header_set_field_basic (&real->message->header, 02590 DBUS_HEADER_FIELD_UNIX_FDS, 02591 DBUS_TYPE_UINT32, 02592 &u); 02593 02594 /* If any of these operations fail the message is 02595 hosed. However, no memory or fds should be leaked since what 02596 has been added to message has been added to the message, and 02597 can hence be accounted for when the message is being 02598 freed. */ 02599 #else 02600 ret = FALSE; 02601 #endif 02602 } 02603 else 02604 { 02605 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02606 } 02607 02608 if (!_dbus_message_iter_close_signature (real)) 02609 ret = FALSE; 02610 02611 return ret; 02612 } 02613 02649 dbus_bool_t 02650 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02651 int element_type, 02652 const void *value, 02653 int n_elements) 02654 { 02655 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02656 dbus_bool_t ret; 02657 02658 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02659 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02660 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); 02661 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02662 _dbus_return_val_if_fail (value != NULL, FALSE); 02663 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02664 _dbus_return_val_if_fail (n_elements <= 02665 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02666 FALSE); 02667 02668 #ifndef DBUS_DISABLE_CHECKS 02669 if (element_type == DBUS_TYPE_BOOLEAN) 02670 { 02671 const dbus_bool_t * const *bools = value; 02672 int i; 02673 02674 for (i = 0; i < n_elements; i++) 02675 { 02676 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE); 02677 } 02678 } 02679 #endif 02680 02681 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02682 02683 return ret; 02684 } 02685 02707 dbus_bool_t 02708 dbus_message_iter_open_container (DBusMessageIter *iter, 02709 int type, 02710 const char *contained_signature, 02711 DBusMessageIter *sub) 02712 { 02713 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02714 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02715 DBusString contained_str; 02716 02717 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02718 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02719 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02720 _dbus_return_val_if_fail (sub != NULL, FALSE); 02721 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02722 contained_signature == NULL) || 02723 (type == DBUS_TYPE_DICT_ENTRY && 02724 contained_signature == NULL) || 02725 (type == DBUS_TYPE_VARIANT && 02726 contained_signature != NULL) || 02727 (type == DBUS_TYPE_ARRAY && 02728 contained_signature != NULL), FALSE); 02729 02730 /* this would fail if the contained_signature is a dict entry, since 02731 * dict entries are invalid signatures standalone (they must be in 02732 * an array) 02733 */ 02734 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02735 (contained_signature == NULL || 02736 _dbus_check_is_valid_signature (contained_signature)), 02737 FALSE); 02738 02739 if (!_dbus_message_iter_open_signature (real)) 02740 return FALSE; 02741 02742 *real_sub = *real; 02743 02744 if (contained_signature != NULL) 02745 { 02746 _dbus_string_init_const (&contained_str, contained_signature); 02747 02748 return _dbus_type_writer_recurse (&real->u.writer, 02749 type, 02750 &contained_str, 0, 02751 &real_sub->u.writer); 02752 } 02753 else 02754 { 02755 return _dbus_type_writer_recurse (&real->u.writer, 02756 type, 02757 NULL, 0, 02758 &real_sub->u.writer); 02759 } 02760 } 02761 02762 02776 dbus_bool_t 02777 dbus_message_iter_close_container (DBusMessageIter *iter, 02778 DBusMessageIter *sub) 02779 { 02780 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02781 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02782 dbus_bool_t ret; 02783 02784 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02785 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02786 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 02787 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02788 02789 ret = _dbus_type_writer_unrecurse (&real->u.writer, 02790 &real_sub->u.writer); 02791 02792 if (!_dbus_message_iter_close_signature (real)) 02793 ret = FALSE; 02794 02795 return ret; 02796 } 02797 02809 void 02810 dbus_message_iter_abandon_container (DBusMessageIter *iter, 02811 DBusMessageIter *sub) 02812 { 02813 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02814 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02815 02816 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 02817 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02818 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 02819 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02820 02821 _dbus_message_iter_abandon_signature (real); 02822 } 02823 02840 void 02841 dbus_message_set_no_reply (DBusMessage *message, 02842 dbus_bool_t no_reply) 02843 { 02844 _dbus_return_if_fail (message != NULL); 02845 _dbus_return_if_fail (!message->locked); 02846 02847 _dbus_header_toggle_flag (&message->header, 02848 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 02849 no_reply); 02850 } 02851 02859 dbus_bool_t 02860 dbus_message_get_no_reply (DBusMessage *message) 02861 { 02862 _dbus_return_val_if_fail (message != NULL, FALSE); 02863 02864 return _dbus_header_get_flag (&message->header, 02865 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 02866 } 02867 02882 void 02883 dbus_message_set_auto_start (DBusMessage *message, 02884 dbus_bool_t auto_start) 02885 { 02886 _dbus_return_if_fail (message != NULL); 02887 _dbus_return_if_fail (!message->locked); 02888 02889 _dbus_header_toggle_flag (&message->header, 02890 DBUS_HEADER_FLAG_NO_AUTO_START, 02891 !auto_start); 02892 } 02893 02901 dbus_bool_t 02902 dbus_message_get_auto_start (DBusMessage *message) 02903 { 02904 _dbus_return_val_if_fail (message != NULL, FALSE); 02905 02906 return !_dbus_header_get_flag (&message->header, 02907 DBUS_HEADER_FLAG_NO_AUTO_START); 02908 } 02909 02910 02923 dbus_bool_t 02924 dbus_message_set_path (DBusMessage *message, 02925 const char *object_path) 02926 { 02927 _dbus_return_val_if_fail (message != NULL, FALSE); 02928 _dbus_return_val_if_fail (!message->locked, FALSE); 02929 _dbus_return_val_if_fail (object_path == NULL || 02930 _dbus_check_is_valid_path (object_path), 02931 FALSE); 02932 02933 return set_or_delete_string_field (message, 02934 DBUS_HEADER_FIELD_PATH, 02935 DBUS_TYPE_OBJECT_PATH, 02936 object_path); 02937 } 02938 02952 const char* 02953 dbus_message_get_path (DBusMessage *message) 02954 { 02955 const char *v; 02956 02957 _dbus_return_val_if_fail (message != NULL, NULL); 02958 02959 v = NULL; /* in case field doesn't exist */ 02960 _dbus_header_get_field_basic (&message->header, 02961 DBUS_HEADER_FIELD_PATH, 02962 DBUS_TYPE_OBJECT_PATH, 02963 (void *) &v); 02964 return v; 02965 } 02966 02976 dbus_bool_t 02977 dbus_message_has_path (DBusMessage *message, 02978 const char *path) 02979 { 02980 const char *msg_path; 02981 msg_path = dbus_message_get_path (message); 02982 02983 if (msg_path == NULL) 02984 { 02985 if (path == NULL) 02986 return TRUE; 02987 else 02988 return FALSE; 02989 } 02990 02991 if (path == NULL) 02992 return FALSE; 02993 02994 if (strcmp (msg_path, path) == 0) 02995 return TRUE; 02996 02997 return FALSE; 02998 } 02999 03020 dbus_bool_t 03021 dbus_message_get_path_decomposed (DBusMessage *message, 03022 char ***path) 03023 { 03024 const char *v; 03025 03026 _dbus_return_val_if_fail (message != NULL, FALSE); 03027 _dbus_return_val_if_fail (path != NULL, FALSE); 03028 03029 *path = NULL; 03030 03031 v = dbus_message_get_path (message); 03032 if (v != NULL) 03033 { 03034 if (!_dbus_decompose_path (v, strlen (v), 03035 path, NULL)) 03036 return FALSE; 03037 } 03038 return TRUE; 03039 } 03040 03054 dbus_bool_t 03055 dbus_message_set_interface (DBusMessage *message, 03056 const char *interface) 03057 { 03058 _dbus_return_val_if_fail (message != NULL, FALSE); 03059 _dbus_return_val_if_fail (!message->locked, FALSE); 03060 _dbus_return_val_if_fail (interface == NULL || 03061 _dbus_check_is_valid_interface (interface), 03062 FALSE); 03063 03064 return set_or_delete_string_field (message, 03065 DBUS_HEADER_FIELD_INTERFACE, 03066 DBUS_TYPE_STRING, 03067 interface); 03068 } 03069 03083 const char* 03084 dbus_message_get_interface (DBusMessage *message) 03085 { 03086 const char *v; 03087 03088 _dbus_return_val_if_fail (message != NULL, NULL); 03089 03090 v = NULL; /* in case field doesn't exist */ 03091 _dbus_header_get_field_basic (&message->header, 03092 DBUS_HEADER_FIELD_INTERFACE, 03093 DBUS_TYPE_STRING, 03094 (void *) &v); 03095 return v; 03096 } 03097 03105 dbus_bool_t 03106 dbus_message_has_interface (DBusMessage *message, 03107 const char *interface) 03108 { 03109 const char *msg_interface; 03110 msg_interface = dbus_message_get_interface (message); 03111 03112 if (msg_interface == NULL) 03113 { 03114 if (interface == NULL) 03115 return TRUE; 03116 else 03117 return FALSE; 03118 } 03119 03120 if (interface == NULL) 03121 return FALSE; 03122 03123 if (strcmp (msg_interface, interface) == 0) 03124 return TRUE; 03125 03126 return FALSE; 03127 03128 } 03129 03142 dbus_bool_t 03143 dbus_message_set_member (DBusMessage *message, 03144 const char *member) 03145 { 03146 _dbus_return_val_if_fail (message != NULL, FALSE); 03147 _dbus_return_val_if_fail (!message->locked, FALSE); 03148 _dbus_return_val_if_fail (member == NULL || 03149 _dbus_check_is_valid_member (member), 03150 FALSE); 03151 03152 return set_or_delete_string_field (message, 03153 DBUS_HEADER_FIELD_MEMBER, 03154 DBUS_TYPE_STRING, 03155 member); 03156 } 03157 03169 const char* 03170 dbus_message_get_member (DBusMessage *message) 03171 { 03172 const char *v; 03173 03174 _dbus_return_val_if_fail (message != NULL, NULL); 03175 03176 v = NULL; /* in case field doesn't exist */ 03177 _dbus_header_get_field_basic (&message->header, 03178 DBUS_HEADER_FIELD_MEMBER, 03179 DBUS_TYPE_STRING, 03180 (void *) &v); 03181 return v; 03182 } 03183 03191 dbus_bool_t 03192 dbus_message_has_member (DBusMessage *message, 03193 const char *member) 03194 { 03195 const char *msg_member; 03196 msg_member = dbus_message_get_member (message); 03197 03198 if (msg_member == NULL) 03199 { 03200 if (member == NULL) 03201 return TRUE; 03202 else 03203 return FALSE; 03204 } 03205 03206 if (member == NULL) 03207 return FALSE; 03208 03209 if (strcmp (msg_member, member) == 0) 03210 return TRUE; 03211 03212 return FALSE; 03213 03214 } 03215 03227 dbus_bool_t 03228 dbus_message_set_error_name (DBusMessage *message, 03229 const char *error_name) 03230 { 03231 _dbus_return_val_if_fail (message != NULL, FALSE); 03232 _dbus_return_val_if_fail (!message->locked, FALSE); 03233 _dbus_return_val_if_fail (error_name == NULL || 03234 _dbus_check_is_valid_error_name (error_name), 03235 FALSE); 03236 03237 return set_or_delete_string_field (message, 03238 DBUS_HEADER_FIELD_ERROR_NAME, 03239 DBUS_TYPE_STRING, 03240 error_name); 03241 } 03242 03253 const char* 03254 dbus_message_get_error_name (DBusMessage *message) 03255 { 03256 const char *v; 03257 03258 _dbus_return_val_if_fail (message != NULL, NULL); 03259 03260 v = NULL; /* in case field doesn't exist */ 03261 _dbus_header_get_field_basic (&message->header, 03262 DBUS_HEADER_FIELD_ERROR_NAME, 03263 DBUS_TYPE_STRING, 03264 (void *) &v); 03265 return v; 03266 } 03267 03281 dbus_bool_t 03282 dbus_message_set_destination (DBusMessage *message, 03283 const char *destination) 03284 { 03285 _dbus_return_val_if_fail (message != NULL, FALSE); 03286 _dbus_return_val_if_fail (!message->locked, FALSE); 03287 _dbus_return_val_if_fail (destination == NULL || 03288 _dbus_check_is_valid_bus_name (destination), 03289 FALSE); 03290 03291 return set_or_delete_string_field (message, 03292 DBUS_HEADER_FIELD_DESTINATION, 03293 DBUS_TYPE_STRING, 03294 destination); 03295 } 03296 03306 const char* 03307 dbus_message_get_destination (DBusMessage *message) 03308 { 03309 const char *v; 03310 03311 _dbus_return_val_if_fail (message != NULL, NULL); 03312 03313 v = NULL; /* in case field doesn't exist */ 03314 _dbus_header_get_field_basic (&message->header, 03315 DBUS_HEADER_FIELD_DESTINATION, 03316 DBUS_TYPE_STRING, 03317 (void *) &v); 03318 return v; 03319 } 03320 03335 dbus_bool_t 03336 dbus_message_set_sender (DBusMessage *message, 03337 const char *sender) 03338 { 03339 _dbus_return_val_if_fail (message != NULL, FALSE); 03340 _dbus_return_val_if_fail (!message->locked, FALSE); 03341 _dbus_return_val_if_fail (sender == NULL || 03342 _dbus_check_is_valid_bus_name (sender), 03343 FALSE); 03344 03345 return set_or_delete_string_field (message, 03346 DBUS_HEADER_FIELD_SENDER, 03347 DBUS_TYPE_STRING, 03348 sender); 03349 } 03350 03366 const char* 03367 dbus_message_get_sender (DBusMessage *message) 03368 { 03369 const char *v; 03370 03371 _dbus_return_val_if_fail (message != NULL, NULL); 03372 03373 v = NULL; /* in case field doesn't exist */ 03374 _dbus_header_get_field_basic (&message->header, 03375 DBUS_HEADER_FIELD_SENDER, 03376 DBUS_TYPE_STRING, 03377 (void *) &v); 03378 return v; 03379 } 03380 03399 const char* 03400 dbus_message_get_signature (DBusMessage *message) 03401 { 03402 const DBusString *type_str; 03403 int type_pos; 03404 03405 _dbus_return_val_if_fail (message != NULL, NULL); 03406 03407 get_const_signature (&message->header, &type_str, &type_pos); 03408 03409 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03410 } 03411 03412 static dbus_bool_t 03413 _dbus_message_has_type_interface_member (DBusMessage *message, 03414 int type, 03415 const char *interface, 03416 const char *member) 03417 { 03418 const char *n; 03419 03420 _dbus_assert (message != NULL); 03421 _dbus_assert (interface != NULL); 03422 _dbus_assert (member != NULL); 03423 03424 if (dbus_message_get_type (message) != type) 03425 return FALSE; 03426 03427 /* Optimize by checking the short member name first 03428 * instead of the longer interface name 03429 */ 03430 03431 n = dbus_message_get_member (message); 03432 03433 if (n && strcmp (n, member) == 0) 03434 { 03435 n = dbus_message_get_interface (message); 03436 03437 if (n == NULL || strcmp (n, interface) == 0) 03438 return TRUE; 03439 } 03440 03441 return FALSE; 03442 } 03443 03458 dbus_bool_t 03459 dbus_message_is_method_call (DBusMessage *message, 03460 const char *interface, 03461 const char *method) 03462 { 03463 _dbus_return_val_if_fail (message != NULL, FALSE); 03464 _dbus_return_val_if_fail (interface != NULL, FALSE); 03465 _dbus_return_val_if_fail (method != NULL, FALSE); 03466 /* don't check that interface/method are valid since it would be 03467 * expensive, and not catch many common errors 03468 */ 03469 03470 return _dbus_message_has_type_interface_member (message, 03471 DBUS_MESSAGE_TYPE_METHOD_CALL, 03472 interface, method); 03473 } 03474 03486 dbus_bool_t 03487 dbus_message_is_signal (DBusMessage *message, 03488 const char *interface, 03489 const char *signal_name) 03490 { 03491 _dbus_return_val_if_fail (message != NULL, FALSE); 03492 _dbus_return_val_if_fail (interface != NULL, FALSE); 03493 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03494 /* don't check that interface/name are valid since it would be 03495 * expensive, and not catch many common errors 03496 */ 03497 03498 return _dbus_message_has_type_interface_member (message, 03499 DBUS_MESSAGE_TYPE_SIGNAL, 03500 interface, signal_name); 03501 } 03502 03513 dbus_bool_t 03514 dbus_message_is_error (DBusMessage *message, 03515 const char *error_name) 03516 { 03517 const char *n; 03518 03519 _dbus_return_val_if_fail (message != NULL, FALSE); 03520 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03521 /* don't check that error_name is valid since it would be expensive, 03522 * and not catch many common errors 03523 */ 03524 03525 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03526 return FALSE; 03527 03528 n = dbus_message_get_error_name (message); 03529 03530 if (n && strcmp (n, error_name) == 0) 03531 return TRUE; 03532 else 03533 return FALSE; 03534 } 03535 03546 dbus_bool_t 03547 dbus_message_has_destination (DBusMessage *message, 03548 const char *name) 03549 { 03550 const char *s; 03551 03552 _dbus_return_val_if_fail (message != NULL, FALSE); 03553 _dbus_return_val_if_fail (name != NULL, FALSE); 03554 /* don't check that name is valid since it would be expensive, and 03555 * not catch many common errors 03556 */ 03557 03558 s = dbus_message_get_destination (message); 03559 03560 if (s && strcmp (s, name) == 0) 03561 return TRUE; 03562 else 03563 return FALSE; 03564 } 03565 03581 dbus_bool_t 03582 dbus_message_has_sender (DBusMessage *message, 03583 const char *name) 03584 { 03585 const char *s; 03586 03587 _dbus_return_val_if_fail (message != NULL, FALSE); 03588 _dbus_return_val_if_fail (name != NULL, FALSE); 03589 /* don't check that name is valid since it would be expensive, and 03590 * not catch many common errors 03591 */ 03592 03593 s = dbus_message_get_sender (message); 03594 03595 if (s && strcmp (s, name) == 0) 03596 return TRUE; 03597 else 03598 return FALSE; 03599 } 03600 03610 dbus_bool_t 03611 dbus_message_has_signature (DBusMessage *message, 03612 const char *signature) 03613 { 03614 const char *s; 03615 03616 _dbus_return_val_if_fail (message != NULL, FALSE); 03617 _dbus_return_val_if_fail (signature != NULL, FALSE); 03618 /* don't check that signature is valid since it would be expensive, 03619 * and not catch many common errors 03620 */ 03621 03622 s = dbus_message_get_signature (message); 03623 03624 if (s && strcmp (s, signature) == 0) 03625 return TRUE; 03626 else 03627 return FALSE; 03628 } 03629 03652 dbus_bool_t 03653 dbus_set_error_from_message (DBusError *error, 03654 DBusMessage *message) 03655 { 03656 const char *str; 03657 03658 _dbus_return_val_if_fail (message != NULL, FALSE); 03659 _dbus_return_val_if_error_is_set (error, FALSE); 03660 03661 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03662 return FALSE; 03663 03664 str = NULL; 03665 dbus_message_get_args (message, NULL, 03666 DBUS_TYPE_STRING, &str, 03667 DBUS_TYPE_INVALID); 03668 03669 dbus_set_error (error, dbus_message_get_error_name (message), 03670 str ? "%s" : NULL, str); 03671 03672 return TRUE; 03673 } 03674 03681 dbus_bool_t 03682 dbus_message_contains_unix_fds(DBusMessage *message) 03683 { 03684 #ifdef HAVE_UNIX_FD_PASSING 03685 _dbus_assert(message); 03686 03687 return message->n_unix_fds > 0; 03688 #else 03689 return FALSE; 03690 #endif 03691 } 03692 03711 #define INITIAL_LOADER_DATA_LEN 32 03712 03719 DBusMessageLoader* 03720 _dbus_message_loader_new (void) 03721 { 03722 DBusMessageLoader *loader; 03723 03724 loader = dbus_new0 (DBusMessageLoader, 1); 03725 if (loader == NULL) 03726 return NULL; 03727 03728 loader->refcount = 1; 03729 03730 loader->corrupted = FALSE; 03731 loader->corruption_reason = DBUS_VALID; 03732 03733 /* this can be configured by the app, but defaults to the protocol max */ 03734 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03735 03736 /* We set a very relatively conservative default here since due to how 03737 SCM_RIGHTS works we need to preallocate an fd array of the maximum 03738 number of unix fds we want to receive in advance. A 03739 try-and-reallocate loop is not possible. */ 03740 loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS; 03741 03742 if (!_dbus_string_init (&loader->data)) 03743 { 03744 dbus_free (loader); 03745 return NULL; 03746 } 03747 03748 /* preallocate the buffer for speed, ignore failure */ 03749 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03750 _dbus_string_set_length (&loader->data, 0); 03751 03752 #ifdef HAVE_UNIX_FD_PASSING 03753 loader->unix_fds = NULL; 03754 loader->n_unix_fds = loader->n_unix_fds_allocated = 0; 03755 loader->unix_fds_outstanding = FALSE; 03756 #endif 03757 03758 return loader; 03759 } 03760 03767 DBusMessageLoader * 03768 _dbus_message_loader_ref (DBusMessageLoader *loader) 03769 { 03770 loader->refcount += 1; 03771 03772 return loader; 03773 } 03774 03781 void 03782 _dbus_message_loader_unref (DBusMessageLoader *loader) 03783 { 03784 loader->refcount -= 1; 03785 if (loader->refcount == 0) 03786 { 03787 #ifdef HAVE_UNIX_FD_PASSING 03788 close_unix_fds(loader->unix_fds, &loader->n_unix_fds); 03789 dbus_free(loader->unix_fds); 03790 #endif 03791 _dbus_list_foreach (&loader->messages, 03792 (DBusForeachFunction) dbus_message_unref, 03793 NULL); 03794 _dbus_list_clear (&loader->messages); 03795 _dbus_string_free (&loader->data); 03796 dbus_free (loader); 03797 } 03798 } 03799 03818 void 03819 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 03820 DBusString **buffer) 03821 { 03822 _dbus_assert (!loader->buffer_outstanding); 03823 03824 *buffer = &loader->data; 03825 03826 loader->buffer_outstanding = TRUE; 03827 } 03828 03839 void 03840 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 03841 DBusString *buffer, 03842 int bytes_read) 03843 { 03844 _dbus_assert (loader->buffer_outstanding); 03845 _dbus_assert (buffer == &loader->data); 03846 03847 loader->buffer_outstanding = FALSE; 03848 } 03849 03860 dbus_bool_t 03861 _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, 03862 int **fds, 03863 unsigned *max_n_fds) 03864 { 03865 #ifdef HAVE_UNIX_FD_PASSING 03866 _dbus_assert (!loader->unix_fds_outstanding); 03867 03868 /* Allocate space where we can put the fds we read. We allocate 03869 space for max_message_unix_fds since this is an 03870 upper limit how many fds can be received within a single 03871 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic 03872 we are allocating the maximum possible array size right from the 03873 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed 03874 there is no better way. */ 03875 03876 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds) 03877 { 03878 int *a = dbus_realloc(loader->unix_fds, 03879 loader->max_message_unix_fds * sizeof(loader->unix_fds[0])); 03880 03881 if (!a) 03882 return FALSE; 03883 03884 loader->unix_fds = a; 03885 loader->n_unix_fds_allocated = loader->max_message_unix_fds; 03886 } 03887 03888 *fds = loader->unix_fds + loader->n_unix_fds; 03889 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds; 03890 03891 loader->unix_fds_outstanding = TRUE; 03892 return TRUE; 03893 #else 03894 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03895 return FALSE; 03896 #endif 03897 } 03898 03909 void 03910 _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, 03911 int *fds, 03912 unsigned n_fds) 03913 { 03914 #ifdef HAVE_UNIX_FD_PASSING 03915 _dbus_assert(loader->unix_fds_outstanding); 03916 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds); 03917 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated); 03918 03919 loader->n_unix_fds += n_fds; 03920 loader->unix_fds_outstanding = FALSE; 03921 03922 if (n_fds && loader->unix_fds_change) 03923 loader->unix_fds_change (loader->unix_fds_change_data); 03924 #else 03925 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03926 #endif 03927 } 03928 03929 /* 03930 * FIXME when we move the header out of the buffer, that memmoves all 03931 * buffered messages. Kind of crappy. 03932 * 03933 * Also we copy the header and body, which is kind of crappy. To 03934 * avoid this, we have to allow header and body to be in a single 03935 * memory block, which is good for messages we read and bad for 03936 * messages we are creating. But we could move_len() the buffer into 03937 * this single memory block, and move_len() will just swap the buffers 03938 * if you're moving the entire buffer replacing the dest string. 03939 * 03940 * We could also have the message loader tell the transport how many 03941 * bytes to read; so it would first ask for some arbitrary number like 03942 * 256, then if the message was incomplete it would use the 03943 * header/body len to ask for exactly the size of the message (or 03944 * blocks the size of a typical kernel buffer for the socket). That 03945 * way we don't get trailing bytes in the buffer that have to be 03946 * memmoved. Though I suppose we also don't have a chance of reading a 03947 * bunch of small messages at once, so the optimization may be stupid. 03948 * 03949 * Another approach would be to keep a "start" index into 03950 * loader->data and only delete it occasionally, instead of after 03951 * each message is loaded. 03952 * 03953 * load_message() returns FALSE if not enough memory OR the loader was corrupted 03954 */ 03955 static dbus_bool_t 03956 load_message (DBusMessageLoader *loader, 03957 DBusMessage *message, 03958 int byte_order, 03959 int fields_array_len, 03960 int header_len, 03961 int body_len) 03962 { 03963 dbus_bool_t oom; 03964 DBusValidity validity; 03965 const DBusString *type_str; 03966 int type_pos; 03967 DBusValidationMode mode; 03968 dbus_uint32_t n_unix_fds = 0; 03969 03970 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 03971 03972 oom = FALSE; 03973 03974 #if 0 03975 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 03976 #endif 03977 03978 /* 1. VALIDATE AND COPY OVER HEADER */ 03979 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 03980 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 03981 03982 if (!_dbus_header_load (&message->header, 03983 mode, 03984 &validity, 03985 byte_order, 03986 fields_array_len, 03987 header_len, 03988 body_len, 03989 &loader->data, 0, 03990 _dbus_string_get_length (&loader->data))) 03991 { 03992 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 03993 03994 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 03995 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 03996 _dbus_assert (validity != DBUS_VALID); 03997 03998 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 03999 oom = TRUE; 04000 else 04001 { 04002 loader->corrupted = TRUE; 04003 loader->corruption_reason = validity; 04004 } 04005 goto failed; 04006 } 04007 04008 _dbus_assert (validity == DBUS_VALID); 04009 04010 message->byte_order = byte_order; 04011 04012 /* 2. VALIDATE BODY */ 04013 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 04014 { 04015 get_const_signature (&message->header, &type_str, &type_pos); 04016 04017 /* Because the bytes_remaining arg is NULL, this validates that the 04018 * body is the right length 04019 */ 04020 validity = _dbus_validate_body_with_reason (type_str, 04021 type_pos, 04022 byte_order, 04023 NULL, 04024 &loader->data, 04025 header_len, 04026 body_len); 04027 if (validity != DBUS_VALID) 04028 { 04029 _dbus_verbose ("Failed to validate message body code %d\n", validity); 04030 04031 loader->corrupted = TRUE; 04032 loader->corruption_reason = validity; 04033 04034 goto failed; 04035 } 04036 } 04037 04038 /* 3. COPY OVER UNIX FDS */ 04039 _dbus_header_get_field_basic(&message->header, 04040 DBUS_HEADER_FIELD_UNIX_FDS, 04041 DBUS_TYPE_UINT32, 04042 &n_unix_fds); 04043 04044 #ifdef HAVE_UNIX_FD_PASSING 04045 04046 if (n_unix_fds > loader->n_unix_fds) 04047 { 04048 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n", 04049 n_unix_fds, loader->n_unix_fds); 04050 04051 loader->corrupted = TRUE; 04052 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04053 goto failed; 04054 } 04055 04056 /* If this was a recycled message there might still be 04057 some memory allocated for the fds */ 04058 dbus_free(message->unix_fds); 04059 04060 if (n_unix_fds > 0) 04061 { 04062 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0])); 04063 if (message->unix_fds == NULL) 04064 { 04065 _dbus_verbose ("Failed to allocate file descriptor array\n"); 04066 oom = TRUE; 04067 goto failed; 04068 } 04069 04070 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; 04071 loader->n_unix_fds -= n_unix_fds; 04072 memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0])); 04073 04074 if (loader->unix_fds_change) 04075 loader->unix_fds_change (loader->unix_fds_change_data); 04076 } 04077 else 04078 message->unix_fds = NULL; 04079 04080 #else 04081 04082 if (n_unix_fds > 0) 04083 { 04084 _dbus_verbose ("Hmm, message claims to come with file descriptors " 04085 "but that's not supported on our platform, disconnecting.\n"); 04086 04087 loader->corrupted = TRUE; 04088 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04089 goto failed; 04090 } 04091 04092 #endif 04093 04094 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 04095 04096 if (!_dbus_list_append (&loader->messages, message)) 04097 { 04098 _dbus_verbose ("Failed to append new message to loader queue\n"); 04099 oom = TRUE; 04100 goto failed; 04101 } 04102 04103 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 04104 _dbus_assert (_dbus_string_get_length (&loader->data) >= 04105 (header_len + body_len)); 04106 04107 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 04108 { 04109 _dbus_verbose ("Failed to move body into new message\n"); 04110 oom = TRUE; 04111 goto failed; 04112 } 04113 04114 _dbus_string_delete (&loader->data, 0, header_len + body_len); 04115 04116 /* don't waste more than 2k of memory */ 04117 _dbus_string_compact (&loader->data, 2048); 04118 04119 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 04120 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 04121 04122 _dbus_verbose ("Loaded message %p\n", message); 04123 04124 _dbus_assert (!oom); 04125 _dbus_assert (!loader->corrupted); 04126 _dbus_assert (loader->messages != NULL); 04127 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04128 04129 return TRUE; 04130 04131 failed: 04132 04133 /* Clean up */ 04134 04135 /* does nothing if the message isn't in the list */ 04136 _dbus_list_remove_last (&loader->messages, message); 04137 04138 if (oom) 04139 _dbus_assert (!loader->corrupted); 04140 else 04141 _dbus_assert (loader->corrupted); 04142 04143 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 04144 04145 return FALSE; 04146 } 04147 04162 dbus_bool_t 04163 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 04164 { 04165 while (!loader->corrupted && 04166 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 04167 { 04168 DBusValidity validity; 04169 int byte_order, fields_array_len, header_len, body_len; 04170 04171 if (_dbus_header_have_message_untrusted (loader->max_message_size, 04172 &validity, 04173 &byte_order, 04174 &fields_array_len, 04175 &header_len, 04176 &body_len, 04177 &loader->data, 0, 04178 _dbus_string_get_length (&loader->data))) 04179 { 04180 DBusMessage *message; 04181 04182 _dbus_assert (validity == DBUS_VALID); 04183 04184 message = dbus_message_new_empty_header (); 04185 if (message == NULL) 04186 return FALSE; 04187 04188 if (!load_message (loader, message, 04189 byte_order, fields_array_len, 04190 header_len, body_len)) 04191 { 04192 dbus_message_unref (message); 04193 /* load_message() returns false if corrupted or OOM; if 04194 * corrupted then return TRUE for not OOM 04195 */ 04196 return loader->corrupted; 04197 } 04198 04199 _dbus_assert (loader->messages != NULL); 04200 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04201 } 04202 else 04203 { 04204 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 04205 validity); 04206 if (validity != DBUS_VALID) 04207 { 04208 loader->corrupted = TRUE; 04209 loader->corruption_reason = validity; 04210 } 04211 return TRUE; 04212 } 04213 } 04214 04215 return TRUE; 04216 } 04217 04225 DBusMessage* 04226 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 04227 { 04228 if (loader->messages) 04229 return loader->messages->data; 04230 else 04231 return NULL; 04232 } 04233 04242 DBusMessage* 04243 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 04244 { 04245 return _dbus_list_pop_first (&loader->messages); 04246 } 04247 04256 DBusList* 04257 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 04258 { 04259 return _dbus_list_pop_first_link (&loader->messages); 04260 } 04261 04268 void 04269 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 04270 DBusList *link) 04271 { 04272 _dbus_list_prepend_link (&loader->messages, link); 04273 } 04274 04284 dbus_bool_t 04285 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 04286 { 04287 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04288 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04289 return loader->corrupted; 04290 } 04291 04298 DBusValidity 04299 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 04300 { 04301 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04302 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04303 04304 return loader->corruption_reason; 04305 } 04306 04313 void 04314 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 04315 long size) 04316 { 04317 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 04318 { 04319 _dbus_verbose ("clamping requested max message size %ld to %d\n", 04320 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 04321 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 04322 } 04323 loader->max_message_size = size; 04324 } 04325 04332 long 04333 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 04334 { 04335 return loader->max_message_size; 04336 } 04337 04344 void 04345 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, 04346 long n) 04347 { 04348 if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS) 04349 { 04350 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n", 04351 n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS); 04352 n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS; 04353 } 04354 loader->max_message_unix_fds = n; 04355 } 04356 04363 long 04364 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) 04365 { 04366 return loader->max_message_unix_fds; 04367 } 04368 04369 static DBusDataSlotAllocator slot_allocator; 04370 _DBUS_DEFINE_GLOBAL_LOCK (message_slots); 04371 04377 int 04378 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader) 04379 { 04380 #ifdef HAVE_UNIX_FD_PASSING 04381 return loader->n_unix_fds; 04382 #else 04383 return 0; 04384 #endif 04385 } 04386 04395 void 04396 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader, 04397 void (* callback) (void *), 04398 void *data) 04399 { 04400 #ifdef HAVE_UNIX_FD_PASSING 04401 loader->unix_fds_change = callback; 04402 loader->unix_fds_change_data = data; 04403 #endif 04404 } 04405 04420 dbus_bool_t 04421 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 04422 { 04423 return _dbus_data_slot_allocator_alloc (&slot_allocator, 04424 &_DBUS_LOCK_NAME (message_slots), 04425 slot_p); 04426 } 04427 04439 void 04440 dbus_message_free_data_slot (dbus_int32_t *slot_p) 04441 { 04442 _dbus_return_if_fail (*slot_p >= 0); 04443 04444 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 04445 } 04446 04460 dbus_bool_t 04461 dbus_message_set_data (DBusMessage *message, 04462 dbus_int32_t slot, 04463 void *data, 04464 DBusFreeFunction free_data_func) 04465 { 04466 DBusFreeFunction old_free_func; 04467 void *old_data; 04468 dbus_bool_t retval; 04469 04470 _dbus_return_val_if_fail (message != NULL, FALSE); 04471 _dbus_return_val_if_fail (slot >= 0, FALSE); 04472 04473 retval = _dbus_data_slot_list_set (&slot_allocator, 04474 &message->slot_list, 04475 slot, data, free_data_func, 04476 &old_free_func, &old_data); 04477 04478 if (retval) 04479 { 04480 /* Do the actual free outside the message lock */ 04481 if (old_free_func) 04482 (* old_free_func) (old_data); 04483 } 04484 04485 return retval; 04486 } 04487 04496 void* 04497 dbus_message_get_data (DBusMessage *message, 04498 dbus_int32_t slot) 04499 { 04500 void *res; 04501 04502 _dbus_return_val_if_fail (message != NULL, NULL); 04503 04504 res = _dbus_data_slot_list_get (&slot_allocator, 04505 &message->slot_list, 04506 slot); 04507 04508 return res; 04509 } 04510 04524 int 04525 dbus_message_type_from_string (const char *type_str) 04526 { 04527 if (strcmp (type_str, "method_call") == 0) 04528 return DBUS_MESSAGE_TYPE_METHOD_CALL; 04529 if (strcmp (type_str, "method_return") == 0) 04530 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 04531 else if (strcmp (type_str, "signal") == 0) 04532 return DBUS_MESSAGE_TYPE_SIGNAL; 04533 else if (strcmp (type_str, "error") == 0) 04534 return DBUS_MESSAGE_TYPE_ERROR; 04535 else 04536 return DBUS_MESSAGE_TYPE_INVALID; 04537 } 04538 04552 const char * 04553 dbus_message_type_to_string (int type) 04554 { 04555 switch (type) 04556 { 04557 case DBUS_MESSAGE_TYPE_METHOD_CALL: 04558 return "method_call"; 04559 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 04560 return "method_return"; 04561 case DBUS_MESSAGE_TYPE_SIGNAL: 04562 return "signal"; 04563 case DBUS_MESSAGE_TYPE_ERROR: 04564 return "error"; 04565 default: 04566 return "invalid"; 04567 } 04568 } 04569 04582 dbus_bool_t 04583 dbus_message_marshal (DBusMessage *msg, 04584 char **marshalled_data_p, 04585 int *len_p) 04586 { 04587 DBusString tmp; 04588 dbus_bool_t was_locked; 04589 04590 _dbus_return_val_if_fail (msg != NULL, FALSE); 04591 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04592 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04593 04594 if (!_dbus_string_init (&tmp)) 04595 return FALSE; 04596 04597 /* Ensure the message is locked, to ensure the length header is filled in. */ 04598 was_locked = msg->locked; 04599 04600 if (!was_locked) 04601 dbus_message_lock (msg); 04602 04603 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04604 goto fail; 04605 04606 *len_p = _dbus_string_get_length (&tmp); 04607 04608 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04609 goto fail; 04610 04611 *len_p = _dbus_string_get_length (&tmp); 04612 04613 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04614 goto fail; 04615 04616 _dbus_string_free (&tmp); 04617 04618 if (!was_locked) 04619 msg->locked = FALSE; 04620 04621 return TRUE; 04622 04623 fail: 04624 _dbus_string_free (&tmp); 04625 04626 if (!was_locked) 04627 msg->locked = FALSE; 04628 04629 return FALSE; 04630 } 04631 04644 DBusMessage * 04645 dbus_message_demarshal (const char *str, 04646 int len, 04647 DBusError *error) 04648 { 04649 DBusMessageLoader *loader; 04650 DBusString *buffer; 04651 DBusMessage *msg; 04652 04653 _dbus_return_val_if_fail (str != NULL, NULL); 04654 04655 loader = _dbus_message_loader_new (); 04656 04657 if (loader == NULL) 04658 return NULL; 04659 04660 _dbus_message_loader_get_buffer (loader, &buffer); 04661 _dbus_string_append_len (buffer, str, len); 04662 _dbus_message_loader_return_buffer (loader, buffer, len); 04663 04664 if (!_dbus_message_loader_queue_messages (loader)) 04665 goto fail_oom; 04666 04667 if (_dbus_message_loader_get_is_corrupted (loader)) 04668 goto fail_corrupt; 04669 04670 msg = _dbus_message_loader_pop_message (loader); 04671 04672 if (!msg) 04673 goto fail_oom; 04674 04675 _dbus_message_loader_unref (loader); 04676 return msg; 04677 04678 fail_corrupt: 04679 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04680 _dbus_validity_to_error_message (loader->corruption_reason)); 04681 _dbus_message_loader_unref (loader); 04682 return NULL; 04683 04684 fail_oom: 04685 _DBUS_SET_OOM (error); 04686 _dbus_message_loader_unref (loader); 04687 return NULL; 04688 } 04689 04703 int 04704 dbus_message_demarshal_bytes_needed(const char *buf, 04705 int len) 04706 { 04707 DBusString str; 04708 int byte_order, fields_array_len, header_len, body_len; 04709 DBusValidity validity = DBUS_VALID; 04710 int have_message; 04711 04712 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04713 return 0; 04714 04715 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04716 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04717 _dbus_string_init_const_len (&str, buf, len); 04718 04719 validity = DBUS_VALID; 04720 have_message 04721 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04722 &validity, &byte_order, 04723 &fields_array_len, 04724 &header_len, 04725 &body_len, 04726 &str, 0, 04727 len); 04728 _dbus_string_free (&str); 04729 04730 if (validity == DBUS_VALID) 04731 { 04732 _dbus_assert (have_message || (header_len + body_len) > len); 04733 return header_len + body_len; 04734 } 04735 else 04736 { 04737 return -1; /* broken! */ 04738 } 04739 } 04740 04743 /* tests in dbus-message-util.c */