D-Bus
1.10.12
|
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 #define _DBUS_TYPE_IS_STRINGLIKE(type) \ 00045 (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \ 00046 type == DBUS_TYPE_OBJECT_PATH) 00047 00048 static void dbus_message_finalize (DBusMessage *message); 00049 00060 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00061 static dbus_bool_t 00062 _dbus_enable_message_cache (void) 00063 { 00064 static int enabled = -1; 00065 00066 if (enabled < 0) 00067 { 00068 const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE"); 00069 00070 enabled = TRUE; 00071 00072 if (s && *s) 00073 { 00074 if (*s == '0') 00075 enabled = FALSE; 00076 else if (*s == '1') 00077 enabled = TRUE; 00078 else 00079 _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'", 00080 s); 00081 } 00082 } 00083 00084 return enabled; 00085 } 00086 #else 00087 /* constant expression, should be optimized away */ 00088 # define _dbus_enable_message_cache() (TRUE) 00089 #endif 00090 00091 #ifndef _dbus_message_trace_ref 00092 void 00093 _dbus_message_trace_ref (DBusMessage *message, 00094 int old_refcount, 00095 int new_refcount, 00096 const char *why) 00097 { 00098 static int enabled = -1; 00099 00100 _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why, 00101 "DBUS_MESSAGE_TRACE", &enabled); 00102 } 00103 #endif 00104 00105 /* Not thread locked, but strictly const/read-only so should be OK 00106 */ 00108 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, ""); 00109 00110 /* these have wacky values to help trap uninitialized iterators; 00111 * but has to fit in 3 bits 00112 */ 00113 enum { 00114 DBUS_MESSAGE_ITER_TYPE_READER = 3, 00115 DBUS_MESSAGE_ITER_TYPE_WRITER = 7 00116 }; 00117 00119 typedef struct DBusMessageRealIter DBusMessageRealIter; 00120 00126 struct DBusMessageRealIter 00127 { 00128 DBusMessage *message; 00129 dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 00130 dbus_uint32_t iter_type : 3; 00131 dbus_uint32_t sig_refcount : 8; 00132 union 00133 { 00134 DBusTypeWriter writer; 00135 DBusTypeReader reader; 00136 } u; 00137 }; 00138 00144 typedef struct 00145 { 00146 void *dummy1; 00147 void *dummy2; 00148 dbus_uint32_t dummy3; 00149 int dummy4; 00150 int dummy5; 00151 int dummy6; 00152 int dummy7; 00153 int dummy8; 00154 int dummy9; 00155 int dummy10; 00156 int dummy11; 00157 int pad1; 00158 int pad2; 00159 void *pad3; 00160 } DBusMessageIter_1_10_0; 00161 00162 static void 00163 get_const_signature (DBusHeader *header, 00164 const DBusString **type_str_p, 00165 int *type_pos_p) 00166 { 00167 if (_dbus_header_get_field_raw (header, 00168 DBUS_HEADER_FIELD_SIGNATURE, 00169 type_str_p, 00170 type_pos_p)) 00171 { 00172 *type_pos_p += 1; /* skip the signature length which is 1 byte */ 00173 } 00174 else 00175 { 00176 *type_str_p = &_dbus_empty_signature_str; 00177 *type_pos_p = 0; 00178 } 00179 } 00180 00186 static void 00187 _dbus_message_byteswap (DBusMessage *message) 00188 { 00189 const DBusString *type_str; 00190 int type_pos; 00191 char byte_order; 00192 00193 byte_order = _dbus_header_get_byte_order (&message->header); 00194 00195 if (byte_order == DBUS_COMPILER_BYTE_ORDER) 00196 return; 00197 00198 _dbus_verbose ("Swapping message into compiler byte order\n"); 00199 00200 get_const_signature (&message->header, &type_str, &type_pos); 00201 00202 _dbus_marshal_byteswap (type_str, type_pos, 00203 byte_order, 00204 DBUS_COMPILER_BYTE_ORDER, 00205 &message->body, 0); 00206 00207 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER); 00208 _dbus_assert (_dbus_header_get_byte_order (&message->header) == 00209 DBUS_COMPILER_BYTE_ORDER); 00210 } 00211 00218 #define ensure_byte_order(message) _dbus_message_byteswap (message) 00219 00230 void 00231 _dbus_message_get_network_data (DBusMessage *message, 00232 const DBusString **header, 00233 const DBusString **body) 00234 { 00235 _dbus_assert (message->locked); 00236 00237 *header = &message->header.data; 00238 *body = &message->body; 00239 } 00240 00250 void _dbus_message_get_unix_fds(DBusMessage *message, 00251 const int **fds, 00252 unsigned *n_fds) 00253 { 00254 _dbus_assert (message->locked); 00255 00256 #ifdef HAVE_UNIX_FD_PASSING 00257 *fds = message->unix_fds; 00258 *n_fds = message->n_unix_fds; 00259 #else 00260 *fds = NULL; 00261 *n_fds = 0; 00262 #endif 00263 } 00264 00276 void 00277 dbus_message_set_serial (DBusMessage *message, 00278 dbus_uint32_t serial) 00279 { 00280 _dbus_return_if_fail (message != NULL); 00281 _dbus_return_if_fail (!message->locked); 00282 00283 _dbus_header_set_serial (&message->header, serial); 00284 } 00285 00302 void 00303 _dbus_message_add_counter_link (DBusMessage *message, 00304 DBusList *link) 00305 { 00306 /* right now we don't recompute the delta when message 00307 * size changes, and that's OK for current purposes 00308 * I think, but could be important to change later. 00309 * Do recompute it whenever there are no outstanding counters, 00310 * since it's basically free. 00311 */ 00312 if (message->counters == NULL) 00313 { 00314 message->size_counter_delta = 00315 _dbus_string_get_length (&message->header.data) + 00316 _dbus_string_get_length (&message->body); 00317 00318 #ifdef HAVE_UNIX_FD_PASSING 00319 message->unix_fd_counter_delta = message->n_unix_fds; 00320 #endif 00321 00322 #if 0 00323 _dbus_verbose ("message has size %ld\n", 00324 message->size_counter_delta); 00325 #endif 00326 } 00327 00328 _dbus_list_append_link (&message->counters, link); 00329 00330 _dbus_counter_adjust_size (link->data, message->size_counter_delta); 00331 00332 #ifdef HAVE_UNIX_FD_PASSING 00333 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta); 00334 #endif 00335 } 00336 00351 dbus_bool_t 00352 _dbus_message_add_counter (DBusMessage *message, 00353 DBusCounter *counter) 00354 { 00355 DBusList *link; 00356 00357 link = _dbus_list_alloc_link (counter); 00358 if (link == NULL) 00359 return FALSE; 00360 00361 _dbus_counter_ref (counter); 00362 _dbus_message_add_counter_link (message, link); 00363 00364 return TRUE; 00365 } 00366 00374 void 00375 _dbus_message_remove_counter (DBusMessage *message, 00376 DBusCounter *counter) 00377 { 00378 DBusList *link; 00379 00380 link = _dbus_list_find_last (&message->counters, 00381 counter); 00382 _dbus_assert (link != NULL); 00383 00384 _dbus_list_remove_link (&message->counters, link); 00385 00386 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00387 00388 #ifdef HAVE_UNIX_FD_PASSING 00389 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00390 #endif 00391 00392 _dbus_counter_notify (counter); 00393 _dbus_counter_unref (counter); 00394 } 00395 00406 void 00407 dbus_message_lock (DBusMessage *message) 00408 { 00409 if (!message->locked) 00410 { 00411 _dbus_header_update_lengths (&message->header, 00412 _dbus_string_get_length (&message->body)); 00413 00414 /* must have a signature if you have a body */ 00415 _dbus_assert (_dbus_string_get_length (&message->body) == 0 || 00416 dbus_message_get_signature (message) != NULL); 00417 00418 message->locked = TRUE; 00419 } 00420 } 00421 00422 static dbus_bool_t 00423 set_or_delete_string_field (DBusMessage *message, 00424 int field, 00425 int typecode, 00426 const char *value) 00427 { 00428 if (value == NULL) 00429 return _dbus_header_delete_field (&message->header, field); 00430 else 00431 return _dbus_header_set_field_basic (&message->header, 00432 field, 00433 typecode, 00434 &value); 00435 } 00436 00437 #if 0 00438 /* Probably we don't need to use this */ 00462 static dbus_bool_t 00463 _dbus_message_set_signature (DBusMessage *message, 00464 const char *signature) 00465 { 00466 _dbus_return_val_if_fail (message != NULL, FALSE); 00467 _dbus_return_val_if_fail (!message->locked, FALSE); 00468 _dbus_return_val_if_fail (signature == NULL || 00469 _dbus_check_is_valid_signature (signature)); 00470 /* can't delete the signature if you have a message body */ 00471 _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || 00472 signature != NULL); 00473 00474 return set_or_delete_string_field (message, 00475 DBUS_HEADER_FIELD_SIGNATURE, 00476 DBUS_TYPE_SIGNATURE, 00477 signature); 00478 } 00479 #endif 00480 00481 /* Message Cache 00482 * 00483 * We cache some DBusMessage to reduce the overhead of allocating 00484 * them. In my profiling this consistently made about an 8% 00485 * difference. It avoids the malloc for the message, the malloc for 00486 * the slot list, the malloc for the header string and body string, 00487 * and the associated free() calls. It does introduce another global 00488 * lock which could be a performance issue in certain cases. 00489 * 00490 * For the echo client/server the round trip time goes from around 00491 * .000077 to .000069 with the message cache on my laptop. The sysprof 00492 * change is as follows (numbers are cumulative percentage): 00493 * 00494 * with message cache implemented as array as it is now (0.000069 per): 00495 * new_empty_header 1.46 00496 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache) 00497 * mutex_unlock 0.25 00498 * self 0.41 00499 * unref 2.24 00500 * self 0.68 00501 * list_clear 0.43 00502 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache) 00503 * mutex_unlock 0.25 00504 * 00505 * with message cache implemented as list (0.000070 per roundtrip): 00506 * new_empty_header 2.72 00507 * list_pop_first 1.88 00508 * unref 3.3 00509 * list_prepend 1.63 00510 * 00511 * without cache (0.000077 per roundtrip): 00512 * new_empty_header 6.7 00513 * string_init_preallocated 3.43 00514 * dbus_malloc 2.43 00515 * dbus_malloc0 2.59 00516 * 00517 * unref 4.02 00518 * string_free 1.82 00519 * dbus_free 1.63 00520 * dbus_free 0.71 00521 * 00522 * If you implement the message_cache with a list, the primary reason 00523 * it's slower is that you add another thread lock (on the DBusList 00524 * mempool). 00525 */ 00526 00528 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE 00529 00531 #define MAX_MESSAGE_CACHE_SIZE 5 00532 00533 /* Protected by _DBUS_LOCK (message_cache) */ 00534 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; 00535 static int message_cache_count = 0; 00536 static dbus_bool_t message_cache_shutdown_registered = FALSE; 00537 00538 static void 00539 dbus_message_cache_shutdown (void *data) 00540 { 00541 int i; 00542 00543 if (!_DBUS_LOCK (message_cache)) 00544 _dbus_assert_not_reached ("we would have initialized global locks " 00545 "before registering a shutdown function"); 00546 00547 i = 0; 00548 while (i < MAX_MESSAGE_CACHE_SIZE) 00549 { 00550 if (message_cache[i]) 00551 dbus_message_finalize (message_cache[i]); 00552 00553 ++i; 00554 } 00555 00556 message_cache_count = 0; 00557 message_cache_shutdown_registered = FALSE; 00558 00559 _DBUS_UNLOCK (message_cache); 00560 } 00561 00569 static DBusMessage* 00570 dbus_message_get_cached (void) 00571 { 00572 DBusMessage *message; 00573 int i; 00574 00575 message = NULL; 00576 00577 if (!_DBUS_LOCK (message_cache)) 00578 { 00579 /* we'd have initialized global locks before caching anything, 00580 * so there can't be anything in the cache */ 00581 return NULL; 00582 } 00583 00584 _dbus_assert (message_cache_count >= 0); 00585 00586 if (message_cache_count == 0) 00587 { 00588 _DBUS_UNLOCK (message_cache); 00589 return NULL; 00590 } 00591 00592 /* This is not necessarily true unless count > 0, and 00593 * message_cache is uninitialized until the shutdown is 00594 * registered 00595 */ 00596 _dbus_assert (message_cache_shutdown_registered); 00597 00598 i = 0; 00599 while (i < MAX_MESSAGE_CACHE_SIZE) 00600 { 00601 if (message_cache[i]) 00602 { 00603 message = message_cache[i]; 00604 message_cache[i] = NULL; 00605 message_cache_count -= 1; 00606 break; 00607 } 00608 ++i; 00609 } 00610 _dbus_assert (message_cache_count >= 0); 00611 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00612 _dbus_assert (message != NULL); 00613 00614 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00615 00616 _dbus_assert (message->counters == NULL); 00617 00618 _DBUS_UNLOCK (message_cache); 00619 00620 return message; 00621 } 00622 00623 #ifdef HAVE_UNIX_FD_PASSING 00624 static void 00625 close_unix_fds(int *fds, unsigned *n_fds) 00626 { 00627 DBusError e; 00628 unsigned int i; 00629 00630 if (*n_fds <= 0) 00631 return; 00632 00633 dbus_error_init(&e); 00634 00635 for (i = 0; i < *n_fds; i++) 00636 { 00637 if (!_dbus_close(fds[i], &e)) 00638 { 00639 _dbus_warn("Failed to close file descriptor: %s\n", e.message); 00640 dbus_error_free(&e); 00641 } 00642 } 00643 00644 *n_fds = 0; 00645 00646 /* We don't free the array here, in case we can recycle it later */ 00647 } 00648 #endif 00649 00650 static void 00651 free_counter (void *element, 00652 void *data) 00653 { 00654 DBusCounter *counter = element; 00655 DBusMessage *message = data; 00656 00657 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00658 #ifdef HAVE_UNIX_FD_PASSING 00659 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00660 #endif 00661 00662 _dbus_counter_notify (counter); 00663 _dbus_counter_unref (counter); 00664 } 00665 00671 static void 00672 dbus_message_cache_or_finalize (DBusMessage *message) 00673 { 00674 dbus_bool_t was_cached; 00675 int i; 00676 00677 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00678 00679 /* This calls application code and has to be done first thing 00680 * without holding the lock 00681 */ 00682 _dbus_data_slot_list_clear (&message->slot_list); 00683 00684 _dbus_list_foreach (&message->counters, 00685 free_counter, message); 00686 _dbus_list_clear (&message->counters); 00687 00688 #ifdef HAVE_UNIX_FD_PASSING 00689 close_unix_fds(message->unix_fds, &message->n_unix_fds); 00690 #endif 00691 00692 was_cached = FALSE; 00693 00694 if (!_DBUS_LOCK (message_cache)) 00695 { 00696 /* The only way to get a non-null message goes through 00697 * dbus_message_get_cached() which takes the lock. */ 00698 _dbus_assert_not_reached ("we would have initialized global locks " 00699 "the first time we constructed a message"); 00700 } 00701 00702 if (!message_cache_shutdown_registered) 00703 { 00704 _dbus_assert (message_cache_count == 0); 00705 00706 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL)) 00707 goto out; 00708 00709 i = 0; 00710 while (i < MAX_MESSAGE_CACHE_SIZE) 00711 { 00712 message_cache[i] = NULL; 00713 ++i; 00714 } 00715 00716 message_cache_shutdown_registered = TRUE; 00717 } 00718 00719 _dbus_assert (message_cache_count >= 0); 00720 00721 if (!_dbus_enable_message_cache ()) 00722 goto out; 00723 00724 if ((_dbus_string_get_length (&message->header.data) + 00725 _dbus_string_get_length (&message->body)) > 00726 MAX_MESSAGE_SIZE_TO_CACHE) 00727 goto out; 00728 00729 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE) 00730 goto out; 00731 00732 /* Find empty slot */ 00733 i = 0; 00734 while (message_cache[i] != NULL) 00735 ++i; 00736 00737 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00738 00739 _dbus_assert (message_cache[i] == NULL); 00740 message_cache[i] = message; 00741 message_cache_count += 1; 00742 was_cached = TRUE; 00743 #ifndef DBUS_DISABLE_CHECKS 00744 message->in_cache = TRUE; 00745 #endif 00746 00747 out: 00748 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00749 00750 _DBUS_UNLOCK (message_cache); 00751 00752 if (!was_cached) 00753 dbus_message_finalize (message); 00754 } 00755 00756 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT) 00757 static dbus_bool_t 00758 _dbus_message_iter_check (DBusMessageRealIter *iter) 00759 { 00760 char byte_order; 00761 00762 if (iter == NULL) 00763 { 00764 _dbus_warn_check_failed ("dbus message iterator is NULL\n"); 00765 return FALSE; 00766 } 00767 00768 byte_order = _dbus_header_get_byte_order (&iter->message->header); 00769 00770 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER) 00771 { 00772 if (iter->u.reader.byte_order != byte_order) 00773 { 00774 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n"); 00775 return FALSE; 00776 } 00777 /* because we swap the message into compiler order when you init an iter */ 00778 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); 00779 } 00780 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) 00781 { 00782 if (iter->u.writer.byte_order != byte_order) 00783 { 00784 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n"); 00785 return FALSE; 00786 } 00787 /* because we swap the message into compiler order when you init an iter */ 00788 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); 00789 } 00790 else 00791 { 00792 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n"); 00793 return FALSE; 00794 } 00795 00796 if (iter->changed_stamp != iter->message->changed_stamp) 00797 { 00798 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); 00799 return FALSE; 00800 } 00801 00802 return TRUE; 00803 } 00804 #endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */ 00805 00818 dbus_bool_t 00819 _dbus_message_iter_get_args_valist (DBusMessageIter *iter, 00820 DBusError *error, 00821 int first_arg_type, 00822 va_list var_args) 00823 { 00824 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 00825 int spec_type, msg_type, i, j; 00826 dbus_bool_t retval; 00827 va_list copy_args; 00828 00829 _dbus_assert (_dbus_message_iter_check (real)); 00830 00831 retval = FALSE; 00832 00833 spec_type = first_arg_type; 00834 i = 0; 00835 00836 /* copy var_args first, then we can do another iteration over it to 00837 * free memory and close unix fds if parse failed at some point. 00838 */ 00839 DBUS_VA_COPY (copy_args, var_args); 00840 00841 while (spec_type != DBUS_TYPE_INVALID) 00842 { 00843 msg_type = dbus_message_iter_get_arg_type (iter); 00844 00845 if (msg_type != spec_type) 00846 { 00847 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00848 "Argument %d is specified to be of type \"%s\", but " 00849 "is actually of type \"%s\"\n", i, 00850 _dbus_type_to_string (spec_type), 00851 _dbus_type_to_string (msg_type)); 00852 00853 goto out; 00854 } 00855 00856 if (spec_type == DBUS_TYPE_UNIX_FD) 00857 { 00858 #ifdef HAVE_UNIX_FD_PASSING 00859 DBusBasicValue idx; 00860 int *pfd, nfd; 00861 00862 pfd = va_arg (var_args, int*); 00863 _dbus_assert(pfd); 00864 00865 _dbus_type_reader_read_basic(&real->u.reader, &idx); 00866 00867 if (idx.u32 >= real->message->n_unix_fds) 00868 { 00869 dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE, 00870 "Message refers to file descriptor at index %i," 00871 "but has only %i descriptors attached.\n", 00872 idx.u32, 00873 real->message->n_unix_fds); 00874 goto out; 00875 } 00876 00877 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0) 00878 goto out; 00879 00880 *pfd = nfd; 00881 #else 00882 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00883 "Platform does not support file desciptor passing.\n"); 00884 goto out; 00885 #endif 00886 } 00887 else if (dbus_type_is_basic (spec_type)) 00888 { 00889 DBusBasicValue *ptr; 00890 00891 ptr = va_arg (var_args, DBusBasicValue*); 00892 00893 _dbus_assert (ptr != NULL); 00894 00895 _dbus_type_reader_read_basic (&real->u.reader, 00896 ptr); 00897 } 00898 else if (spec_type == DBUS_TYPE_ARRAY) 00899 { 00900 int element_type; 00901 int spec_element_type; 00902 const DBusBasicValue **ptr; 00903 int *n_elements_p; 00904 DBusTypeReader array; 00905 00906 spec_element_type = va_arg (var_args, int); 00907 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 00908 00909 if (spec_element_type != element_type) 00910 { 00911 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00912 "Argument %d is specified to be an array of \"%s\", but " 00913 "is actually an array of \"%s\"\n", 00914 i, 00915 _dbus_type_to_string (spec_element_type), 00916 _dbus_type_to_string (element_type)); 00917 00918 goto out; 00919 } 00920 00921 if (dbus_type_is_fixed (spec_element_type) && 00922 element_type != DBUS_TYPE_UNIX_FD) 00923 { 00924 ptr = va_arg (var_args, const DBusBasicValue**); 00925 n_elements_p = va_arg (var_args, int*); 00926 00927 _dbus_assert (ptr != NULL); 00928 _dbus_assert (n_elements_p != NULL); 00929 00930 _dbus_type_reader_recurse (&real->u.reader, &array); 00931 00932 _dbus_type_reader_read_fixed_multi (&array, 00933 (void *) ptr, n_elements_p); 00934 } 00935 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type)) 00936 { 00937 char ***str_array_p; 00938 int n_elements; 00939 char **str_array; 00940 00941 str_array_p = va_arg (var_args, char***); 00942 n_elements_p = va_arg (var_args, int*); 00943 00944 _dbus_assert (str_array_p != NULL); 00945 _dbus_assert (n_elements_p != NULL); 00946 00947 /* Count elements in the array */ 00948 _dbus_type_reader_recurse (&real->u.reader, &array); 00949 00950 n_elements = 0; 00951 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 00952 { 00953 ++n_elements; 00954 _dbus_type_reader_next (&array); 00955 } 00956 00957 str_array = dbus_new0 (char*, n_elements + 1); 00958 if (str_array == NULL) 00959 { 00960 _DBUS_SET_OOM (error); 00961 goto out; 00962 } 00963 00964 /* Now go through and dup each string */ 00965 _dbus_type_reader_recurse (&real->u.reader, &array); 00966 00967 j = 0; 00968 while (j < n_elements) 00969 { 00970 const char *s; 00971 _dbus_type_reader_read_basic (&array, 00972 (void *) &s); 00973 00974 str_array[j] = _dbus_strdup (s); 00975 if (str_array[j] == NULL) 00976 { 00977 dbus_free_string_array (str_array); 00978 _DBUS_SET_OOM (error); 00979 goto out; 00980 } 00981 00982 ++j; 00983 00984 if (!_dbus_type_reader_next (&array)) 00985 _dbus_assert (j == n_elements); 00986 } 00987 00988 _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); 00989 _dbus_assert (j == n_elements); 00990 _dbus_assert (str_array[j] == NULL); 00991 00992 *str_array_p = str_array; 00993 *n_elements_p = n_elements; 00994 } 00995 #ifndef DBUS_DISABLE_CHECKS 00996 else 00997 { 00998 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", 00999 _DBUS_FUNCTION_NAME); 01000 goto out; 01001 } 01002 #endif 01003 } 01004 #ifndef DBUS_DISABLE_CHECKS 01005 else 01006 { 01007 _dbus_warn ("you can only read arrays and basic types with %s for now\n", 01008 _DBUS_FUNCTION_NAME); 01009 goto out; 01010 } 01011 #endif 01012 01013 /* how many arguments already handled */ 01014 i++; 01015 01016 spec_type = va_arg (var_args, int); 01017 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) 01018 { 01019 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 01020 "Message has only %d arguments, but more were expected", i); 01021 goto out; 01022 } 01023 } 01024 01025 retval = TRUE; 01026 01027 out: 01028 /* there may memory or unix fd leak in the above iteration if parse failed. 01029 * so we have another iteration over copy_args to free memory and close 01030 * unix fds. 01031 */ 01032 if (!retval) 01033 { 01034 spec_type = first_arg_type; 01035 j = 0; 01036 01037 while (j < i) 01038 { 01039 if (spec_type == DBUS_TYPE_UNIX_FD) 01040 { 01041 #ifdef HAVE_UNIX_FD_PASSING 01042 int *pfd; 01043 01044 pfd = va_arg (copy_args, int *); 01045 _dbus_assert(pfd); 01046 if (*pfd >= 0) 01047 { 01048 _dbus_close (*pfd, NULL); 01049 *pfd = -1; 01050 } 01051 #endif 01052 } 01053 else if (dbus_type_is_basic (spec_type)) 01054 { 01055 /* move the index forward */ 01056 va_arg (copy_args, DBusBasicValue *); 01057 } 01058 else if (spec_type == DBUS_TYPE_ARRAY) 01059 { 01060 int spec_element_type; 01061 01062 spec_element_type = va_arg (copy_args, int); 01063 if (dbus_type_is_fixed (spec_element_type)) 01064 { 01065 /* move the index forward */ 01066 va_arg (copy_args, const DBusBasicValue **); 01067 va_arg (copy_args, int *); 01068 } 01069 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type)) 01070 { 01071 char ***str_array_p; 01072 01073 str_array_p = va_arg (copy_args, char ***); 01074 /* move the index forward */ 01075 va_arg (copy_args, int *); 01076 _dbus_assert (str_array_p != NULL); 01077 dbus_free_string_array (*str_array_p); 01078 *str_array_p = NULL; 01079 } 01080 } 01081 01082 spec_type = va_arg (copy_args, int); 01083 j++; 01084 } 01085 } 01086 01087 va_end (copy_args); 01088 return retval; 01089 } 01090 01149 dbus_uint32_t 01150 dbus_message_get_serial (DBusMessage *message) 01151 { 01152 _dbus_return_val_if_fail (message != NULL, 0); 01153 01154 return _dbus_header_get_serial (&message->header); 01155 } 01156 01165 dbus_bool_t 01166 dbus_message_set_reply_serial (DBusMessage *message, 01167 dbus_uint32_t reply_serial) 01168 { 01169 DBusBasicValue value; 01170 01171 _dbus_return_val_if_fail (message != NULL, FALSE); 01172 _dbus_return_val_if_fail (!message->locked, FALSE); 01173 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */ 01174 01175 value.u32 = reply_serial; 01176 01177 return _dbus_header_set_field_basic (&message->header, 01178 DBUS_HEADER_FIELD_REPLY_SERIAL, 01179 DBUS_TYPE_UINT32, 01180 &value); 01181 } 01182 01189 dbus_uint32_t 01190 dbus_message_get_reply_serial (DBusMessage *message) 01191 { 01192 dbus_uint32_t v_UINT32; 01193 01194 _dbus_return_val_if_fail (message != NULL, 0); 01195 01196 if (_dbus_header_get_field_basic (&message->header, 01197 DBUS_HEADER_FIELD_REPLY_SERIAL, 01198 DBUS_TYPE_UINT32, 01199 &v_UINT32)) 01200 return v_UINT32; 01201 else 01202 return 0; 01203 } 01204 01205 static void 01206 dbus_message_finalize (DBusMessage *message) 01207 { 01208 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01209 01210 /* This calls application callbacks! */ 01211 _dbus_data_slot_list_free (&message->slot_list); 01212 01213 _dbus_list_foreach (&message->counters, 01214 free_counter, message); 01215 _dbus_list_clear (&message->counters); 01216 01217 _dbus_header_free (&message->header); 01218 _dbus_string_free (&message->body); 01219 01220 #ifdef HAVE_UNIX_FD_PASSING 01221 close_unix_fds(message->unix_fds, &message->n_unix_fds); 01222 dbus_free(message->unix_fds); 01223 #endif 01224 01225 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01226 01227 dbus_free (message); 01228 } 01229 01230 static DBusMessage* 01231 dbus_message_new_empty_header (void) 01232 { 01233 DBusMessage *message; 01234 dbus_bool_t from_cache; 01235 01236 message = dbus_message_get_cached (); 01237 01238 if (message != NULL) 01239 { 01240 from_cache = TRUE; 01241 } 01242 else 01243 { 01244 from_cache = FALSE; 01245 message = dbus_new0 (DBusMessage, 1); 01246 if (message == NULL) 01247 return NULL; 01248 #ifndef DBUS_DISABLE_CHECKS 01249 message->generation = _dbus_current_generation; 01250 #endif 01251 01252 #ifdef HAVE_UNIX_FD_PASSING 01253 message->unix_fds = NULL; 01254 message->n_unix_fds_allocated = 0; 01255 #endif 01256 } 01257 01258 _dbus_atomic_inc (&message->refcount); 01259 01260 _dbus_message_trace_ref (message, 0, 1, "new_empty_header"); 01261 01262 message->locked = FALSE; 01263 #ifndef DBUS_DISABLE_CHECKS 01264 message->in_cache = FALSE; 01265 #endif 01266 message->counters = NULL; 01267 message->size_counter_delta = 0; 01268 message->changed_stamp = 0; 01269 01270 #ifdef HAVE_UNIX_FD_PASSING 01271 message->n_unix_fds = 0; 01272 message->n_unix_fds_allocated = 0; 01273 message->unix_fd_counter_delta = 0; 01274 #endif 01275 01276 if (!from_cache) 01277 _dbus_data_slot_list_init (&message->slot_list); 01278 01279 if (from_cache) 01280 { 01281 _dbus_header_reinit (&message->header); 01282 _dbus_string_set_length (&message->body, 0); 01283 } 01284 else 01285 { 01286 if (!_dbus_header_init (&message->header)) 01287 { 01288 dbus_free (message); 01289 return NULL; 01290 } 01291 01292 if (!_dbus_string_init_preallocated (&message->body, 32)) 01293 { 01294 _dbus_header_free (&message->header); 01295 dbus_free (message); 01296 return NULL; 01297 } 01298 } 01299 01300 return message; 01301 } 01302 01315 DBusMessage* 01316 dbus_message_new (int message_type) 01317 { 01318 DBusMessage *message; 01319 01320 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL); 01321 01322 message = dbus_message_new_empty_header (); 01323 if (message == NULL) 01324 return NULL; 01325 01326 if (!_dbus_header_create (&message->header, 01327 DBUS_COMPILER_BYTE_ORDER, 01328 message_type, 01329 NULL, NULL, NULL, NULL, NULL)) 01330 { 01331 dbus_message_unref (message); 01332 return NULL; 01333 } 01334 01335 return message; 01336 } 01337 01359 DBusMessage* 01360 dbus_message_new_method_call (const char *destination, 01361 const char *path, 01362 const char *iface, 01363 const char *method) 01364 { 01365 DBusMessage *message; 01366 01367 _dbus_return_val_if_fail (path != NULL, NULL); 01368 _dbus_return_val_if_fail (method != NULL, NULL); 01369 _dbus_return_val_if_fail (destination == NULL || 01370 _dbus_check_is_valid_bus_name (destination), NULL); 01371 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01372 _dbus_return_val_if_fail (iface == NULL || 01373 _dbus_check_is_valid_interface (iface), NULL); 01374 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); 01375 01376 message = dbus_message_new_empty_header (); 01377 if (message == NULL) 01378 return NULL; 01379 01380 if (!_dbus_header_create (&message->header, 01381 DBUS_COMPILER_BYTE_ORDER, 01382 DBUS_MESSAGE_TYPE_METHOD_CALL, 01383 destination, path, iface, method, NULL)) 01384 { 01385 dbus_message_unref (message); 01386 return NULL; 01387 } 01388 01389 return message; 01390 } 01391 01399 DBusMessage* 01400 dbus_message_new_method_return (DBusMessage *method_call) 01401 { 01402 DBusMessage *message; 01403 const char *sender; 01404 01405 _dbus_return_val_if_fail (method_call != NULL, NULL); 01406 01407 sender = dbus_message_get_sender (method_call); 01408 01409 /* sender is allowed to be null here in peer-to-peer case */ 01410 01411 message = dbus_message_new_empty_header (); 01412 if (message == NULL) 01413 return NULL; 01414 01415 if (!_dbus_header_create (&message->header, 01416 DBUS_COMPILER_BYTE_ORDER, 01417 DBUS_MESSAGE_TYPE_METHOD_RETURN, 01418 sender, NULL, NULL, NULL, NULL)) 01419 { 01420 dbus_message_unref (message); 01421 return NULL; 01422 } 01423 01424 dbus_message_set_no_reply (message, TRUE); 01425 01426 if (!dbus_message_set_reply_serial (message, 01427 dbus_message_get_serial (method_call))) 01428 { 01429 dbus_message_unref (message); 01430 return NULL; 01431 } 01432 01433 return message; 01434 } 01435 01450 DBusMessage* 01451 dbus_message_new_signal (const char *path, 01452 const char *iface, 01453 const char *name) 01454 { 01455 DBusMessage *message; 01456 01457 _dbus_return_val_if_fail (path != NULL, NULL); 01458 _dbus_return_val_if_fail (iface != NULL, NULL); 01459 _dbus_return_val_if_fail (name != NULL, NULL); 01460 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01461 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL); 01462 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); 01463 01464 message = dbus_message_new_empty_header (); 01465 if (message == NULL) 01466 return NULL; 01467 01468 if (!_dbus_header_create (&message->header, 01469 DBUS_COMPILER_BYTE_ORDER, 01470 DBUS_MESSAGE_TYPE_SIGNAL, 01471 NULL, path, iface, name, NULL)) 01472 { 01473 dbus_message_unref (message); 01474 return NULL; 01475 } 01476 01477 dbus_message_set_no_reply (message, TRUE); 01478 01479 return message; 01480 } 01481 01496 DBusMessage* 01497 dbus_message_new_error (DBusMessage *reply_to, 01498 const char *error_name, 01499 const char *error_message) 01500 { 01501 DBusMessage *message; 01502 const char *sender; 01503 DBusMessageIter iter; 01504 01505 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01506 _dbus_return_val_if_fail (error_name != NULL, NULL); 01507 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01508 01509 sender = dbus_message_get_sender (reply_to); 01510 01511 /* sender may be NULL for non-message-bus case or 01512 * when the message bus is dealing with an unregistered 01513 * connection. 01514 */ 01515 message = dbus_message_new_empty_header (); 01516 if (message == NULL) 01517 return NULL; 01518 01519 if (!_dbus_header_create (&message->header, 01520 DBUS_COMPILER_BYTE_ORDER, 01521 DBUS_MESSAGE_TYPE_ERROR, 01522 sender, NULL, NULL, NULL, error_name)) 01523 { 01524 dbus_message_unref (message); 01525 return NULL; 01526 } 01527 01528 dbus_message_set_no_reply (message, TRUE); 01529 01530 if (!dbus_message_set_reply_serial (message, 01531 dbus_message_get_serial (reply_to))) 01532 { 01533 dbus_message_unref (message); 01534 return NULL; 01535 } 01536 01537 if (error_message != NULL) 01538 { 01539 dbus_message_iter_init_append (message, &iter); 01540 if (!dbus_message_iter_append_basic (&iter, 01541 DBUS_TYPE_STRING, 01542 &error_message)) 01543 { 01544 dbus_message_unref (message); 01545 return NULL; 01546 } 01547 } 01548 01549 return message; 01550 } 01551 01568 DBusMessage* 01569 dbus_message_new_error_printf (DBusMessage *reply_to, 01570 const char *error_name, 01571 const char *error_format, 01572 ...) 01573 { 01574 va_list args; 01575 DBusString str; 01576 DBusMessage *message; 01577 01578 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01579 _dbus_return_val_if_fail (error_name != NULL, NULL); 01580 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01581 01582 if (!_dbus_string_init (&str)) 01583 return NULL; 01584 01585 va_start (args, error_format); 01586 01587 if (_dbus_string_append_printf_valist (&str, error_format, args)) 01588 message = dbus_message_new_error (reply_to, error_name, 01589 _dbus_string_get_const_data (&str)); 01590 else 01591 message = NULL; 01592 01593 _dbus_string_free (&str); 01594 01595 va_end (args); 01596 01597 return message; 01598 } 01599 01600 01613 DBusMessage * 01614 dbus_message_copy (const DBusMessage *message) 01615 { 01616 DBusMessage *retval; 01617 01618 _dbus_return_val_if_fail (message != NULL, NULL); 01619 01620 retval = dbus_new0 (DBusMessage, 1); 01621 if (retval == NULL) 01622 return NULL; 01623 01624 _dbus_atomic_inc (&retval->refcount); 01625 01626 retval->locked = FALSE; 01627 #ifndef DBUS_DISABLE_CHECKS 01628 retval->generation = message->generation; 01629 #endif 01630 01631 if (!_dbus_header_copy (&message->header, &retval->header)) 01632 { 01633 dbus_free (retval); 01634 return NULL; 01635 } 01636 01637 if (!_dbus_string_init_preallocated (&retval->body, 01638 _dbus_string_get_length (&message->body))) 01639 { 01640 _dbus_header_free (&retval->header); 01641 dbus_free (retval); 01642 return NULL; 01643 } 01644 01645 if (!_dbus_string_copy (&message->body, 0, 01646 &retval->body, 0)) 01647 goto failed_copy; 01648 01649 #ifdef HAVE_UNIX_FD_PASSING 01650 retval->unix_fds = dbus_new(int, message->n_unix_fds); 01651 if (retval->unix_fds == NULL && message->n_unix_fds > 0) 01652 goto failed_copy; 01653 01654 retval->n_unix_fds_allocated = message->n_unix_fds; 01655 01656 for (retval->n_unix_fds = 0; 01657 retval->n_unix_fds < message->n_unix_fds; 01658 retval->n_unix_fds++) 01659 { 01660 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL); 01661 01662 if (retval->unix_fds[retval->n_unix_fds] < 0) 01663 goto failed_copy; 01664 } 01665 01666 #endif 01667 01668 _dbus_message_trace_ref (retval, 0, 1, "copy"); 01669 return retval; 01670 01671 failed_copy: 01672 _dbus_header_free (&retval->header); 01673 _dbus_string_free (&retval->body); 01674 01675 #ifdef HAVE_UNIX_FD_PASSING 01676 close_unix_fds(retval->unix_fds, &retval->n_unix_fds); 01677 dbus_free(retval->unix_fds); 01678 #endif 01679 01680 dbus_free (retval); 01681 01682 return NULL; 01683 } 01684 01685 01693 DBusMessage * 01694 dbus_message_ref (DBusMessage *message) 01695 { 01696 dbus_int32_t old_refcount; 01697 01698 _dbus_return_val_if_fail (message != NULL, NULL); 01699 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); 01700 _dbus_return_val_if_fail (!message->in_cache, NULL); 01701 01702 old_refcount = _dbus_atomic_inc (&message->refcount); 01703 _dbus_assert (old_refcount >= 1); 01704 _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref"); 01705 01706 return message; 01707 } 01708 01716 void 01717 dbus_message_unref (DBusMessage *message) 01718 { 01719 dbus_int32_t old_refcount; 01720 01721 _dbus_return_if_fail (message != NULL); 01722 _dbus_return_if_fail (message->generation == _dbus_current_generation); 01723 _dbus_return_if_fail (!message->in_cache); 01724 01725 old_refcount = _dbus_atomic_dec (&message->refcount); 01726 01727 _dbus_assert (old_refcount >= 1); 01728 01729 _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref"); 01730 01731 if (old_refcount == 1) 01732 { 01733 /* Calls application callbacks! */ 01734 dbus_message_cache_or_finalize (message); 01735 } 01736 } 01737 01748 int 01749 dbus_message_get_type (DBusMessage *message) 01750 { 01751 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID); 01752 01753 return _dbus_header_get_message_type (&message->header); 01754 } 01755 01818 dbus_bool_t 01819 dbus_message_append_args (DBusMessage *message, 01820 int first_arg_type, 01821 ...) 01822 { 01823 dbus_bool_t retval; 01824 va_list var_args; 01825 01826 _dbus_return_val_if_fail (message != NULL, FALSE); 01827 01828 va_start (var_args, first_arg_type); 01829 retval = dbus_message_append_args_valist (message, 01830 first_arg_type, 01831 var_args); 01832 va_end (var_args); 01833 01834 return retval; 01835 } 01836 01850 dbus_bool_t 01851 dbus_message_append_args_valist (DBusMessage *message, 01852 int first_arg_type, 01853 va_list var_args) 01854 { 01855 int type; 01856 DBusMessageIter iter; 01857 01858 _dbus_return_val_if_fail (message != NULL, FALSE); 01859 01860 type = first_arg_type; 01861 01862 dbus_message_iter_init_append (message, &iter); 01863 01864 while (type != DBUS_TYPE_INVALID) 01865 { 01866 if (dbus_type_is_basic (type)) 01867 { 01868 const DBusBasicValue *value; 01869 value = va_arg (var_args, const DBusBasicValue*); 01870 01871 if (!dbus_message_iter_append_basic (&iter, 01872 type, 01873 value)) 01874 goto failed; 01875 } 01876 else if (type == DBUS_TYPE_ARRAY) 01877 { 01878 int element_type; 01879 DBusMessageIter array; 01880 char buf[2]; 01881 01882 element_type = va_arg (var_args, int); 01883 01884 buf[0] = element_type; 01885 buf[1] = '\0'; 01886 if (!dbus_message_iter_open_container (&iter, 01887 DBUS_TYPE_ARRAY, 01888 buf, 01889 &array)) 01890 goto failed; 01891 01892 if (dbus_type_is_fixed (element_type) && 01893 element_type != DBUS_TYPE_UNIX_FD) 01894 { 01895 const DBusBasicValue **value; 01896 int n_elements; 01897 01898 value = va_arg (var_args, const DBusBasicValue**); 01899 n_elements = va_arg (var_args, int); 01900 01901 if (!dbus_message_iter_append_fixed_array (&array, 01902 element_type, 01903 value, 01904 n_elements)) { 01905 dbus_message_iter_abandon_container (&iter, &array); 01906 goto failed; 01907 } 01908 } 01909 else if (_DBUS_TYPE_IS_STRINGLIKE (element_type)) 01910 { 01911 const char ***value_p; 01912 const char **value; 01913 int n_elements; 01914 int i; 01915 01916 value_p = va_arg (var_args, const char***); 01917 n_elements = va_arg (var_args, int); 01918 01919 value = *value_p; 01920 01921 i = 0; 01922 while (i < n_elements) 01923 { 01924 if (!dbus_message_iter_append_basic (&array, 01925 element_type, 01926 &value[i])) { 01927 dbus_message_iter_abandon_container (&iter, &array); 01928 goto failed; 01929 } 01930 ++i; 01931 } 01932 } 01933 else 01934 { 01935 _dbus_warn ("arrays of %s can't be appended with %s for now\n", 01936 _dbus_type_to_string (element_type), 01937 _DBUS_FUNCTION_NAME); 01938 goto failed; 01939 } 01940 01941 if (!dbus_message_iter_close_container (&iter, &array)) 01942 goto failed; 01943 } 01944 #ifndef DBUS_DISABLE_CHECKS 01945 else 01946 { 01947 _dbus_warn ("type %s isn't supported yet in %s\n", 01948 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME); 01949 goto failed; 01950 } 01951 #endif 01952 01953 type = va_arg (var_args, int); 01954 } 01955 01956 return TRUE; 01957 01958 failed: 01959 return FALSE; 01960 } 01961 02006 dbus_bool_t 02007 dbus_message_get_args (DBusMessage *message, 02008 DBusError *error, 02009 int first_arg_type, 02010 ...) 02011 { 02012 dbus_bool_t retval; 02013 va_list var_args; 02014 02015 _dbus_return_val_if_fail (message != NULL, FALSE); 02016 _dbus_return_val_if_error_is_set (error, FALSE); 02017 02018 va_start (var_args, first_arg_type); 02019 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args); 02020 va_end (var_args); 02021 02022 return retval; 02023 } 02024 02035 dbus_bool_t 02036 dbus_message_get_args_valist (DBusMessage *message, 02037 DBusError *error, 02038 int first_arg_type, 02039 va_list var_args) 02040 { 02041 DBusMessageIter iter; 02042 02043 _dbus_return_val_if_fail (message != NULL, FALSE); 02044 _dbus_return_val_if_error_is_set (error, FALSE); 02045 02046 dbus_message_iter_init (message, &iter); 02047 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); 02048 } 02049 02050 static void 02051 _dbus_message_iter_init_common (DBusMessage *message, 02052 DBusMessageRealIter *real, 02053 int iter_type) 02054 { 02055 /* If these static assertions fail on your platform, report it as a bug. */ 02056 _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); 02057 _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <= 02058 _DBUS_ALIGNOF (DBusMessageIter)); 02059 /* A failure of these two assertions would indicate that we've broken 02060 * ABI on this platform since 1.10.0. */ 02061 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) == 02062 sizeof (DBusMessageIter)); 02063 _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) == 02064 _DBUS_ALIGNOF (DBusMessageIter)); 02065 /* If this static assertion fails, it means the DBusMessageIter struct 02066 * is not "packed", which might result in "iter = other_iter" not copying 02067 * every byte. */ 02068 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) == 02069 4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int)); 02070 02071 /* Since the iterator will read or write who-knows-what from the 02072 * message, we need to get in the right byte order 02073 */ 02074 ensure_byte_order (message); 02075 02076 real->message = message; 02077 real->changed_stamp = message->changed_stamp; 02078 real->iter_type = iter_type; 02079 real->sig_refcount = 0; 02080 } 02081 02104 dbus_bool_t 02105 dbus_message_iter_init (DBusMessage *message, 02106 DBusMessageIter *iter) 02107 { 02108 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02109 const DBusString *type_str; 02110 int type_pos; 02111 02112 _dbus_return_val_if_fail (message != NULL, FALSE); 02113 _dbus_return_val_if_fail (iter != NULL, FALSE); 02114 02115 get_const_signature (&message->header, &type_str, &type_pos); 02116 02117 _dbus_message_iter_init_common (message, real, 02118 DBUS_MESSAGE_ITER_TYPE_READER); 02119 02120 _dbus_type_reader_init (&real->u.reader, 02121 _dbus_header_get_byte_order (&message->header), 02122 type_str, type_pos, 02123 &message->body, 02124 0); 02125 02126 return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID; 02127 } 02128 02135 dbus_bool_t 02136 dbus_message_iter_has_next (DBusMessageIter *iter) 02137 { 02138 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02139 02140 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 02141 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02142 02143 return _dbus_type_reader_has_next (&real->u.reader); 02144 } 02145 02154 dbus_bool_t 02155 dbus_message_iter_next (DBusMessageIter *iter) 02156 { 02157 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02158 02159 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 02160 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02161 02162 return _dbus_type_reader_next (&real->u.reader); 02163 } 02164 02179 int 02180 dbus_message_iter_get_arg_type (DBusMessageIter *iter) 02181 { 02182 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02183 02184 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02185 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02186 02187 return _dbus_type_reader_get_current_type (&real->u.reader); 02188 } 02189 02198 int 02199 dbus_message_iter_get_element_type (DBusMessageIter *iter) 02200 { 02201 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02202 02203 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02204 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); 02205 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 02206 02207 return _dbus_type_reader_get_element_type (&real->u.reader); 02208 } 02209 02235 void 02236 dbus_message_iter_recurse (DBusMessageIter *iter, 02237 DBusMessageIter *sub) 02238 { 02239 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02240 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02241 02242 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02243 _dbus_return_if_fail (sub != NULL); 02244 02245 *real_sub = *real; 02246 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader); 02247 } 02248 02260 char * 02261 dbus_message_iter_get_signature (DBusMessageIter *iter) 02262 { 02263 const DBusString *sig; 02264 DBusString retstr; 02265 char *ret; 02266 int start, len; 02267 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02268 02269 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL); 02270 02271 if (!_dbus_string_init (&retstr)) 02272 return NULL; 02273 02274 _dbus_type_reader_get_signature (&real->u.reader, &sig, 02275 &start, &len); 02276 if (!_dbus_string_append_len (&retstr, 02277 _dbus_string_get_const_data (sig) + start, 02278 len)) 02279 return NULL; 02280 if (!_dbus_string_steal_data (&retstr, &ret)) 02281 return NULL; 02282 _dbus_string_free (&retstr); 02283 return ret; 02284 } 02285 02333 void 02334 dbus_message_iter_get_basic (DBusMessageIter *iter, 02335 void *value) 02336 { 02337 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02338 02339 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02340 _dbus_return_if_fail (value != NULL); 02341 02342 if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD) 02343 { 02344 #ifdef HAVE_UNIX_FD_PASSING 02345 DBusBasicValue idx; 02346 02347 _dbus_type_reader_read_basic(&real->u.reader, &idx); 02348 02349 if (idx.u32 >= real->message->n_unix_fds) { 02350 /* Hmm, we cannot really signal an error here, so let's make 02351 sure to return an invalid fd. */ 02352 *((int*) value) = -1; 02353 return; 02354 } 02355 02356 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL); 02357 #else 02358 *((int*) value) = -1; 02359 #endif 02360 } 02361 else 02362 { 02363 _dbus_type_reader_read_basic (&real->u.reader, 02364 value); 02365 } 02366 } 02367 02378 int 02379 dbus_message_iter_get_element_count (DBusMessageIter *iter) 02380 { 02381 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02382 DBusTypeReader array; 02383 int element_type; 02384 int n_elements = 0; 02385 02386 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02387 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader) 02388 == DBUS_TYPE_ARRAY, 0); 02389 02390 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 02391 _dbus_type_reader_recurse (&real->u.reader, &array); 02392 if (dbus_type_is_fixed (element_type)) 02393 { 02394 int alignment = _dbus_type_get_alignment (element_type); 02395 int total_len = _dbus_type_reader_get_array_length (&array); 02396 n_elements = total_len / alignment; 02397 } 02398 else 02399 { 02400 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 02401 { 02402 ++n_elements; 02403 _dbus_type_reader_next (&array); 02404 } 02405 } 02406 02407 return n_elements; 02408 } 02409 02422 int 02423 dbus_message_iter_get_array_len (DBusMessageIter *iter) 02424 { 02425 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02426 02427 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02428 02429 return _dbus_type_reader_get_array_length (&real->u.reader); 02430 } 02431 02467 void 02468 dbus_message_iter_get_fixed_array (DBusMessageIter *iter, 02469 void *value, 02470 int *n_elements) 02471 { 02472 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02473 #ifndef DBUS_DISABLE_CHECKS 02474 int subtype = _dbus_type_reader_get_current_type(&real->u.reader); 02475 02476 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02477 _dbus_return_if_fail (value != NULL); 02478 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) || 02479 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD)); 02480 #endif 02481 02482 _dbus_type_reader_read_fixed_multi (&real->u.reader, 02483 value, n_elements); 02484 } 02485 02497 void 02498 dbus_message_iter_init_append (DBusMessage *message, 02499 DBusMessageIter *iter) 02500 { 02501 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02502 02503 _dbus_return_if_fail (message != NULL); 02504 _dbus_return_if_fail (iter != NULL); 02505 02506 _dbus_message_iter_init_common (message, real, 02507 DBUS_MESSAGE_ITER_TYPE_WRITER); 02508 02509 /* We create the signature string and point iterators at it "on demand" 02510 * when a value is actually appended. That means that init() never fails 02511 * due to OOM. 02512 */ 02513 _dbus_type_writer_init_types_delayed (&real->u.writer, 02514 _dbus_header_get_byte_order (&message->header), 02515 &message->body, 02516 _dbus_string_get_length (&message->body)); 02517 } 02518 02527 static dbus_bool_t 02528 _dbus_message_iter_open_signature (DBusMessageRealIter *real) 02529 { 02530 DBusString *str; 02531 const DBusString *current_sig; 02532 int current_sig_pos; 02533 02534 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02535 02536 if (real->u.writer.type_str != NULL) 02537 { 02538 _dbus_assert (real->sig_refcount > 0); 02539 real->sig_refcount += 1; 02540 return TRUE; 02541 } 02542 02543 str = dbus_new (DBusString, 1); 02544 if (str == NULL) 02545 return FALSE; 02546 02547 if (!_dbus_header_get_field_raw (&real->message->header, 02548 DBUS_HEADER_FIELD_SIGNATURE, 02549 ¤t_sig, ¤t_sig_pos)) 02550 current_sig = NULL; 02551 02552 if (current_sig) 02553 { 02554 int current_len; 02555 02556 current_len = _dbus_string_get_byte (current_sig, current_sig_pos); 02557 current_sig_pos += 1; /* move on to sig data */ 02558 02559 if (!_dbus_string_init_preallocated (str, current_len + 4)) 02560 { 02561 dbus_free (str); 02562 return FALSE; 02563 } 02564 02565 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len, 02566 str, 0)) 02567 { 02568 _dbus_string_free (str); 02569 dbus_free (str); 02570 return FALSE; 02571 } 02572 } 02573 else 02574 { 02575 if (!_dbus_string_init_preallocated (str, 4)) 02576 { 02577 dbus_free (str); 02578 return FALSE; 02579 } 02580 } 02581 02582 real->sig_refcount = 1; 02583 02584 _dbus_type_writer_add_types (&real->u.writer, 02585 str, _dbus_string_get_length (str)); 02586 return TRUE; 02587 } 02588 02598 static dbus_bool_t 02599 _dbus_message_iter_close_signature (DBusMessageRealIter *real) 02600 { 02601 DBusString *str; 02602 const char *v_STRING; 02603 dbus_bool_t retval; 02604 02605 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02606 _dbus_assert (real->u.writer.type_str != NULL); 02607 _dbus_assert (real->sig_refcount > 0); 02608 02609 real->sig_refcount -= 1; 02610 02611 if (real->sig_refcount > 0) 02612 return TRUE; 02613 _dbus_assert (real->sig_refcount == 0); 02614 02615 retval = TRUE; 02616 02617 str = real->u.writer.type_str; 02618 02619 v_STRING = _dbus_string_get_const_data (str); 02620 if (!_dbus_header_set_field_basic (&real->message->header, 02621 DBUS_HEADER_FIELD_SIGNATURE, 02622 DBUS_TYPE_SIGNATURE, 02623 &v_STRING)) 02624 retval = FALSE; 02625 02626 _dbus_type_writer_remove_types (&real->u.writer); 02627 _dbus_string_free (str); 02628 dbus_free (str); 02629 02630 return retval; 02631 } 02632 02640 static void 02641 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real) 02642 { 02643 DBusString *str; 02644 02645 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02646 _dbus_assert (real->u.writer.type_str != NULL); 02647 _dbus_assert (real->sig_refcount > 0); 02648 02649 real->sig_refcount -= 1; 02650 02651 if (real->sig_refcount > 0) 02652 return; 02653 _dbus_assert (real->sig_refcount == 0); 02654 02655 str = real->u.writer.type_str; 02656 02657 _dbus_type_writer_remove_types (&real->u.writer); 02658 _dbus_string_free (str); 02659 dbus_free (str); 02660 } 02661 02662 #ifndef DBUS_DISABLE_CHECKS 02663 static dbus_bool_t 02664 _dbus_message_iter_append_check (DBusMessageRealIter *iter) 02665 { 02666 if (!_dbus_message_iter_check (iter)) 02667 return FALSE; 02668 02669 if (iter->message->locked) 02670 { 02671 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n"); 02672 return FALSE; 02673 } 02674 02675 return TRUE; 02676 } 02677 #endif /* DBUS_DISABLE_CHECKS */ 02678 02679 #ifdef HAVE_UNIX_FD_PASSING 02680 static int * 02681 expand_fd_array(DBusMessage *m, 02682 unsigned n) 02683 { 02684 _dbus_assert(m); 02685 02686 /* This makes space for adding n new fds to the array and returns a 02687 pointer to the place were the first fd should be put. */ 02688 02689 if (m->n_unix_fds + n > m->n_unix_fds_allocated) 02690 { 02691 unsigned k; 02692 int *p; 02693 02694 /* Make twice as much space as necessary */ 02695 k = (m->n_unix_fds + n) * 2; 02696 02697 /* Allocate at least four */ 02698 if (k < 4) 02699 k = 4; 02700 02701 p = dbus_realloc(m->unix_fds, k * sizeof(int)); 02702 if (p == NULL) 02703 return NULL; 02704 02705 m->unix_fds = p; 02706 m->n_unix_fds_allocated = k; 02707 } 02708 02709 return m->unix_fds + m->n_unix_fds; 02710 } 02711 #endif 02712 02732 dbus_bool_t 02733 dbus_message_iter_append_basic (DBusMessageIter *iter, 02734 int type, 02735 const void *value) 02736 { 02737 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02738 dbus_bool_t ret; 02739 02740 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02741 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02742 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE); 02743 _dbus_return_val_if_fail (value != NULL, FALSE); 02744 02745 #ifndef DBUS_DISABLE_CHECKS 02746 switch (type) 02747 { 02748 const char * const *string_p; 02749 const dbus_bool_t *bool_p; 02750 02751 case DBUS_TYPE_STRING: 02752 string_p = value; 02753 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE); 02754 break; 02755 02756 case DBUS_TYPE_OBJECT_PATH: 02757 string_p = value; 02758 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE); 02759 break; 02760 02761 case DBUS_TYPE_SIGNATURE: 02762 string_p = value; 02763 _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE); 02764 break; 02765 02766 case DBUS_TYPE_BOOLEAN: 02767 bool_p = value; 02768 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE); 02769 break; 02770 02771 default: 02772 { 02773 /* nothing to check, all possible values are allowed */ 02774 } 02775 } 02776 #endif 02777 02778 if (!_dbus_message_iter_open_signature (real)) 02779 return FALSE; 02780 02781 if (type == DBUS_TYPE_UNIX_FD) 02782 { 02783 #ifdef HAVE_UNIX_FD_PASSING 02784 int *fds; 02785 dbus_uint32_t u; 02786 02787 /* First step, include the fd in the fd list of this message */ 02788 if (!(fds = expand_fd_array(real->message, 1))) 02789 return FALSE; 02790 02791 *fds = _dbus_dup(*(int*) value, NULL); 02792 if (*fds < 0) 02793 return FALSE; 02794 02795 u = real->message->n_unix_fds; 02796 02797 /* Second step, write the index to the fd */ 02798 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) { 02799 _dbus_close(*fds, NULL); 02800 return FALSE; 02801 } 02802 02803 real->message->n_unix_fds += 1; 02804 u += 1; 02805 02806 /* Final step, update the header accordingly */ 02807 ret = _dbus_header_set_field_basic (&real->message->header, 02808 DBUS_HEADER_FIELD_UNIX_FDS, 02809 DBUS_TYPE_UINT32, 02810 &u); 02811 02812 /* If any of these operations fail the message is 02813 hosed. However, no memory or fds should be leaked since what 02814 has been added to message has been added to the message, and 02815 can hence be accounted for when the message is being 02816 freed. */ 02817 #else 02818 ret = FALSE; 02819 #endif 02820 } 02821 else 02822 { 02823 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02824 } 02825 02826 if (!_dbus_message_iter_close_signature (real)) 02827 ret = FALSE; 02828 02829 return ret; 02830 } 02831 02867 dbus_bool_t 02868 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02869 int element_type, 02870 const void *value, 02871 int n_elements) 02872 { 02873 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02874 dbus_bool_t ret; 02875 02876 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02877 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02878 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); 02879 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02880 _dbus_return_val_if_fail (value != NULL, FALSE); 02881 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02882 _dbus_return_val_if_fail (n_elements <= 02883 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02884 FALSE); 02885 02886 #ifndef DBUS_DISABLE_CHECKS 02887 if (element_type == DBUS_TYPE_BOOLEAN) 02888 { 02889 const dbus_bool_t * const *bools = value; 02890 int i; 02891 02892 for (i = 0; i < n_elements; i++) 02893 { 02894 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE); 02895 } 02896 } 02897 #endif 02898 02899 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02900 02901 return ret; 02902 } 02903 02925 dbus_bool_t 02926 dbus_message_iter_open_container (DBusMessageIter *iter, 02927 int type, 02928 const char *contained_signature, 02929 DBusMessageIter *sub) 02930 { 02931 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02932 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02933 DBusString contained_str; 02934 02935 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02936 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02937 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02938 _dbus_return_val_if_fail (sub != NULL, FALSE); 02939 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02940 contained_signature == NULL) || 02941 (type == DBUS_TYPE_DICT_ENTRY && 02942 contained_signature == NULL) || 02943 (type == DBUS_TYPE_VARIANT && 02944 contained_signature != NULL) || 02945 (type == DBUS_TYPE_ARRAY && 02946 contained_signature != NULL), FALSE); 02947 02948 /* this would fail if the contained_signature is a dict entry, since 02949 * dict entries are invalid signatures standalone (they must be in 02950 * an array) 02951 */ 02952 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02953 (contained_signature == NULL || 02954 _dbus_check_is_valid_signature (contained_signature)), 02955 FALSE); 02956 02957 if (!_dbus_message_iter_open_signature (real)) 02958 return FALSE; 02959 02960 *real_sub = *real; 02961 02962 if (contained_signature != NULL) 02963 { 02964 _dbus_string_init_const (&contained_str, contained_signature); 02965 02966 return _dbus_type_writer_recurse (&real->u.writer, 02967 type, 02968 &contained_str, 0, 02969 &real_sub->u.writer); 02970 } 02971 else 02972 { 02973 return _dbus_type_writer_recurse (&real->u.writer, 02974 type, 02975 NULL, 0, 02976 &real_sub->u.writer); 02977 } 02978 } 02979 02980 02994 dbus_bool_t 02995 dbus_message_iter_close_container (DBusMessageIter *iter, 02996 DBusMessageIter *sub) 02997 { 02998 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02999 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 03000 dbus_bool_t ret; 03001 03002 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 03003 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 03004 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 03005 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 03006 03007 ret = _dbus_type_writer_unrecurse (&real->u.writer, 03008 &real_sub->u.writer); 03009 03010 if (!_dbus_message_iter_close_signature (real)) 03011 ret = FALSE; 03012 03013 return ret; 03014 } 03015 03027 void 03028 dbus_message_iter_abandon_container (DBusMessageIter *iter, 03029 DBusMessageIter *sub) 03030 { 03031 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 03032 #ifndef DBUS_DISABLE_CHECKS 03033 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 03034 03035 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 03036 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 03037 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 03038 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 03039 #endif 03040 03041 _dbus_message_iter_abandon_signature (real); 03042 } 03043 03060 void 03061 dbus_message_set_no_reply (DBusMessage *message, 03062 dbus_bool_t no_reply) 03063 { 03064 _dbus_return_if_fail (message != NULL); 03065 _dbus_return_if_fail (!message->locked); 03066 03067 _dbus_header_toggle_flag (&message->header, 03068 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 03069 no_reply); 03070 } 03071 03079 dbus_bool_t 03080 dbus_message_get_no_reply (DBusMessage *message) 03081 { 03082 _dbus_return_val_if_fail (message != NULL, FALSE); 03083 03084 return _dbus_header_get_flag (&message->header, 03085 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 03086 } 03087 03102 void 03103 dbus_message_set_auto_start (DBusMessage *message, 03104 dbus_bool_t auto_start) 03105 { 03106 _dbus_return_if_fail (message != NULL); 03107 _dbus_return_if_fail (!message->locked); 03108 03109 _dbus_header_toggle_flag (&message->header, 03110 DBUS_HEADER_FLAG_NO_AUTO_START, 03111 !auto_start); 03112 } 03113 03121 dbus_bool_t 03122 dbus_message_get_auto_start (DBusMessage *message) 03123 { 03124 _dbus_return_val_if_fail (message != NULL, FALSE); 03125 03126 return !_dbus_header_get_flag (&message->header, 03127 DBUS_HEADER_FLAG_NO_AUTO_START); 03128 } 03129 03130 03143 dbus_bool_t 03144 dbus_message_set_path (DBusMessage *message, 03145 const char *object_path) 03146 { 03147 _dbus_return_val_if_fail (message != NULL, FALSE); 03148 _dbus_return_val_if_fail (!message->locked, FALSE); 03149 _dbus_return_val_if_fail (object_path == NULL || 03150 _dbus_check_is_valid_path (object_path), 03151 FALSE); 03152 03153 return set_or_delete_string_field (message, 03154 DBUS_HEADER_FIELD_PATH, 03155 DBUS_TYPE_OBJECT_PATH, 03156 object_path); 03157 } 03158 03172 const char* 03173 dbus_message_get_path (DBusMessage *message) 03174 { 03175 const char *v; 03176 03177 _dbus_return_val_if_fail (message != NULL, NULL); 03178 03179 v = NULL; /* in case field doesn't exist */ 03180 _dbus_header_get_field_basic (&message->header, 03181 DBUS_HEADER_FIELD_PATH, 03182 DBUS_TYPE_OBJECT_PATH, 03183 (void *) &v); 03184 return v; 03185 } 03186 03196 dbus_bool_t 03197 dbus_message_has_path (DBusMessage *message, 03198 const char *path) 03199 { 03200 const char *msg_path; 03201 msg_path = dbus_message_get_path (message); 03202 03203 if (msg_path == NULL) 03204 { 03205 if (path == NULL) 03206 return TRUE; 03207 else 03208 return FALSE; 03209 } 03210 03211 if (path == NULL) 03212 return FALSE; 03213 03214 if (strcmp (msg_path, path) == 0) 03215 return TRUE; 03216 03217 return FALSE; 03218 } 03219 03240 dbus_bool_t 03241 dbus_message_get_path_decomposed (DBusMessage *message, 03242 char ***path) 03243 { 03244 const char *v; 03245 03246 _dbus_return_val_if_fail (message != NULL, FALSE); 03247 _dbus_return_val_if_fail (path != NULL, FALSE); 03248 03249 *path = NULL; 03250 03251 v = dbus_message_get_path (message); 03252 if (v != NULL) 03253 { 03254 if (!_dbus_decompose_path (v, strlen (v), 03255 path, NULL)) 03256 return FALSE; 03257 } 03258 return TRUE; 03259 } 03260 03274 dbus_bool_t 03275 dbus_message_set_interface (DBusMessage *message, 03276 const char *iface) 03277 { 03278 _dbus_return_val_if_fail (message != NULL, FALSE); 03279 _dbus_return_val_if_fail (!message->locked, FALSE); 03280 _dbus_return_val_if_fail (iface == NULL || 03281 _dbus_check_is_valid_interface (iface), 03282 FALSE); 03283 03284 return set_or_delete_string_field (message, 03285 DBUS_HEADER_FIELD_INTERFACE, 03286 DBUS_TYPE_STRING, 03287 iface); 03288 } 03289 03303 const char* 03304 dbus_message_get_interface (DBusMessage *message) 03305 { 03306 const char *v; 03307 03308 _dbus_return_val_if_fail (message != NULL, NULL); 03309 03310 v = NULL; /* in case field doesn't exist */ 03311 _dbus_header_get_field_basic (&message->header, 03312 DBUS_HEADER_FIELD_INTERFACE, 03313 DBUS_TYPE_STRING, 03314 (void *) &v); 03315 return v; 03316 } 03317 03325 dbus_bool_t 03326 dbus_message_has_interface (DBusMessage *message, 03327 const char *iface) 03328 { 03329 const char *msg_interface; 03330 msg_interface = dbus_message_get_interface (message); 03331 03332 if (msg_interface == NULL) 03333 { 03334 if (iface == NULL) 03335 return TRUE; 03336 else 03337 return FALSE; 03338 } 03339 03340 if (iface == NULL) 03341 return FALSE; 03342 03343 if (strcmp (msg_interface, iface) == 0) 03344 return TRUE; 03345 03346 return FALSE; 03347 03348 } 03349 03362 dbus_bool_t 03363 dbus_message_set_member (DBusMessage *message, 03364 const char *member) 03365 { 03366 _dbus_return_val_if_fail (message != NULL, FALSE); 03367 _dbus_return_val_if_fail (!message->locked, FALSE); 03368 _dbus_return_val_if_fail (member == NULL || 03369 _dbus_check_is_valid_member (member), 03370 FALSE); 03371 03372 return set_or_delete_string_field (message, 03373 DBUS_HEADER_FIELD_MEMBER, 03374 DBUS_TYPE_STRING, 03375 member); 03376 } 03377 03389 const char* 03390 dbus_message_get_member (DBusMessage *message) 03391 { 03392 const char *v; 03393 03394 _dbus_return_val_if_fail (message != NULL, NULL); 03395 03396 v = NULL; /* in case field doesn't exist */ 03397 _dbus_header_get_field_basic (&message->header, 03398 DBUS_HEADER_FIELD_MEMBER, 03399 DBUS_TYPE_STRING, 03400 (void *) &v); 03401 return v; 03402 } 03403 03411 dbus_bool_t 03412 dbus_message_has_member (DBusMessage *message, 03413 const char *member) 03414 { 03415 const char *msg_member; 03416 msg_member = dbus_message_get_member (message); 03417 03418 if (msg_member == NULL) 03419 { 03420 if (member == NULL) 03421 return TRUE; 03422 else 03423 return FALSE; 03424 } 03425 03426 if (member == NULL) 03427 return FALSE; 03428 03429 if (strcmp (msg_member, member) == 0) 03430 return TRUE; 03431 03432 return FALSE; 03433 03434 } 03435 03447 dbus_bool_t 03448 dbus_message_set_error_name (DBusMessage *message, 03449 const char *error_name) 03450 { 03451 _dbus_return_val_if_fail (message != NULL, FALSE); 03452 _dbus_return_val_if_fail (!message->locked, FALSE); 03453 _dbus_return_val_if_fail (error_name == NULL || 03454 _dbus_check_is_valid_error_name (error_name), 03455 FALSE); 03456 03457 return set_or_delete_string_field (message, 03458 DBUS_HEADER_FIELD_ERROR_NAME, 03459 DBUS_TYPE_STRING, 03460 error_name); 03461 } 03462 03473 const char* 03474 dbus_message_get_error_name (DBusMessage *message) 03475 { 03476 const char *v; 03477 03478 _dbus_return_val_if_fail (message != NULL, NULL); 03479 03480 v = NULL; /* in case field doesn't exist */ 03481 _dbus_header_get_field_basic (&message->header, 03482 DBUS_HEADER_FIELD_ERROR_NAME, 03483 DBUS_TYPE_STRING, 03484 (void *) &v); 03485 return v; 03486 } 03487 03501 dbus_bool_t 03502 dbus_message_set_destination (DBusMessage *message, 03503 const char *destination) 03504 { 03505 _dbus_return_val_if_fail (message != NULL, FALSE); 03506 _dbus_return_val_if_fail (!message->locked, FALSE); 03507 _dbus_return_val_if_fail (destination == NULL || 03508 _dbus_check_is_valid_bus_name (destination), 03509 FALSE); 03510 03511 return set_or_delete_string_field (message, 03512 DBUS_HEADER_FIELD_DESTINATION, 03513 DBUS_TYPE_STRING, 03514 destination); 03515 } 03516 03526 const char* 03527 dbus_message_get_destination (DBusMessage *message) 03528 { 03529 const char *v; 03530 03531 _dbus_return_val_if_fail (message != NULL, NULL); 03532 03533 v = NULL; /* in case field doesn't exist */ 03534 _dbus_header_get_field_basic (&message->header, 03535 DBUS_HEADER_FIELD_DESTINATION, 03536 DBUS_TYPE_STRING, 03537 (void *) &v); 03538 return v; 03539 } 03540 03555 dbus_bool_t 03556 dbus_message_set_sender (DBusMessage *message, 03557 const char *sender) 03558 { 03559 _dbus_return_val_if_fail (message != NULL, FALSE); 03560 _dbus_return_val_if_fail (!message->locked, FALSE); 03561 _dbus_return_val_if_fail (sender == NULL || 03562 _dbus_check_is_valid_bus_name (sender), 03563 FALSE); 03564 03565 return set_or_delete_string_field (message, 03566 DBUS_HEADER_FIELD_SENDER, 03567 DBUS_TYPE_STRING, 03568 sender); 03569 } 03570 03586 const char* 03587 dbus_message_get_sender (DBusMessage *message) 03588 { 03589 const char *v; 03590 03591 _dbus_return_val_if_fail (message != NULL, NULL); 03592 03593 v = NULL; /* in case field doesn't exist */ 03594 _dbus_header_get_field_basic (&message->header, 03595 DBUS_HEADER_FIELD_SENDER, 03596 DBUS_TYPE_STRING, 03597 (void *) &v); 03598 return v; 03599 } 03600 03619 const char* 03620 dbus_message_get_signature (DBusMessage *message) 03621 { 03622 const DBusString *type_str; 03623 int type_pos; 03624 03625 _dbus_return_val_if_fail (message != NULL, NULL); 03626 03627 get_const_signature (&message->header, &type_str, &type_pos); 03628 03629 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03630 } 03631 03632 static dbus_bool_t 03633 _dbus_message_has_type_interface_member (DBusMessage *message, 03634 int type, 03635 const char *iface, 03636 const char *member) 03637 { 03638 const char *n; 03639 03640 _dbus_assert (message != NULL); 03641 _dbus_assert (iface != NULL); 03642 _dbus_assert (member != NULL); 03643 03644 if (dbus_message_get_type (message) != type) 03645 return FALSE; 03646 03647 /* Optimize by checking the short member name first 03648 * instead of the longer interface name 03649 */ 03650 03651 n = dbus_message_get_member (message); 03652 03653 if (n && strcmp (n, member) == 0) 03654 { 03655 n = dbus_message_get_interface (message); 03656 03657 if (n == NULL || strcmp (n, iface) == 0) 03658 return TRUE; 03659 } 03660 03661 return FALSE; 03662 } 03663 03678 dbus_bool_t 03679 dbus_message_is_method_call (DBusMessage *message, 03680 const char *iface, 03681 const char *method) 03682 { 03683 _dbus_return_val_if_fail (message != NULL, FALSE); 03684 _dbus_return_val_if_fail (iface != NULL, FALSE); 03685 _dbus_return_val_if_fail (method != NULL, FALSE); 03686 /* don't check that interface/method are valid since it would be 03687 * expensive, and not catch many common errors 03688 */ 03689 03690 return _dbus_message_has_type_interface_member (message, 03691 DBUS_MESSAGE_TYPE_METHOD_CALL, 03692 iface, method); 03693 } 03694 03706 dbus_bool_t 03707 dbus_message_is_signal (DBusMessage *message, 03708 const char *iface, 03709 const char *signal_name) 03710 { 03711 _dbus_return_val_if_fail (message != NULL, FALSE); 03712 _dbus_return_val_if_fail (iface != NULL, FALSE); 03713 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03714 /* don't check that interface/name are valid since it would be 03715 * expensive, and not catch many common errors 03716 */ 03717 03718 return _dbus_message_has_type_interface_member (message, 03719 DBUS_MESSAGE_TYPE_SIGNAL, 03720 iface, signal_name); 03721 } 03722 03733 dbus_bool_t 03734 dbus_message_is_error (DBusMessage *message, 03735 const char *error_name) 03736 { 03737 const char *n; 03738 03739 _dbus_return_val_if_fail (message != NULL, FALSE); 03740 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03741 /* don't check that error_name is valid since it would be expensive, 03742 * and not catch many common errors 03743 */ 03744 03745 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03746 return FALSE; 03747 03748 n = dbus_message_get_error_name (message); 03749 03750 if (n && strcmp (n, error_name) == 0) 03751 return TRUE; 03752 else 03753 return FALSE; 03754 } 03755 03766 dbus_bool_t 03767 dbus_message_has_destination (DBusMessage *message, 03768 const char *name) 03769 { 03770 const char *s; 03771 03772 _dbus_return_val_if_fail (message != NULL, FALSE); 03773 _dbus_return_val_if_fail (name != NULL, FALSE); 03774 /* don't check that name is valid since it would be expensive, and 03775 * not catch many common errors 03776 */ 03777 03778 s = dbus_message_get_destination (message); 03779 03780 if (s && strcmp (s, name) == 0) 03781 return TRUE; 03782 else 03783 return FALSE; 03784 } 03785 03801 dbus_bool_t 03802 dbus_message_has_sender (DBusMessage *message, 03803 const char *name) 03804 { 03805 const char *s; 03806 03807 _dbus_return_val_if_fail (message != NULL, FALSE); 03808 _dbus_return_val_if_fail (name != NULL, FALSE); 03809 /* don't check that name is valid since it would be expensive, and 03810 * not catch many common errors 03811 */ 03812 03813 s = dbus_message_get_sender (message); 03814 03815 if (s && strcmp (s, name) == 0) 03816 return TRUE; 03817 else 03818 return FALSE; 03819 } 03820 03830 dbus_bool_t 03831 dbus_message_has_signature (DBusMessage *message, 03832 const char *signature) 03833 { 03834 const char *s; 03835 03836 _dbus_return_val_if_fail (message != NULL, FALSE); 03837 _dbus_return_val_if_fail (signature != NULL, FALSE); 03838 /* don't check that signature is valid since it would be expensive, 03839 * and not catch many common errors 03840 */ 03841 03842 s = dbus_message_get_signature (message); 03843 03844 if (s && strcmp (s, signature) == 0) 03845 return TRUE; 03846 else 03847 return FALSE; 03848 } 03849 03872 dbus_bool_t 03873 dbus_set_error_from_message (DBusError *error, 03874 DBusMessage *message) 03875 { 03876 const char *str; 03877 03878 _dbus_return_val_if_fail (message != NULL, FALSE); 03879 _dbus_return_val_if_error_is_set (error, FALSE); 03880 03881 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03882 return FALSE; 03883 03884 str = NULL; 03885 dbus_message_get_args (message, NULL, 03886 DBUS_TYPE_STRING, &str, 03887 DBUS_TYPE_INVALID); 03888 03889 dbus_set_error (error, dbus_message_get_error_name (message), 03890 str ? "%s" : NULL, str); 03891 03892 return TRUE; 03893 } 03894 03901 dbus_bool_t 03902 dbus_message_contains_unix_fds(DBusMessage *message) 03903 { 03904 #ifdef HAVE_UNIX_FD_PASSING 03905 _dbus_assert(message); 03906 03907 return message->n_unix_fds > 0; 03908 #else 03909 return FALSE; 03910 #endif 03911 } 03912 03931 #define INITIAL_LOADER_DATA_LEN 32 03932 03939 DBusMessageLoader* 03940 _dbus_message_loader_new (void) 03941 { 03942 DBusMessageLoader *loader; 03943 03944 loader = dbus_new0 (DBusMessageLoader, 1); 03945 if (loader == NULL) 03946 return NULL; 03947 03948 loader->refcount = 1; 03949 03950 loader->corrupted = FALSE; 03951 loader->corruption_reason = DBUS_VALID; 03952 03953 /* this can be configured by the app, but defaults to the protocol max */ 03954 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03955 03956 /* We set a very relatively conservative default here since due to how 03957 SCM_RIGHTS works we need to preallocate an fd array of the maximum 03958 number of unix fds we want to receive in advance. A 03959 try-and-reallocate loop is not possible. */ 03960 loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS; 03961 03962 if (!_dbus_string_init (&loader->data)) 03963 { 03964 dbus_free (loader); 03965 return NULL; 03966 } 03967 03968 /* preallocate the buffer for speed, ignore failure */ 03969 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03970 _dbus_string_set_length (&loader->data, 0); 03971 03972 #ifdef HAVE_UNIX_FD_PASSING 03973 loader->unix_fds = NULL; 03974 loader->n_unix_fds = loader->n_unix_fds_allocated = 0; 03975 loader->unix_fds_outstanding = FALSE; 03976 #endif 03977 03978 return loader; 03979 } 03980 03987 DBusMessageLoader * 03988 _dbus_message_loader_ref (DBusMessageLoader *loader) 03989 { 03990 loader->refcount += 1; 03991 03992 return loader; 03993 } 03994 04001 void 04002 _dbus_message_loader_unref (DBusMessageLoader *loader) 04003 { 04004 loader->refcount -= 1; 04005 if (loader->refcount == 0) 04006 { 04007 #ifdef HAVE_UNIX_FD_PASSING 04008 close_unix_fds(loader->unix_fds, &loader->n_unix_fds); 04009 dbus_free(loader->unix_fds); 04010 #endif 04011 _dbus_list_foreach (&loader->messages, 04012 (DBusForeachFunction) dbus_message_unref, 04013 NULL); 04014 _dbus_list_clear (&loader->messages); 04015 _dbus_string_free (&loader->data); 04016 dbus_free (loader); 04017 } 04018 } 04019 04038 void 04039 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 04040 DBusString **buffer) 04041 { 04042 _dbus_assert (!loader->buffer_outstanding); 04043 04044 *buffer = &loader->data; 04045 04046 loader->buffer_outstanding = TRUE; 04047 } 04048 04058 void 04059 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 04060 DBusString *buffer) 04061 { 04062 _dbus_assert (loader->buffer_outstanding); 04063 _dbus_assert (buffer == &loader->data); 04064 04065 loader->buffer_outstanding = FALSE; 04066 } 04067 04078 dbus_bool_t 04079 _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, 04080 int **fds, 04081 unsigned *max_n_fds) 04082 { 04083 #ifdef HAVE_UNIX_FD_PASSING 04084 _dbus_assert (!loader->unix_fds_outstanding); 04085 04086 /* Allocate space where we can put the fds we read. We allocate 04087 space for max_message_unix_fds since this is an 04088 upper limit how many fds can be received within a single 04089 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic 04090 we are allocating the maximum possible array size right from the 04091 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed 04092 there is no better way. */ 04093 04094 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds) 04095 { 04096 int *a = dbus_realloc(loader->unix_fds, 04097 loader->max_message_unix_fds * sizeof(loader->unix_fds[0])); 04098 04099 if (!a) 04100 return FALSE; 04101 04102 loader->unix_fds = a; 04103 loader->n_unix_fds_allocated = loader->max_message_unix_fds; 04104 } 04105 04106 *fds = loader->unix_fds + loader->n_unix_fds; 04107 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds; 04108 04109 loader->unix_fds_outstanding = TRUE; 04110 return TRUE; 04111 #else 04112 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 04113 return FALSE; 04114 #endif 04115 } 04116 04127 void 04128 _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, 04129 int *fds, 04130 unsigned n_fds) 04131 { 04132 #ifdef HAVE_UNIX_FD_PASSING 04133 _dbus_assert(loader->unix_fds_outstanding); 04134 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds); 04135 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated); 04136 04137 loader->n_unix_fds += n_fds; 04138 loader->unix_fds_outstanding = FALSE; 04139 04140 if (n_fds && loader->unix_fds_change) 04141 loader->unix_fds_change (loader->unix_fds_change_data); 04142 #else 04143 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 04144 #endif 04145 } 04146 04147 /* 04148 * FIXME when we move the header out of the buffer, that memmoves all 04149 * buffered messages. Kind of crappy. 04150 * 04151 * Also we copy the header and body, which is kind of crappy. To 04152 * avoid this, we have to allow header and body to be in a single 04153 * memory block, which is good for messages we read and bad for 04154 * messages we are creating. But we could move_len() the buffer into 04155 * this single memory block, and move_len() will just swap the buffers 04156 * if you're moving the entire buffer replacing the dest string. 04157 * 04158 * We could also have the message loader tell the transport how many 04159 * bytes to read; so it would first ask for some arbitrary number like 04160 * 256, then if the message was incomplete it would use the 04161 * header/body len to ask for exactly the size of the message (or 04162 * blocks the size of a typical kernel buffer for the socket). That 04163 * way we don't get trailing bytes in the buffer that have to be 04164 * memmoved. Though I suppose we also don't have a chance of reading a 04165 * bunch of small messages at once, so the optimization may be stupid. 04166 * 04167 * Another approach would be to keep a "start" index into 04168 * loader->data and only delete it occasionally, instead of after 04169 * each message is loaded. 04170 * 04171 * load_message() returns FALSE if not enough memory OR the loader was corrupted 04172 */ 04173 static dbus_bool_t 04174 load_message (DBusMessageLoader *loader, 04175 DBusMessage *message, 04176 int byte_order, 04177 int fields_array_len, 04178 int header_len, 04179 int body_len) 04180 { 04181 dbus_bool_t oom; 04182 DBusValidity validity; 04183 const DBusString *type_str; 04184 int type_pos; 04185 DBusValidationMode mode; 04186 dbus_uint32_t n_unix_fds = 0; 04187 04188 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 04189 04190 oom = FALSE; 04191 04192 #if 0 04193 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 04194 #endif 04195 04196 /* 1. VALIDATE AND COPY OVER HEADER */ 04197 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 04198 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 04199 04200 if (!_dbus_header_load (&message->header, 04201 mode, 04202 &validity, 04203 byte_order, 04204 fields_array_len, 04205 header_len, 04206 body_len, 04207 &loader->data, 0, 04208 _dbus_string_get_length (&loader->data))) 04209 { 04210 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 04211 04212 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 04213 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 04214 _dbus_assert (validity != DBUS_VALID); 04215 04216 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 04217 oom = TRUE; 04218 else 04219 { 04220 loader->corrupted = TRUE; 04221 loader->corruption_reason = validity; 04222 } 04223 goto failed; 04224 } 04225 04226 _dbus_assert (validity == DBUS_VALID); 04227 04228 /* 2. VALIDATE BODY */ 04229 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 04230 { 04231 get_const_signature (&message->header, &type_str, &type_pos); 04232 04233 /* Because the bytes_remaining arg is NULL, this validates that the 04234 * body is the right length 04235 */ 04236 validity = _dbus_validate_body_with_reason (type_str, 04237 type_pos, 04238 byte_order, 04239 NULL, 04240 &loader->data, 04241 header_len, 04242 body_len); 04243 if (validity != DBUS_VALID) 04244 { 04245 _dbus_verbose ("Failed to validate message body code %d\n", validity); 04246 04247 loader->corrupted = TRUE; 04248 loader->corruption_reason = validity; 04249 04250 goto failed; 04251 } 04252 } 04253 04254 /* 3. COPY OVER UNIX FDS */ 04255 _dbus_header_get_field_basic(&message->header, 04256 DBUS_HEADER_FIELD_UNIX_FDS, 04257 DBUS_TYPE_UINT32, 04258 &n_unix_fds); 04259 04260 #ifdef HAVE_UNIX_FD_PASSING 04261 04262 if (n_unix_fds > loader->n_unix_fds) 04263 { 04264 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n", 04265 n_unix_fds, loader->n_unix_fds); 04266 04267 loader->corrupted = TRUE; 04268 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04269 goto failed; 04270 } 04271 04272 /* If this was a recycled message there might still be 04273 some memory allocated for the fds */ 04274 dbus_free(message->unix_fds); 04275 04276 if (n_unix_fds > 0) 04277 { 04278 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0])); 04279 if (message->unix_fds == NULL) 04280 { 04281 _dbus_verbose ("Failed to allocate file descriptor array\n"); 04282 oom = TRUE; 04283 goto failed; 04284 } 04285 04286 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; 04287 loader->n_unix_fds -= n_unix_fds; 04288 memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0])); 04289 04290 if (loader->unix_fds_change) 04291 loader->unix_fds_change (loader->unix_fds_change_data); 04292 } 04293 else 04294 message->unix_fds = NULL; 04295 04296 #else 04297 04298 if (n_unix_fds > 0) 04299 { 04300 _dbus_verbose ("Hmm, message claims to come with file descriptors " 04301 "but that's not supported on our platform, disconnecting.\n"); 04302 04303 loader->corrupted = TRUE; 04304 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04305 goto failed; 04306 } 04307 04308 #endif 04309 04310 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 04311 04312 if (!_dbus_list_append (&loader->messages, message)) 04313 { 04314 _dbus_verbose ("Failed to append new message to loader queue\n"); 04315 oom = TRUE; 04316 goto failed; 04317 } 04318 04319 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 04320 _dbus_assert (_dbus_string_get_length (&loader->data) >= 04321 (header_len + body_len)); 04322 04323 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 04324 { 04325 _dbus_verbose ("Failed to move body into new message\n"); 04326 oom = TRUE; 04327 goto failed; 04328 } 04329 04330 _dbus_string_delete (&loader->data, 0, header_len + body_len); 04331 04332 /* don't waste more than 2k of memory */ 04333 _dbus_string_compact (&loader->data, 2048); 04334 04335 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 04336 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 04337 04338 _dbus_verbose ("Loaded message %p\n", message); 04339 04340 _dbus_assert (!oom); 04341 _dbus_assert (!loader->corrupted); 04342 _dbus_assert (loader->messages != NULL); 04343 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04344 04345 return TRUE; 04346 04347 failed: 04348 04349 /* Clean up */ 04350 04351 /* does nothing if the message isn't in the list */ 04352 _dbus_list_remove_last (&loader->messages, message); 04353 04354 if (oom) 04355 _dbus_assert (!loader->corrupted); 04356 else 04357 _dbus_assert (loader->corrupted); 04358 04359 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 04360 04361 return FALSE; 04362 } 04363 04378 dbus_bool_t 04379 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 04380 { 04381 while (!loader->corrupted && 04382 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 04383 { 04384 DBusValidity validity; 04385 int byte_order, fields_array_len, header_len, body_len; 04386 04387 if (_dbus_header_have_message_untrusted (loader->max_message_size, 04388 &validity, 04389 &byte_order, 04390 &fields_array_len, 04391 &header_len, 04392 &body_len, 04393 &loader->data, 0, 04394 _dbus_string_get_length (&loader->data))) 04395 { 04396 DBusMessage *message; 04397 04398 _dbus_assert (validity == DBUS_VALID); 04399 04400 message = dbus_message_new_empty_header (); 04401 if (message == NULL) 04402 return FALSE; 04403 04404 if (!load_message (loader, message, 04405 byte_order, fields_array_len, 04406 header_len, body_len)) 04407 { 04408 dbus_message_unref (message); 04409 /* load_message() returns false if corrupted or OOM; if 04410 * corrupted then return TRUE for not OOM 04411 */ 04412 return loader->corrupted; 04413 } 04414 04415 _dbus_assert (loader->messages != NULL); 04416 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04417 } 04418 else 04419 { 04420 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 04421 validity); 04422 if (validity != DBUS_VALID) 04423 { 04424 loader->corrupted = TRUE; 04425 loader->corruption_reason = validity; 04426 } 04427 return TRUE; 04428 } 04429 } 04430 04431 return TRUE; 04432 } 04433 04441 DBusMessage* 04442 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 04443 { 04444 if (loader->messages) 04445 return loader->messages->data; 04446 else 04447 return NULL; 04448 } 04449 04458 DBusMessage* 04459 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 04460 { 04461 return _dbus_list_pop_first (&loader->messages); 04462 } 04463 04472 DBusList* 04473 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 04474 { 04475 return _dbus_list_pop_first_link (&loader->messages); 04476 } 04477 04484 void 04485 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 04486 DBusList *link) 04487 { 04488 _dbus_list_prepend_link (&loader->messages, link); 04489 } 04490 04500 dbus_bool_t 04501 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 04502 { 04503 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04504 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04505 return loader->corrupted; 04506 } 04507 04514 DBusValidity 04515 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 04516 { 04517 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04518 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04519 04520 return loader->corruption_reason; 04521 } 04522 04529 void 04530 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 04531 long size) 04532 { 04533 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 04534 { 04535 _dbus_verbose ("clamping requested max message size %ld to %d\n", 04536 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 04537 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 04538 } 04539 loader->max_message_size = size; 04540 } 04541 04548 long 04549 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 04550 { 04551 return loader->max_message_size; 04552 } 04553 04560 void 04561 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, 04562 long n) 04563 { 04564 if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS) 04565 { 04566 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n", 04567 n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS); 04568 n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS; 04569 } 04570 loader->max_message_unix_fds = n; 04571 } 04572 04579 long 04580 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) 04581 { 04582 return loader->max_message_unix_fds; 04583 } 04584 04590 int 04591 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader) 04592 { 04593 #ifdef HAVE_UNIX_FD_PASSING 04594 return loader->n_unix_fds; 04595 #else 04596 return 0; 04597 #endif 04598 } 04599 04608 void 04609 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader, 04610 void (* callback) (void *), 04611 void *data) 04612 { 04613 #ifdef HAVE_UNIX_FD_PASSING 04614 loader->unix_fds_change = callback; 04615 loader->unix_fds_change_data = data; 04616 #endif 04617 } 04618 04619 static DBusDataSlotAllocator slot_allocator = 04620 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots)); 04621 04636 dbus_bool_t 04637 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 04638 { 04639 return _dbus_data_slot_allocator_alloc (&slot_allocator, 04640 slot_p); 04641 } 04642 04654 void 04655 dbus_message_free_data_slot (dbus_int32_t *slot_p) 04656 { 04657 _dbus_return_if_fail (*slot_p >= 0); 04658 04659 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 04660 } 04661 04675 dbus_bool_t 04676 dbus_message_set_data (DBusMessage *message, 04677 dbus_int32_t slot, 04678 void *data, 04679 DBusFreeFunction free_data_func) 04680 { 04681 DBusFreeFunction old_free_func; 04682 void *old_data; 04683 dbus_bool_t retval; 04684 04685 _dbus_return_val_if_fail (message != NULL, FALSE); 04686 _dbus_return_val_if_fail (slot >= 0, FALSE); 04687 04688 retval = _dbus_data_slot_list_set (&slot_allocator, 04689 &message->slot_list, 04690 slot, data, free_data_func, 04691 &old_free_func, &old_data); 04692 04693 if (retval) 04694 { 04695 /* Do the actual free outside the message lock */ 04696 if (old_free_func) 04697 (* old_free_func) (old_data); 04698 } 04699 04700 return retval; 04701 } 04702 04711 void* 04712 dbus_message_get_data (DBusMessage *message, 04713 dbus_int32_t slot) 04714 { 04715 void *res; 04716 04717 _dbus_return_val_if_fail (message != NULL, NULL); 04718 04719 res = _dbus_data_slot_list_get (&slot_allocator, 04720 &message->slot_list, 04721 slot); 04722 04723 return res; 04724 } 04725 04739 int 04740 dbus_message_type_from_string (const char *type_str) 04741 { 04742 if (strcmp (type_str, "method_call") == 0) 04743 return DBUS_MESSAGE_TYPE_METHOD_CALL; 04744 if (strcmp (type_str, "method_return") == 0) 04745 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 04746 else if (strcmp (type_str, "signal") == 0) 04747 return DBUS_MESSAGE_TYPE_SIGNAL; 04748 else if (strcmp (type_str, "error") == 0) 04749 return DBUS_MESSAGE_TYPE_ERROR; 04750 else 04751 return DBUS_MESSAGE_TYPE_INVALID; 04752 } 04753 04767 const char * 04768 dbus_message_type_to_string (int type) 04769 { 04770 switch (type) 04771 { 04772 case DBUS_MESSAGE_TYPE_METHOD_CALL: 04773 return "method_call"; 04774 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 04775 return "method_return"; 04776 case DBUS_MESSAGE_TYPE_SIGNAL: 04777 return "signal"; 04778 case DBUS_MESSAGE_TYPE_ERROR: 04779 return "error"; 04780 default: 04781 return "invalid"; 04782 } 04783 } 04784 04797 dbus_bool_t 04798 dbus_message_marshal (DBusMessage *msg, 04799 char **marshalled_data_p, 04800 int *len_p) 04801 { 04802 DBusString tmp; 04803 dbus_bool_t was_locked; 04804 04805 _dbus_return_val_if_fail (msg != NULL, FALSE); 04806 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04807 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04808 04809 if (!_dbus_string_init (&tmp)) 04810 return FALSE; 04811 04812 /* Ensure the message is locked, to ensure the length header is filled in. */ 04813 was_locked = msg->locked; 04814 04815 if (!was_locked) 04816 dbus_message_lock (msg); 04817 04818 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04819 goto fail; 04820 04821 *len_p = _dbus_string_get_length (&tmp); 04822 04823 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04824 goto fail; 04825 04826 *len_p = _dbus_string_get_length (&tmp); 04827 04828 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04829 goto fail; 04830 04831 _dbus_string_free (&tmp); 04832 04833 if (!was_locked) 04834 msg->locked = FALSE; 04835 04836 return TRUE; 04837 04838 fail: 04839 _dbus_string_free (&tmp); 04840 04841 if (!was_locked) 04842 msg->locked = FALSE; 04843 04844 return FALSE; 04845 } 04846 04859 DBusMessage * 04860 dbus_message_demarshal (const char *str, 04861 int len, 04862 DBusError *error) 04863 { 04864 DBusMessageLoader *loader; 04865 DBusString *buffer; 04866 DBusMessage *msg; 04867 04868 _dbus_return_val_if_fail (str != NULL, NULL); 04869 04870 loader = _dbus_message_loader_new (); 04871 04872 if (loader == NULL) 04873 return NULL; 04874 04875 _dbus_message_loader_get_buffer (loader, &buffer); 04876 04877 if (!_dbus_string_append_len (buffer, str, len)) 04878 goto fail_oom; 04879 04880 _dbus_message_loader_return_buffer (loader, buffer); 04881 04882 if (!_dbus_message_loader_queue_messages (loader)) 04883 goto fail_oom; 04884 04885 if (_dbus_message_loader_get_is_corrupted (loader)) 04886 goto fail_corrupt; 04887 04888 msg = _dbus_message_loader_pop_message (loader); 04889 04890 if (!msg) 04891 goto fail_oom; 04892 04893 _dbus_message_loader_unref (loader); 04894 return msg; 04895 04896 fail_corrupt: 04897 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04898 _dbus_validity_to_error_message (loader->corruption_reason)); 04899 _dbus_message_loader_unref (loader); 04900 return NULL; 04901 04902 fail_oom: 04903 _DBUS_SET_OOM (error); 04904 _dbus_message_loader_unref (loader); 04905 return NULL; 04906 } 04907 04920 int 04921 dbus_message_demarshal_bytes_needed(const char *buf, 04922 int len) 04923 { 04924 DBusString str; 04925 int byte_order, fields_array_len, header_len, body_len; 04926 DBusValidity validity = DBUS_VALID; 04927 int have_message; 04928 04929 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04930 return 0; 04931 04932 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04933 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04934 _dbus_string_init_const_len (&str, buf, len); 04935 04936 validity = DBUS_VALID; 04937 have_message 04938 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04939 &validity, &byte_order, 04940 &fields_array_len, 04941 &header_len, 04942 &body_len, 04943 &str, 0, 04944 len); 04945 _dbus_string_free (&str); 04946 04947 if (validity == DBUS_VALID) 04948 { 04949 _dbus_assert (have_message || (header_len + body_len) > len); 04950 (void) have_message; /* unused unless asserting */ 04951 return header_len + body_len; 04952 } 04953 else 04954 { 04955 return -1; /* broken! */ 04956 } 04957 } 04958 04980 void 04981 dbus_message_set_allow_interactive_authorization (DBusMessage *message, 04982 dbus_bool_t allow) 04983 { 04984 _dbus_return_if_fail (message != NULL); 04985 _dbus_return_if_fail (!message->locked); 04986 04987 _dbus_header_toggle_flag (&message->header, 04988 DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION, 04989 allow); 04990 } 04991 04998 dbus_bool_t 04999 dbus_message_get_allow_interactive_authorization (DBusMessage *message) 05000 { 05001 _dbus_return_val_if_fail (message != NULL, FALSE); 05002 05003 return _dbus_header_get_flag (&message->header, 05004 DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION); 05005 } 05006 05009 /* tests in dbus-message-util.c */