|
D-Bus
1.8.20
|
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 00139 static void 00140 get_const_signature (DBusHeader *header, 00141 const DBusString **type_str_p, 00142 int *type_pos_p) 00143 { 00144 if (_dbus_header_get_field_raw (header, 00145 DBUS_HEADER_FIELD_SIGNATURE, 00146 type_str_p, 00147 type_pos_p)) 00148 { 00149 *type_pos_p += 1; /* skip the signature length which is 1 byte */ 00150 } 00151 else 00152 { 00153 *type_str_p = &_dbus_empty_signature_str; 00154 *type_pos_p = 0; 00155 } 00156 } 00157 00163 static void 00164 _dbus_message_byteswap (DBusMessage *message) 00165 { 00166 const DBusString *type_str; 00167 int type_pos; 00168 char byte_order; 00169 00170 byte_order = _dbus_header_get_byte_order (&message->header); 00171 00172 if (byte_order == DBUS_COMPILER_BYTE_ORDER) 00173 return; 00174 00175 _dbus_verbose ("Swapping message into compiler byte order\n"); 00176 00177 get_const_signature (&message->header, &type_str, &type_pos); 00178 00179 _dbus_marshal_byteswap (type_str, type_pos, 00180 byte_order, 00181 DBUS_COMPILER_BYTE_ORDER, 00182 &message->body, 0); 00183 00184 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER); 00185 _dbus_assert (_dbus_header_get_byte_order (&message->header) == 00186 DBUS_COMPILER_BYTE_ORDER); 00187 } 00188 00195 #define ensure_byte_order(message) _dbus_message_byteswap (message) 00196 00207 void 00208 _dbus_message_get_network_data (DBusMessage *message, 00209 const DBusString **header, 00210 const DBusString **body) 00211 { 00212 _dbus_assert (message->locked); 00213 00214 *header = &message->header.data; 00215 *body = &message->body; 00216 } 00217 00227 void _dbus_message_get_unix_fds(DBusMessage *message, 00228 const int **fds, 00229 unsigned *n_fds) 00230 { 00231 _dbus_assert (message->locked); 00232 00233 #ifdef HAVE_UNIX_FD_PASSING 00234 *fds = message->unix_fds; 00235 *n_fds = message->n_unix_fds; 00236 #else 00237 *fds = NULL; 00238 *n_fds = 0; 00239 #endif 00240 } 00241 00253 void 00254 dbus_message_set_serial (DBusMessage *message, 00255 dbus_uint32_t serial) 00256 { 00257 _dbus_return_if_fail (message != NULL); 00258 _dbus_return_if_fail (!message->locked); 00259 00260 _dbus_header_set_serial (&message->header, serial); 00261 } 00262 00279 void 00280 _dbus_message_add_counter_link (DBusMessage *message, 00281 DBusList *link) 00282 { 00283 /* right now we don't recompute the delta when message 00284 * size changes, and that's OK for current purposes 00285 * I think, but could be important to change later. 00286 * Do recompute it whenever there are no outstanding counters, 00287 * since it's basically free. 00288 */ 00289 if (message->counters == NULL) 00290 { 00291 message->size_counter_delta = 00292 _dbus_string_get_length (&message->header.data) + 00293 _dbus_string_get_length (&message->body); 00294 00295 #ifdef HAVE_UNIX_FD_PASSING 00296 message->unix_fd_counter_delta = message->n_unix_fds; 00297 #endif 00298 00299 #if 0 00300 _dbus_verbose ("message has size %ld\n", 00301 message->size_counter_delta); 00302 #endif 00303 } 00304 00305 _dbus_list_append_link (&message->counters, link); 00306 00307 _dbus_counter_adjust_size (link->data, message->size_counter_delta); 00308 00309 #ifdef HAVE_UNIX_FD_PASSING 00310 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta); 00311 #endif 00312 } 00313 00328 dbus_bool_t 00329 _dbus_message_add_counter (DBusMessage *message, 00330 DBusCounter *counter) 00331 { 00332 DBusList *link; 00333 00334 link = _dbus_list_alloc_link (counter); 00335 if (link == NULL) 00336 return FALSE; 00337 00338 _dbus_counter_ref (counter); 00339 _dbus_message_add_counter_link (message, link); 00340 00341 return TRUE; 00342 } 00343 00351 void 00352 _dbus_message_remove_counter (DBusMessage *message, 00353 DBusCounter *counter) 00354 { 00355 DBusList *link; 00356 00357 link = _dbus_list_find_last (&message->counters, 00358 counter); 00359 _dbus_assert (link != NULL); 00360 00361 _dbus_list_remove_link (&message->counters, link); 00362 00363 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00364 00365 #ifdef HAVE_UNIX_FD_PASSING 00366 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00367 #endif 00368 00369 _dbus_counter_notify (counter); 00370 _dbus_counter_unref (counter); 00371 } 00372 00383 void 00384 dbus_message_lock (DBusMessage *message) 00385 { 00386 if (!message->locked) 00387 { 00388 _dbus_header_update_lengths (&message->header, 00389 _dbus_string_get_length (&message->body)); 00390 00391 /* must have a signature if you have a body */ 00392 _dbus_assert (_dbus_string_get_length (&message->body) == 0 || 00393 dbus_message_get_signature (message) != NULL); 00394 00395 message->locked = TRUE; 00396 } 00397 } 00398 00399 static dbus_bool_t 00400 set_or_delete_string_field (DBusMessage *message, 00401 int field, 00402 int typecode, 00403 const char *value) 00404 { 00405 if (value == NULL) 00406 return _dbus_header_delete_field (&message->header, field); 00407 else 00408 return _dbus_header_set_field_basic (&message->header, 00409 field, 00410 typecode, 00411 &value); 00412 } 00413 00414 #if 0 00415 /* Probably we don't need to use this */ 00439 static dbus_bool_t 00440 _dbus_message_set_signature (DBusMessage *message, 00441 const char *signature) 00442 { 00443 _dbus_return_val_if_fail (message != NULL, FALSE); 00444 _dbus_return_val_if_fail (!message->locked, FALSE); 00445 _dbus_return_val_if_fail (signature == NULL || 00446 _dbus_check_is_valid_signature (signature)); 00447 /* can't delete the signature if you have a message body */ 00448 _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || 00449 signature != NULL); 00450 00451 return set_or_delete_string_field (message, 00452 DBUS_HEADER_FIELD_SIGNATURE, 00453 DBUS_TYPE_SIGNATURE, 00454 signature); 00455 } 00456 #endif 00457 00458 /* Message Cache 00459 * 00460 * We cache some DBusMessage to reduce the overhead of allocating 00461 * them. In my profiling this consistently made about an 8% 00462 * difference. It avoids the malloc for the message, the malloc for 00463 * the slot list, the malloc for the header string and body string, 00464 * and the associated free() calls. It does introduce another global 00465 * lock which could be a performance issue in certain cases. 00466 * 00467 * For the echo client/server the round trip time goes from around 00468 * .000077 to .000069 with the message cache on my laptop. The sysprof 00469 * change is as follows (numbers are cumulative percentage): 00470 * 00471 * with message cache implemented as array as it is now (0.000069 per): 00472 * new_empty_header 1.46 00473 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache) 00474 * mutex_unlock 0.25 00475 * self 0.41 00476 * unref 2.24 00477 * self 0.68 00478 * list_clear 0.43 00479 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache) 00480 * mutex_unlock 0.25 00481 * 00482 * with message cache implemented as list (0.000070 per roundtrip): 00483 * new_empty_header 2.72 00484 * list_pop_first 1.88 00485 * unref 3.3 00486 * list_prepend 1.63 00487 * 00488 * without cache (0.000077 per roundtrip): 00489 * new_empty_header 6.7 00490 * string_init_preallocated 3.43 00491 * dbus_malloc 2.43 00492 * dbus_malloc0 2.59 00493 * 00494 * unref 4.02 00495 * string_free 1.82 00496 * dbus_free 1.63 00497 * dbus_free 0.71 00498 * 00499 * If you implement the message_cache with a list, the primary reason 00500 * it's slower is that you add another thread lock (on the DBusList 00501 * mempool). 00502 */ 00503 00505 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE 00506 00508 #define MAX_MESSAGE_CACHE_SIZE 5 00509 00510 /* Protected by _DBUS_LOCK (message_cache) */ 00511 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; 00512 static int message_cache_count = 0; 00513 static dbus_bool_t message_cache_shutdown_registered = FALSE; 00514 00515 static void 00516 dbus_message_cache_shutdown (void *data) 00517 { 00518 int i; 00519 00520 if (!_DBUS_LOCK (message_cache)) 00521 _dbus_assert_not_reached ("we would have initialized global locks " 00522 "before registering a shutdown function"); 00523 00524 i = 0; 00525 while (i < MAX_MESSAGE_CACHE_SIZE) 00526 { 00527 if (message_cache[i]) 00528 dbus_message_finalize (message_cache[i]); 00529 00530 ++i; 00531 } 00532 00533 message_cache_count = 0; 00534 message_cache_shutdown_registered = FALSE; 00535 00536 _DBUS_UNLOCK (message_cache); 00537 } 00538 00546 static DBusMessage* 00547 dbus_message_get_cached (void) 00548 { 00549 DBusMessage *message; 00550 int i; 00551 00552 message = NULL; 00553 00554 if (!_DBUS_LOCK (message_cache)) 00555 { 00556 /* we'd have initialized global locks before caching anything, 00557 * so there can't be anything in the cache */ 00558 return NULL; 00559 } 00560 00561 _dbus_assert (message_cache_count >= 0); 00562 00563 if (message_cache_count == 0) 00564 { 00565 _DBUS_UNLOCK (message_cache); 00566 return NULL; 00567 } 00568 00569 /* This is not necessarily true unless count > 0, and 00570 * message_cache is uninitialized until the shutdown is 00571 * registered 00572 */ 00573 _dbus_assert (message_cache_shutdown_registered); 00574 00575 i = 0; 00576 while (i < MAX_MESSAGE_CACHE_SIZE) 00577 { 00578 if (message_cache[i]) 00579 { 00580 message = message_cache[i]; 00581 message_cache[i] = NULL; 00582 message_cache_count -= 1; 00583 break; 00584 } 00585 ++i; 00586 } 00587 _dbus_assert (message_cache_count >= 0); 00588 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00589 _dbus_assert (message != NULL); 00590 00591 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00592 00593 _dbus_assert (message->counters == NULL); 00594 00595 _DBUS_UNLOCK (message_cache); 00596 00597 return message; 00598 } 00599 00600 #ifdef HAVE_UNIX_FD_PASSING 00601 static void 00602 close_unix_fds(int *fds, unsigned *n_fds) 00603 { 00604 DBusError e; 00605 int i; 00606 00607 if (*n_fds <= 0) 00608 return; 00609 00610 dbus_error_init(&e); 00611 00612 for (i = 0; i < *n_fds; i++) 00613 { 00614 if (!_dbus_close(fds[i], &e)) 00615 { 00616 _dbus_warn("Failed to close file descriptor: %s\n", e.message); 00617 dbus_error_free(&e); 00618 } 00619 } 00620 00621 *n_fds = 0; 00622 00623 /* We don't free the array here, in case we can recycle it later */ 00624 } 00625 #endif 00626 00627 static void 00628 free_counter (void *element, 00629 void *data) 00630 { 00631 DBusCounter *counter = element; 00632 DBusMessage *message = data; 00633 00634 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00635 #ifdef HAVE_UNIX_FD_PASSING 00636 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00637 #endif 00638 00639 _dbus_counter_notify (counter); 00640 _dbus_counter_unref (counter); 00641 } 00642 00648 static void 00649 dbus_message_cache_or_finalize (DBusMessage *message) 00650 { 00651 dbus_bool_t was_cached; 00652 int i; 00653 00654 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00655 00656 /* This calls application code and has to be done first thing 00657 * without holding the lock 00658 */ 00659 _dbus_data_slot_list_clear (&message->slot_list); 00660 00661 _dbus_list_foreach (&message->counters, 00662 free_counter, message); 00663 _dbus_list_clear (&message->counters); 00664 00665 #ifdef HAVE_UNIX_FD_PASSING 00666 close_unix_fds(message->unix_fds, &message->n_unix_fds); 00667 #endif 00668 00669 was_cached = FALSE; 00670 00671 if (!_DBUS_LOCK (message_cache)) 00672 { 00673 /* The only way to get a non-null message goes through 00674 * dbus_message_get_cached() which takes the lock. */ 00675 _dbus_assert_not_reached ("we would have initialized global locks " 00676 "the first time we constructed a message"); 00677 } 00678 00679 if (!message_cache_shutdown_registered) 00680 { 00681 _dbus_assert (message_cache_count == 0); 00682 00683 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL)) 00684 goto out; 00685 00686 i = 0; 00687 while (i < MAX_MESSAGE_CACHE_SIZE) 00688 { 00689 message_cache[i] = NULL; 00690 ++i; 00691 } 00692 00693 message_cache_shutdown_registered = TRUE; 00694 } 00695 00696 _dbus_assert (message_cache_count >= 0); 00697 00698 if (!_dbus_enable_message_cache ()) 00699 goto out; 00700 00701 if ((_dbus_string_get_length (&message->header.data) + 00702 _dbus_string_get_length (&message->body)) > 00703 MAX_MESSAGE_SIZE_TO_CACHE) 00704 goto out; 00705 00706 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE) 00707 goto out; 00708 00709 /* Find empty slot */ 00710 i = 0; 00711 while (message_cache[i] != NULL) 00712 ++i; 00713 00714 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00715 00716 _dbus_assert (message_cache[i] == NULL); 00717 message_cache[i] = message; 00718 message_cache_count += 1; 00719 was_cached = TRUE; 00720 #ifndef DBUS_DISABLE_CHECKS 00721 message->in_cache = TRUE; 00722 #endif 00723 00724 out: 00725 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00726 00727 _DBUS_UNLOCK (message_cache); 00728 00729 if (!was_cached) 00730 dbus_message_finalize (message); 00731 } 00732 00733 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT) 00734 static dbus_bool_t 00735 _dbus_message_iter_check (DBusMessageRealIter *iter) 00736 { 00737 char byte_order; 00738 00739 if (iter == NULL) 00740 { 00741 _dbus_warn_check_failed ("dbus message iterator is NULL\n"); 00742 return FALSE; 00743 } 00744 00745 byte_order = _dbus_header_get_byte_order (&iter->message->header); 00746 00747 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER) 00748 { 00749 if (iter->u.reader.byte_order != byte_order) 00750 { 00751 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n"); 00752 return FALSE; 00753 } 00754 /* because we swap the message into compiler order when you init an iter */ 00755 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); 00756 } 00757 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) 00758 { 00759 if (iter->u.writer.byte_order != byte_order) 00760 { 00761 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n"); 00762 return FALSE; 00763 } 00764 /* because we swap the message into compiler order when you init an iter */ 00765 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); 00766 } 00767 else 00768 { 00769 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n"); 00770 return FALSE; 00771 } 00772 00773 if (iter->changed_stamp != iter->message->changed_stamp) 00774 { 00775 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); 00776 return FALSE; 00777 } 00778 00779 return TRUE; 00780 } 00781 #endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */ 00782 00795 dbus_bool_t 00796 _dbus_message_iter_get_args_valist (DBusMessageIter *iter, 00797 DBusError *error, 00798 int first_arg_type, 00799 va_list var_args) 00800 { 00801 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 00802 int spec_type, msg_type, i, j; 00803 dbus_bool_t retval; 00804 va_list copy_args; 00805 00806 _dbus_assert (_dbus_message_iter_check (real)); 00807 00808 retval = FALSE; 00809 00810 spec_type = first_arg_type; 00811 i = 0; 00812 00813 /* copy var_args first, then we can do another iteration over it to 00814 * free memory and close unix fds if parse failed at some point. 00815 */ 00816 DBUS_VA_COPY (copy_args, var_args); 00817 00818 while (spec_type != DBUS_TYPE_INVALID) 00819 { 00820 msg_type = dbus_message_iter_get_arg_type (iter); 00821 00822 if (msg_type != spec_type) 00823 { 00824 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00825 "Argument %d is specified to be of type \"%s\", but " 00826 "is actually of type \"%s\"\n", i, 00827 _dbus_type_to_string (spec_type), 00828 _dbus_type_to_string (msg_type)); 00829 00830 goto out; 00831 } 00832 00833 if (spec_type == DBUS_TYPE_UNIX_FD) 00834 { 00835 #ifdef HAVE_UNIX_FD_PASSING 00836 DBusBasicValue idx; 00837 int *pfd, nfd; 00838 00839 pfd = va_arg (var_args, int*); 00840 _dbus_assert(pfd); 00841 00842 _dbus_type_reader_read_basic(&real->u.reader, &idx); 00843 00844 if (idx.u32 >= real->message->n_unix_fds) 00845 { 00846 dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE, 00847 "Message refers to file descriptor at index %i," 00848 "but has only %i descriptors attached.\n", 00849 idx.u32, 00850 real->message->n_unix_fds); 00851 goto out; 00852 } 00853 00854 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0) 00855 goto out; 00856 00857 *pfd = nfd; 00858 #else 00859 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00860 "Platform does not support file desciptor passing.\n"); 00861 goto out; 00862 #endif 00863 } 00864 else if (dbus_type_is_basic (spec_type)) 00865 { 00866 DBusBasicValue *ptr; 00867 00868 ptr = va_arg (var_args, DBusBasicValue*); 00869 00870 _dbus_assert (ptr != NULL); 00871 00872 _dbus_type_reader_read_basic (&real->u.reader, 00873 ptr); 00874 } 00875 else if (spec_type == DBUS_TYPE_ARRAY) 00876 { 00877 int element_type; 00878 int spec_element_type; 00879 const DBusBasicValue **ptr; 00880 int *n_elements_p; 00881 DBusTypeReader array; 00882 00883 spec_element_type = va_arg (var_args, int); 00884 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 00885 00886 if (spec_element_type != element_type) 00887 { 00888 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00889 "Argument %d is specified to be an array of \"%s\", but " 00890 "is actually an array of \"%s\"\n", 00891 i, 00892 _dbus_type_to_string (spec_element_type), 00893 _dbus_type_to_string (element_type)); 00894 00895 goto out; 00896 } 00897 00898 if (dbus_type_is_fixed (spec_element_type) && 00899 element_type != DBUS_TYPE_UNIX_FD) 00900 { 00901 ptr = va_arg (var_args, const DBusBasicValue**); 00902 n_elements_p = va_arg (var_args, int*); 00903 00904 _dbus_assert (ptr != NULL); 00905 _dbus_assert (n_elements_p != NULL); 00906 00907 _dbus_type_reader_recurse (&real->u.reader, &array); 00908 00909 _dbus_type_reader_read_fixed_multi (&array, 00910 (void *) ptr, n_elements_p); 00911 } 00912 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type)) 00913 { 00914 char ***str_array_p; 00915 int n_elements; 00916 char **str_array; 00917 00918 str_array_p = va_arg (var_args, char***); 00919 n_elements_p = va_arg (var_args, int*); 00920 00921 _dbus_assert (str_array_p != NULL); 00922 _dbus_assert (n_elements_p != NULL); 00923 00924 /* Count elements in the array */ 00925 _dbus_type_reader_recurse (&real->u.reader, &array); 00926 00927 n_elements = 0; 00928 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 00929 { 00930 ++n_elements; 00931 _dbus_type_reader_next (&array); 00932 } 00933 00934 str_array = dbus_new0 (char*, n_elements + 1); 00935 if (str_array == NULL) 00936 { 00937 _DBUS_SET_OOM (error); 00938 goto out; 00939 } 00940 00941 /* Now go through and dup each string */ 00942 _dbus_type_reader_recurse (&real->u.reader, &array); 00943 00944 j = 0; 00945 while (j < n_elements) 00946 { 00947 const char *s; 00948 _dbus_type_reader_read_basic (&array, 00949 (void *) &s); 00950 00951 str_array[j] = _dbus_strdup (s); 00952 if (str_array[j] == NULL) 00953 { 00954 dbus_free_string_array (str_array); 00955 _DBUS_SET_OOM (error); 00956 goto out; 00957 } 00958 00959 ++j; 00960 00961 if (!_dbus_type_reader_next (&array)) 00962 _dbus_assert (j == n_elements); 00963 } 00964 00965 _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); 00966 _dbus_assert (j == n_elements); 00967 _dbus_assert (str_array[j] == NULL); 00968 00969 *str_array_p = str_array; 00970 *n_elements_p = n_elements; 00971 } 00972 #ifndef DBUS_DISABLE_CHECKS 00973 else 00974 { 00975 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", 00976 _DBUS_FUNCTION_NAME); 00977 goto out; 00978 } 00979 #endif 00980 } 00981 #ifndef DBUS_DISABLE_CHECKS 00982 else 00983 { 00984 _dbus_warn ("you can only read arrays and basic types with %s for now\n", 00985 _DBUS_FUNCTION_NAME); 00986 goto out; 00987 } 00988 #endif 00989 00990 /* how many arguments already handled */ 00991 i++; 00992 00993 spec_type = va_arg (var_args, int); 00994 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) 00995 { 00996 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00997 "Message has only %d arguments, but more were expected", i); 00998 goto out; 00999 } 01000 } 01001 01002 retval = TRUE; 01003 01004 out: 01005 /* there may memory or unix fd leak in the above iteration if parse failed. 01006 * so we have another iteration over copy_args to free memory and close 01007 * unix fds. 01008 */ 01009 if (!retval) 01010 { 01011 spec_type = first_arg_type; 01012 j = 0; 01013 01014 while (j < i) 01015 { 01016 if (spec_type == DBUS_TYPE_UNIX_FD) 01017 { 01018 #ifdef HAVE_UNIX_FD_PASSING 01019 int *pfd; 01020 01021 pfd = va_arg (copy_args, int *); 01022 _dbus_assert(pfd); 01023 if (*pfd >= 0) 01024 { 01025 _dbus_close (*pfd, NULL); 01026 *pfd = -1; 01027 } 01028 #endif 01029 } 01030 else if (dbus_type_is_basic (spec_type)) 01031 { 01032 /* move the index forward */ 01033 va_arg (copy_args, DBusBasicValue *); 01034 } 01035 else if (spec_type == DBUS_TYPE_ARRAY) 01036 { 01037 int spec_element_type; 01038 01039 spec_element_type = va_arg (copy_args, int); 01040 if (dbus_type_is_fixed (spec_element_type)) 01041 { 01042 /* move the index forward */ 01043 va_arg (copy_args, const DBusBasicValue **); 01044 va_arg (copy_args, int *); 01045 } 01046 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type)) 01047 { 01048 char ***str_array_p; 01049 01050 str_array_p = va_arg (copy_args, char ***); 01051 /* move the index forward */ 01052 va_arg (copy_args, int *); 01053 _dbus_assert (str_array_p != NULL); 01054 dbus_free_string_array (*str_array_p); 01055 *str_array_p = NULL; 01056 } 01057 } 01058 01059 spec_type = va_arg (copy_args, int); 01060 j++; 01061 } 01062 } 01063 01064 va_end (copy_args); 01065 return retval; 01066 } 01067 01126 dbus_uint32_t 01127 dbus_message_get_serial (DBusMessage *message) 01128 { 01129 _dbus_return_val_if_fail (message != NULL, 0); 01130 01131 return _dbus_header_get_serial (&message->header); 01132 } 01133 01142 dbus_bool_t 01143 dbus_message_set_reply_serial (DBusMessage *message, 01144 dbus_uint32_t reply_serial) 01145 { 01146 _dbus_return_val_if_fail (message != NULL, FALSE); 01147 _dbus_return_val_if_fail (!message->locked, FALSE); 01148 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */ 01149 01150 return _dbus_header_set_field_basic (&message->header, 01151 DBUS_HEADER_FIELD_REPLY_SERIAL, 01152 DBUS_TYPE_UINT32, 01153 &reply_serial); 01154 } 01155 01162 dbus_uint32_t 01163 dbus_message_get_reply_serial (DBusMessage *message) 01164 { 01165 dbus_uint32_t v_UINT32; 01166 01167 _dbus_return_val_if_fail (message != NULL, 0); 01168 01169 if (_dbus_header_get_field_basic (&message->header, 01170 DBUS_HEADER_FIELD_REPLY_SERIAL, 01171 DBUS_TYPE_UINT32, 01172 &v_UINT32)) 01173 return v_UINT32; 01174 else 01175 return 0; 01176 } 01177 01178 static void 01179 dbus_message_finalize (DBusMessage *message) 01180 { 01181 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01182 01183 /* This calls application callbacks! */ 01184 _dbus_data_slot_list_free (&message->slot_list); 01185 01186 _dbus_list_foreach (&message->counters, 01187 free_counter, message); 01188 _dbus_list_clear (&message->counters); 01189 01190 _dbus_header_free (&message->header); 01191 _dbus_string_free (&message->body); 01192 01193 #ifdef HAVE_UNIX_FD_PASSING 01194 close_unix_fds(message->unix_fds, &message->n_unix_fds); 01195 dbus_free(message->unix_fds); 01196 #endif 01197 01198 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01199 01200 dbus_free (message); 01201 } 01202 01203 static DBusMessage* 01204 dbus_message_new_empty_header (void) 01205 { 01206 DBusMessage *message; 01207 dbus_bool_t from_cache; 01208 01209 message = dbus_message_get_cached (); 01210 01211 if (message != NULL) 01212 { 01213 from_cache = TRUE; 01214 } 01215 else 01216 { 01217 from_cache = FALSE; 01218 message = dbus_new0 (DBusMessage, 1); 01219 if (message == NULL) 01220 return NULL; 01221 #ifndef DBUS_DISABLE_CHECKS 01222 message->generation = _dbus_current_generation; 01223 #endif 01224 01225 #ifdef HAVE_UNIX_FD_PASSING 01226 message->unix_fds = NULL; 01227 message->n_unix_fds_allocated = 0; 01228 #endif 01229 } 01230 01231 _dbus_atomic_inc (&message->refcount); 01232 01233 _dbus_message_trace_ref (message, 0, 1, "new_empty_header"); 01234 01235 message->locked = FALSE; 01236 #ifndef DBUS_DISABLE_CHECKS 01237 message->in_cache = FALSE; 01238 #endif 01239 message->counters = NULL; 01240 message->size_counter_delta = 0; 01241 message->changed_stamp = 0; 01242 01243 #ifdef HAVE_UNIX_FD_PASSING 01244 message->n_unix_fds = 0; 01245 message->n_unix_fds_allocated = 0; 01246 message->unix_fd_counter_delta = 0; 01247 #endif 01248 01249 if (!from_cache) 01250 _dbus_data_slot_list_init (&message->slot_list); 01251 01252 if (from_cache) 01253 { 01254 _dbus_header_reinit (&message->header); 01255 _dbus_string_set_length (&message->body, 0); 01256 } 01257 else 01258 { 01259 if (!_dbus_header_init (&message->header)) 01260 { 01261 dbus_free (message); 01262 return NULL; 01263 } 01264 01265 if (!_dbus_string_init_preallocated (&message->body, 32)) 01266 { 01267 _dbus_header_free (&message->header); 01268 dbus_free (message); 01269 return NULL; 01270 } 01271 } 01272 01273 return message; 01274 } 01275 01288 DBusMessage* 01289 dbus_message_new (int message_type) 01290 { 01291 DBusMessage *message; 01292 01293 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL); 01294 01295 message = dbus_message_new_empty_header (); 01296 if (message == NULL) 01297 return NULL; 01298 01299 if (!_dbus_header_create (&message->header, 01300 DBUS_COMPILER_BYTE_ORDER, 01301 message_type, 01302 NULL, NULL, NULL, NULL, NULL)) 01303 { 01304 dbus_message_unref (message); 01305 return NULL; 01306 } 01307 01308 return message; 01309 } 01310 01332 DBusMessage* 01333 dbus_message_new_method_call (const char *destination, 01334 const char *path, 01335 const char *iface, 01336 const char *method) 01337 { 01338 DBusMessage *message; 01339 01340 _dbus_return_val_if_fail (path != NULL, NULL); 01341 _dbus_return_val_if_fail (method != NULL, NULL); 01342 _dbus_return_val_if_fail (destination == NULL || 01343 _dbus_check_is_valid_bus_name (destination), NULL); 01344 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01345 _dbus_return_val_if_fail (iface == NULL || 01346 _dbus_check_is_valid_interface (iface), NULL); 01347 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); 01348 01349 message = dbus_message_new_empty_header (); 01350 if (message == NULL) 01351 return NULL; 01352 01353 if (!_dbus_header_create (&message->header, 01354 DBUS_COMPILER_BYTE_ORDER, 01355 DBUS_MESSAGE_TYPE_METHOD_CALL, 01356 destination, path, iface, method, NULL)) 01357 { 01358 dbus_message_unref (message); 01359 return NULL; 01360 } 01361 01362 return message; 01363 } 01364 01372 DBusMessage* 01373 dbus_message_new_method_return (DBusMessage *method_call) 01374 { 01375 DBusMessage *message; 01376 const char *sender; 01377 01378 _dbus_return_val_if_fail (method_call != NULL, NULL); 01379 01380 sender = dbus_message_get_sender (method_call); 01381 01382 /* sender is allowed to be null here in peer-to-peer case */ 01383 01384 message = dbus_message_new_empty_header (); 01385 if (message == NULL) 01386 return NULL; 01387 01388 if (!_dbus_header_create (&message->header, 01389 DBUS_COMPILER_BYTE_ORDER, 01390 DBUS_MESSAGE_TYPE_METHOD_RETURN, 01391 sender, NULL, NULL, NULL, NULL)) 01392 { 01393 dbus_message_unref (message); 01394 return NULL; 01395 } 01396 01397 dbus_message_set_no_reply (message, TRUE); 01398 01399 if (!dbus_message_set_reply_serial (message, 01400 dbus_message_get_serial (method_call))) 01401 { 01402 dbus_message_unref (message); 01403 return NULL; 01404 } 01405 01406 return message; 01407 } 01408 01423 DBusMessage* 01424 dbus_message_new_signal (const char *path, 01425 const char *iface, 01426 const char *name) 01427 { 01428 DBusMessage *message; 01429 01430 _dbus_return_val_if_fail (path != NULL, NULL); 01431 _dbus_return_val_if_fail (iface != NULL, NULL); 01432 _dbus_return_val_if_fail (name != NULL, NULL); 01433 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01434 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL); 01435 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); 01436 01437 message = dbus_message_new_empty_header (); 01438 if (message == NULL) 01439 return NULL; 01440 01441 if (!_dbus_header_create (&message->header, 01442 DBUS_COMPILER_BYTE_ORDER, 01443 DBUS_MESSAGE_TYPE_SIGNAL, 01444 NULL, path, iface, name, NULL)) 01445 { 01446 dbus_message_unref (message); 01447 return NULL; 01448 } 01449 01450 dbus_message_set_no_reply (message, TRUE); 01451 01452 return message; 01453 } 01454 01469 DBusMessage* 01470 dbus_message_new_error (DBusMessage *reply_to, 01471 const char *error_name, 01472 const char *error_message) 01473 { 01474 DBusMessage *message; 01475 const char *sender; 01476 DBusMessageIter iter; 01477 01478 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01479 _dbus_return_val_if_fail (error_name != NULL, NULL); 01480 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01481 01482 sender = dbus_message_get_sender (reply_to); 01483 01484 /* sender may be NULL for non-message-bus case or 01485 * when the message bus is dealing with an unregistered 01486 * connection. 01487 */ 01488 message = dbus_message_new_empty_header (); 01489 if (message == NULL) 01490 return NULL; 01491 01492 if (!_dbus_header_create (&message->header, 01493 DBUS_COMPILER_BYTE_ORDER, 01494 DBUS_MESSAGE_TYPE_ERROR, 01495 sender, NULL, NULL, NULL, error_name)) 01496 { 01497 dbus_message_unref (message); 01498 return NULL; 01499 } 01500 01501 dbus_message_set_no_reply (message, TRUE); 01502 01503 if (!dbus_message_set_reply_serial (message, 01504 dbus_message_get_serial (reply_to))) 01505 { 01506 dbus_message_unref (message); 01507 return NULL; 01508 } 01509 01510 if (error_message != NULL) 01511 { 01512 dbus_message_iter_init_append (message, &iter); 01513 if (!dbus_message_iter_append_basic (&iter, 01514 DBUS_TYPE_STRING, 01515 &error_message)) 01516 { 01517 dbus_message_unref (message); 01518 return NULL; 01519 } 01520 } 01521 01522 return message; 01523 } 01524 01541 DBusMessage* 01542 dbus_message_new_error_printf (DBusMessage *reply_to, 01543 const char *error_name, 01544 const char *error_format, 01545 ...) 01546 { 01547 va_list args; 01548 DBusString str; 01549 DBusMessage *message; 01550 01551 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01552 _dbus_return_val_if_fail (error_name != NULL, NULL); 01553 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01554 01555 if (!_dbus_string_init (&str)) 01556 return NULL; 01557 01558 va_start (args, error_format); 01559 01560 if (_dbus_string_append_printf_valist (&str, error_format, args)) 01561 message = dbus_message_new_error (reply_to, error_name, 01562 _dbus_string_get_const_data (&str)); 01563 else 01564 message = NULL; 01565 01566 _dbus_string_free (&str); 01567 01568 va_end (args); 01569 01570 return message; 01571 } 01572 01573 01586 DBusMessage * 01587 dbus_message_copy (const DBusMessage *message) 01588 { 01589 DBusMessage *retval; 01590 01591 _dbus_return_val_if_fail (message != NULL, NULL); 01592 01593 retval = dbus_new0 (DBusMessage, 1); 01594 if (retval == NULL) 01595 return NULL; 01596 01597 _dbus_atomic_inc (&retval->refcount); 01598 01599 retval->locked = FALSE; 01600 #ifndef DBUS_DISABLE_CHECKS 01601 retval->generation = message->generation; 01602 #endif 01603 01604 if (!_dbus_header_copy (&message->header, &retval->header)) 01605 { 01606 dbus_free (retval); 01607 return NULL; 01608 } 01609 01610 if (!_dbus_string_init_preallocated (&retval->body, 01611 _dbus_string_get_length (&message->body))) 01612 { 01613 _dbus_header_free (&retval->header); 01614 dbus_free (retval); 01615 return NULL; 01616 } 01617 01618 if (!_dbus_string_copy (&message->body, 0, 01619 &retval->body, 0)) 01620 goto failed_copy; 01621 01622 #ifdef HAVE_UNIX_FD_PASSING 01623 retval->unix_fds = dbus_new(int, message->n_unix_fds); 01624 if (retval->unix_fds == NULL && message->n_unix_fds > 0) 01625 goto failed_copy; 01626 01627 retval->n_unix_fds_allocated = message->n_unix_fds; 01628 01629 for (retval->n_unix_fds = 0; 01630 retval->n_unix_fds < message->n_unix_fds; 01631 retval->n_unix_fds++) 01632 { 01633 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL); 01634 01635 if (retval->unix_fds[retval->n_unix_fds] < 0) 01636 goto failed_copy; 01637 } 01638 01639 #endif 01640 01641 _dbus_message_trace_ref (retval, 0, 1, "copy"); 01642 return retval; 01643 01644 failed_copy: 01645 _dbus_header_free (&retval->header); 01646 _dbus_string_free (&retval->body); 01647 01648 #ifdef HAVE_UNIX_FD_PASSING 01649 close_unix_fds(retval->unix_fds, &retval->n_unix_fds); 01650 dbus_free(retval->unix_fds); 01651 #endif 01652 01653 dbus_free (retval); 01654 01655 return NULL; 01656 } 01657 01658 01666 DBusMessage * 01667 dbus_message_ref (DBusMessage *message) 01668 { 01669 dbus_int32_t old_refcount; 01670 01671 _dbus_return_val_if_fail (message != NULL, NULL); 01672 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); 01673 _dbus_return_val_if_fail (!message->in_cache, NULL); 01674 01675 old_refcount = _dbus_atomic_inc (&message->refcount); 01676 _dbus_assert (old_refcount >= 1); 01677 _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref"); 01678 01679 return message; 01680 } 01681 01689 void 01690 dbus_message_unref (DBusMessage *message) 01691 { 01692 dbus_int32_t old_refcount; 01693 01694 _dbus_return_if_fail (message != NULL); 01695 _dbus_return_if_fail (message->generation == _dbus_current_generation); 01696 _dbus_return_if_fail (!message->in_cache); 01697 01698 old_refcount = _dbus_atomic_dec (&message->refcount); 01699 01700 _dbus_assert (old_refcount >= 1); 01701 01702 _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref"); 01703 01704 if (old_refcount == 1) 01705 { 01706 /* Calls application callbacks! */ 01707 dbus_message_cache_or_finalize (message); 01708 } 01709 } 01710 01721 int 01722 dbus_message_get_type (DBusMessage *message) 01723 { 01724 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID); 01725 01726 return _dbus_header_get_message_type (&message->header); 01727 } 01728 01791 dbus_bool_t 01792 dbus_message_append_args (DBusMessage *message, 01793 int first_arg_type, 01794 ...) 01795 { 01796 dbus_bool_t retval; 01797 va_list var_args; 01798 01799 _dbus_return_val_if_fail (message != NULL, FALSE); 01800 01801 va_start (var_args, first_arg_type); 01802 retval = dbus_message_append_args_valist (message, 01803 first_arg_type, 01804 var_args); 01805 va_end (var_args); 01806 01807 return retval; 01808 } 01809 01823 dbus_bool_t 01824 dbus_message_append_args_valist (DBusMessage *message, 01825 int first_arg_type, 01826 va_list var_args) 01827 { 01828 int type; 01829 DBusMessageIter iter; 01830 01831 _dbus_return_val_if_fail (message != NULL, FALSE); 01832 01833 type = first_arg_type; 01834 01835 dbus_message_iter_init_append (message, &iter); 01836 01837 while (type != DBUS_TYPE_INVALID) 01838 { 01839 if (dbus_type_is_basic (type)) 01840 { 01841 const DBusBasicValue *value; 01842 value = va_arg (var_args, const DBusBasicValue*); 01843 01844 if (!dbus_message_iter_append_basic (&iter, 01845 type, 01846 value)) 01847 goto failed; 01848 } 01849 else if (type == DBUS_TYPE_ARRAY) 01850 { 01851 int element_type; 01852 DBusMessageIter array; 01853 char buf[2]; 01854 01855 element_type = va_arg (var_args, int); 01856 01857 buf[0] = element_type; 01858 buf[1] = '\0'; 01859 if (!dbus_message_iter_open_container (&iter, 01860 DBUS_TYPE_ARRAY, 01861 buf, 01862 &array)) 01863 goto failed; 01864 01865 if (dbus_type_is_fixed (element_type) && 01866 element_type != DBUS_TYPE_UNIX_FD) 01867 { 01868 const DBusBasicValue **value; 01869 int n_elements; 01870 01871 value = va_arg (var_args, const DBusBasicValue**); 01872 n_elements = va_arg (var_args, int); 01873 01874 if (!dbus_message_iter_append_fixed_array (&array, 01875 element_type, 01876 value, 01877 n_elements)) { 01878 dbus_message_iter_abandon_container (&iter, &array); 01879 goto failed; 01880 } 01881 } 01882 else if (_DBUS_TYPE_IS_STRINGLIKE (element_type)) 01883 { 01884 const char ***value_p; 01885 const char **value; 01886 int n_elements; 01887 int i; 01888 01889 value_p = va_arg (var_args, const char***); 01890 n_elements = va_arg (var_args, int); 01891 01892 value = *value_p; 01893 01894 i = 0; 01895 while (i < n_elements) 01896 { 01897 if (!dbus_message_iter_append_basic (&array, 01898 element_type, 01899 &value[i])) { 01900 dbus_message_iter_abandon_container (&iter, &array); 01901 goto failed; 01902 } 01903 ++i; 01904 } 01905 } 01906 else 01907 { 01908 _dbus_warn ("arrays of %s can't be appended with %s for now\n", 01909 _dbus_type_to_string (element_type), 01910 _DBUS_FUNCTION_NAME); 01911 goto failed; 01912 } 01913 01914 if (!dbus_message_iter_close_container (&iter, &array)) 01915 goto failed; 01916 } 01917 #ifndef DBUS_DISABLE_CHECKS 01918 else 01919 { 01920 _dbus_warn ("type %s isn't supported yet in %s\n", 01921 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME); 01922 goto failed; 01923 } 01924 #endif 01925 01926 type = va_arg (var_args, int); 01927 } 01928 01929 return TRUE; 01930 01931 failed: 01932 return FALSE; 01933 } 01934 01979 dbus_bool_t 01980 dbus_message_get_args (DBusMessage *message, 01981 DBusError *error, 01982 int first_arg_type, 01983 ...) 01984 { 01985 dbus_bool_t retval; 01986 va_list var_args; 01987 01988 _dbus_return_val_if_fail (message != NULL, FALSE); 01989 _dbus_return_val_if_error_is_set (error, FALSE); 01990 01991 va_start (var_args, first_arg_type); 01992 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args); 01993 va_end (var_args); 01994 01995 return retval; 01996 } 01997 02008 dbus_bool_t 02009 dbus_message_get_args_valist (DBusMessage *message, 02010 DBusError *error, 02011 int first_arg_type, 02012 va_list var_args) 02013 { 02014 DBusMessageIter iter; 02015 02016 _dbus_return_val_if_fail (message != NULL, FALSE); 02017 _dbus_return_val_if_error_is_set (error, FALSE); 02018 02019 dbus_message_iter_init (message, &iter); 02020 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); 02021 } 02022 02023 static void 02024 _dbus_message_iter_init_common (DBusMessage *message, 02025 DBusMessageRealIter *real, 02026 int iter_type) 02027 { 02028 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); 02029 02030 /* Since the iterator will read or write who-knows-what from the 02031 * message, we need to get in the right byte order 02032 */ 02033 ensure_byte_order (message); 02034 02035 real->message = message; 02036 real->changed_stamp = message->changed_stamp; 02037 real->iter_type = iter_type; 02038 real->sig_refcount = 0; 02039 } 02040 02063 dbus_bool_t 02064 dbus_message_iter_init (DBusMessage *message, 02065 DBusMessageIter *iter) 02066 { 02067 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02068 const DBusString *type_str; 02069 int type_pos; 02070 02071 _dbus_return_val_if_fail (message != NULL, FALSE); 02072 _dbus_return_val_if_fail (iter != NULL, FALSE); 02073 02074 get_const_signature (&message->header, &type_str, &type_pos); 02075 02076 _dbus_message_iter_init_common (message, real, 02077 DBUS_MESSAGE_ITER_TYPE_READER); 02078 02079 _dbus_type_reader_init (&real->u.reader, 02080 _dbus_header_get_byte_order (&message->header), 02081 type_str, type_pos, 02082 &message->body, 02083 0); 02084 02085 return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID; 02086 } 02087 02094 dbus_bool_t 02095 dbus_message_iter_has_next (DBusMessageIter *iter) 02096 { 02097 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02098 02099 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 02100 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02101 02102 return _dbus_type_reader_has_next (&real->u.reader); 02103 } 02104 02113 dbus_bool_t 02114 dbus_message_iter_next (DBusMessageIter *iter) 02115 { 02116 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02117 02118 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 02119 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02120 02121 return _dbus_type_reader_next (&real->u.reader); 02122 } 02123 02138 int 02139 dbus_message_iter_get_arg_type (DBusMessageIter *iter) 02140 { 02141 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02142 02143 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02144 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02145 02146 return _dbus_type_reader_get_current_type (&real->u.reader); 02147 } 02148 02157 int 02158 dbus_message_iter_get_element_type (DBusMessageIter *iter) 02159 { 02160 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02161 02162 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02163 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); 02164 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 02165 02166 return _dbus_type_reader_get_element_type (&real->u.reader); 02167 } 02168 02194 void 02195 dbus_message_iter_recurse (DBusMessageIter *iter, 02196 DBusMessageIter *sub) 02197 { 02198 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02199 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02200 02201 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02202 _dbus_return_if_fail (sub != NULL); 02203 02204 *real_sub = *real; 02205 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader); 02206 } 02207 02219 char * 02220 dbus_message_iter_get_signature (DBusMessageIter *iter) 02221 { 02222 const DBusString *sig; 02223 DBusString retstr; 02224 char *ret; 02225 int start, len; 02226 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02227 02228 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL); 02229 02230 if (!_dbus_string_init (&retstr)) 02231 return NULL; 02232 02233 _dbus_type_reader_get_signature (&real->u.reader, &sig, 02234 &start, &len); 02235 if (!_dbus_string_append_len (&retstr, 02236 _dbus_string_get_const_data (sig) + start, 02237 len)) 02238 return NULL; 02239 if (!_dbus_string_steal_data (&retstr, &ret)) 02240 return NULL; 02241 _dbus_string_free (&retstr); 02242 return ret; 02243 } 02244 02292 void 02293 dbus_message_iter_get_basic (DBusMessageIter *iter, 02294 void *value) 02295 { 02296 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02297 02298 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02299 _dbus_return_if_fail (value != NULL); 02300 02301 if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD) 02302 { 02303 #ifdef HAVE_UNIX_FD_PASSING 02304 DBusBasicValue idx; 02305 02306 _dbus_type_reader_read_basic(&real->u.reader, &idx); 02307 02308 if (idx.u32 >= real->message->n_unix_fds) { 02309 /* Hmm, we cannot really signal an error here, so let's make 02310 sure to return an invalid fd. */ 02311 *((int*) value) = -1; 02312 return; 02313 } 02314 02315 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL); 02316 #else 02317 *((int*) value) = -1; 02318 #endif 02319 } 02320 else 02321 { 02322 _dbus_type_reader_read_basic (&real->u.reader, 02323 value); 02324 } 02325 } 02326 02345 int 02346 dbus_message_iter_get_array_len (DBusMessageIter *iter) 02347 { 02348 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02349 02350 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02351 02352 return _dbus_type_reader_get_array_length (&real->u.reader); 02353 } 02354 02390 void 02391 dbus_message_iter_get_fixed_array (DBusMessageIter *iter, 02392 void *value, 02393 int *n_elements) 02394 { 02395 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02396 #ifndef DBUS_DISABLE_CHECKS 02397 int subtype = _dbus_type_reader_get_current_type(&real->u.reader); 02398 02399 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02400 _dbus_return_if_fail (value != NULL); 02401 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) || 02402 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD)); 02403 #endif 02404 02405 _dbus_type_reader_read_fixed_multi (&real->u.reader, 02406 value, n_elements); 02407 } 02408 02420 void 02421 dbus_message_iter_init_append (DBusMessage *message, 02422 DBusMessageIter *iter) 02423 { 02424 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02425 02426 _dbus_return_if_fail (message != NULL); 02427 _dbus_return_if_fail (iter != NULL); 02428 02429 _dbus_message_iter_init_common (message, real, 02430 DBUS_MESSAGE_ITER_TYPE_WRITER); 02431 02432 /* We create the signature string and point iterators at it "on demand" 02433 * when a value is actually appended. That means that init() never fails 02434 * due to OOM. 02435 */ 02436 _dbus_type_writer_init_types_delayed (&real->u.writer, 02437 _dbus_header_get_byte_order (&message->header), 02438 &message->body, 02439 _dbus_string_get_length (&message->body)); 02440 } 02441 02450 static dbus_bool_t 02451 _dbus_message_iter_open_signature (DBusMessageRealIter *real) 02452 { 02453 DBusString *str; 02454 const DBusString *current_sig; 02455 int current_sig_pos; 02456 02457 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02458 02459 if (real->u.writer.type_str != NULL) 02460 { 02461 _dbus_assert (real->sig_refcount > 0); 02462 real->sig_refcount += 1; 02463 return TRUE; 02464 } 02465 02466 str = dbus_new (DBusString, 1); 02467 if (str == NULL) 02468 return FALSE; 02469 02470 if (!_dbus_header_get_field_raw (&real->message->header, 02471 DBUS_HEADER_FIELD_SIGNATURE, 02472 ¤t_sig, ¤t_sig_pos)) 02473 current_sig = NULL; 02474 02475 if (current_sig) 02476 { 02477 int current_len; 02478 02479 current_len = _dbus_string_get_byte (current_sig, current_sig_pos); 02480 current_sig_pos += 1; /* move on to sig data */ 02481 02482 if (!_dbus_string_init_preallocated (str, current_len + 4)) 02483 { 02484 dbus_free (str); 02485 return FALSE; 02486 } 02487 02488 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len, 02489 str, 0)) 02490 { 02491 _dbus_string_free (str); 02492 dbus_free (str); 02493 return FALSE; 02494 } 02495 } 02496 else 02497 { 02498 if (!_dbus_string_init_preallocated (str, 4)) 02499 { 02500 dbus_free (str); 02501 return FALSE; 02502 } 02503 } 02504 02505 real->sig_refcount = 1; 02506 02507 _dbus_type_writer_add_types (&real->u.writer, 02508 str, _dbus_string_get_length (str)); 02509 return TRUE; 02510 } 02511 02521 static dbus_bool_t 02522 _dbus_message_iter_close_signature (DBusMessageRealIter *real) 02523 { 02524 DBusString *str; 02525 const char *v_STRING; 02526 dbus_bool_t retval; 02527 02528 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02529 _dbus_assert (real->u.writer.type_str != NULL); 02530 _dbus_assert (real->sig_refcount > 0); 02531 02532 real->sig_refcount -= 1; 02533 02534 if (real->sig_refcount > 0) 02535 return TRUE; 02536 _dbus_assert (real->sig_refcount == 0); 02537 02538 retval = TRUE; 02539 02540 str = real->u.writer.type_str; 02541 02542 v_STRING = _dbus_string_get_const_data (str); 02543 if (!_dbus_header_set_field_basic (&real->message->header, 02544 DBUS_HEADER_FIELD_SIGNATURE, 02545 DBUS_TYPE_SIGNATURE, 02546 &v_STRING)) 02547 retval = FALSE; 02548 02549 _dbus_type_writer_remove_types (&real->u.writer); 02550 _dbus_string_free (str); 02551 dbus_free (str); 02552 02553 return retval; 02554 } 02555 02563 static void 02564 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real) 02565 { 02566 DBusString *str; 02567 02568 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02569 _dbus_assert (real->u.writer.type_str != NULL); 02570 _dbus_assert (real->sig_refcount > 0); 02571 02572 real->sig_refcount -= 1; 02573 02574 if (real->sig_refcount > 0) 02575 return; 02576 _dbus_assert (real->sig_refcount == 0); 02577 02578 str = real->u.writer.type_str; 02579 02580 _dbus_type_writer_remove_types (&real->u.writer); 02581 _dbus_string_free (str); 02582 dbus_free (str); 02583 } 02584 02585 #ifndef DBUS_DISABLE_CHECKS 02586 static dbus_bool_t 02587 _dbus_message_iter_append_check (DBusMessageRealIter *iter) 02588 { 02589 if (!_dbus_message_iter_check (iter)) 02590 return FALSE; 02591 02592 if (iter->message->locked) 02593 { 02594 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n"); 02595 return FALSE; 02596 } 02597 02598 return TRUE; 02599 } 02600 #endif /* DBUS_DISABLE_CHECKS */ 02601 02602 #ifdef HAVE_UNIX_FD_PASSING 02603 static int * 02604 expand_fd_array(DBusMessage *m, 02605 unsigned n) 02606 { 02607 _dbus_assert(m); 02608 02609 /* This makes space for adding n new fds to the array and returns a 02610 pointer to the place were the first fd should be put. */ 02611 02612 if (m->n_unix_fds + n > m->n_unix_fds_allocated) 02613 { 02614 unsigned k; 02615 int *p; 02616 02617 /* Make twice as much space as necessary */ 02618 k = (m->n_unix_fds + n) * 2; 02619 02620 /* Allocate at least four */ 02621 if (k < 4) 02622 k = 4; 02623 02624 p = dbus_realloc(m->unix_fds, k * sizeof(int)); 02625 if (p == NULL) 02626 return NULL; 02627 02628 m->unix_fds = p; 02629 m->n_unix_fds_allocated = k; 02630 } 02631 02632 return m->unix_fds + m->n_unix_fds; 02633 } 02634 #endif 02635 02655 dbus_bool_t 02656 dbus_message_iter_append_basic (DBusMessageIter *iter, 02657 int type, 02658 const void *value) 02659 { 02660 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02661 dbus_bool_t ret; 02662 02663 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02664 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02665 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE); 02666 _dbus_return_val_if_fail (value != NULL, FALSE); 02667 02668 #ifndef DBUS_DISABLE_CHECKS 02669 switch (type) 02670 { 02671 const char * const *string_p; 02672 const dbus_bool_t *bool_p; 02673 02674 case DBUS_TYPE_STRING: 02675 string_p = value; 02676 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE); 02677 break; 02678 02679 case DBUS_TYPE_OBJECT_PATH: 02680 string_p = value; 02681 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE); 02682 break; 02683 02684 case DBUS_TYPE_SIGNATURE: 02685 string_p = value; 02686 _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE); 02687 break; 02688 02689 case DBUS_TYPE_BOOLEAN: 02690 bool_p = value; 02691 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE); 02692 break; 02693 02694 default: 02695 { 02696 /* nothing to check, all possible values are allowed */ 02697 } 02698 } 02699 #endif 02700 02701 if (!_dbus_message_iter_open_signature (real)) 02702 return FALSE; 02703 02704 if (type == DBUS_TYPE_UNIX_FD) 02705 { 02706 #ifdef HAVE_UNIX_FD_PASSING 02707 int *fds; 02708 dbus_uint32_t u; 02709 02710 /* First step, include the fd in the fd list of this message */ 02711 if (!(fds = expand_fd_array(real->message, 1))) 02712 return FALSE; 02713 02714 *fds = _dbus_dup(*(int*) value, NULL); 02715 if (*fds < 0) 02716 return FALSE; 02717 02718 u = real->message->n_unix_fds; 02719 02720 /* Second step, write the index to the fd */ 02721 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) { 02722 _dbus_close(*fds, NULL); 02723 return FALSE; 02724 } 02725 02726 real->message->n_unix_fds += 1; 02727 u += 1; 02728 02729 /* Final step, update the header accordingly */ 02730 ret = _dbus_header_set_field_basic (&real->message->header, 02731 DBUS_HEADER_FIELD_UNIX_FDS, 02732 DBUS_TYPE_UINT32, 02733 &u); 02734 02735 /* If any of these operations fail the message is 02736 hosed. However, no memory or fds should be leaked since what 02737 has been added to message has been added to the message, and 02738 can hence be accounted for when the message is being 02739 freed. */ 02740 #else 02741 ret = FALSE; 02742 #endif 02743 } 02744 else 02745 { 02746 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02747 } 02748 02749 if (!_dbus_message_iter_close_signature (real)) 02750 ret = FALSE; 02751 02752 return ret; 02753 } 02754 02790 dbus_bool_t 02791 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02792 int element_type, 02793 const void *value, 02794 int n_elements) 02795 { 02796 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02797 dbus_bool_t ret; 02798 02799 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02800 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02801 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); 02802 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02803 _dbus_return_val_if_fail (value != NULL, FALSE); 02804 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02805 _dbus_return_val_if_fail (n_elements <= 02806 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02807 FALSE); 02808 02809 #ifndef DBUS_DISABLE_CHECKS 02810 if (element_type == DBUS_TYPE_BOOLEAN) 02811 { 02812 const dbus_bool_t * const *bools = value; 02813 int i; 02814 02815 for (i = 0; i < n_elements; i++) 02816 { 02817 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE); 02818 } 02819 } 02820 #endif 02821 02822 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02823 02824 return ret; 02825 } 02826 02848 dbus_bool_t 02849 dbus_message_iter_open_container (DBusMessageIter *iter, 02850 int type, 02851 const char *contained_signature, 02852 DBusMessageIter *sub) 02853 { 02854 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02855 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02856 DBusString contained_str; 02857 02858 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02859 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02860 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02861 _dbus_return_val_if_fail (sub != NULL, FALSE); 02862 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02863 contained_signature == NULL) || 02864 (type == DBUS_TYPE_DICT_ENTRY && 02865 contained_signature == NULL) || 02866 (type == DBUS_TYPE_VARIANT && 02867 contained_signature != NULL) || 02868 (type == DBUS_TYPE_ARRAY && 02869 contained_signature != NULL), FALSE); 02870 02871 /* this would fail if the contained_signature is a dict entry, since 02872 * dict entries are invalid signatures standalone (they must be in 02873 * an array) 02874 */ 02875 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02876 (contained_signature == NULL || 02877 _dbus_check_is_valid_signature (contained_signature)), 02878 FALSE); 02879 02880 if (!_dbus_message_iter_open_signature (real)) 02881 return FALSE; 02882 02883 *real_sub = *real; 02884 02885 if (contained_signature != NULL) 02886 { 02887 _dbus_string_init_const (&contained_str, contained_signature); 02888 02889 return _dbus_type_writer_recurse (&real->u.writer, 02890 type, 02891 &contained_str, 0, 02892 &real_sub->u.writer); 02893 } 02894 else 02895 { 02896 return _dbus_type_writer_recurse (&real->u.writer, 02897 type, 02898 NULL, 0, 02899 &real_sub->u.writer); 02900 } 02901 } 02902 02903 02917 dbus_bool_t 02918 dbus_message_iter_close_container (DBusMessageIter *iter, 02919 DBusMessageIter *sub) 02920 { 02921 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02922 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02923 dbus_bool_t ret; 02924 02925 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02926 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02927 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 02928 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02929 02930 ret = _dbus_type_writer_unrecurse (&real->u.writer, 02931 &real_sub->u.writer); 02932 02933 if (!_dbus_message_iter_close_signature (real)) 02934 ret = FALSE; 02935 02936 return ret; 02937 } 02938 02950 void 02951 dbus_message_iter_abandon_container (DBusMessageIter *iter, 02952 DBusMessageIter *sub) 02953 { 02954 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02955 #ifndef DBUS_DISABLE_CHECKS 02956 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02957 02958 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 02959 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02960 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 02961 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02962 #endif 02963 02964 _dbus_message_iter_abandon_signature (real); 02965 } 02966 02983 void 02984 dbus_message_set_no_reply (DBusMessage *message, 02985 dbus_bool_t no_reply) 02986 { 02987 _dbus_return_if_fail (message != NULL); 02988 _dbus_return_if_fail (!message->locked); 02989 02990 _dbus_header_toggle_flag (&message->header, 02991 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 02992 no_reply); 02993 } 02994 03002 dbus_bool_t 03003 dbus_message_get_no_reply (DBusMessage *message) 03004 { 03005 _dbus_return_val_if_fail (message != NULL, FALSE); 03006 03007 return _dbus_header_get_flag (&message->header, 03008 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 03009 } 03010 03025 void 03026 dbus_message_set_auto_start (DBusMessage *message, 03027 dbus_bool_t auto_start) 03028 { 03029 _dbus_return_if_fail (message != NULL); 03030 _dbus_return_if_fail (!message->locked); 03031 03032 _dbus_header_toggle_flag (&message->header, 03033 DBUS_HEADER_FLAG_NO_AUTO_START, 03034 !auto_start); 03035 } 03036 03044 dbus_bool_t 03045 dbus_message_get_auto_start (DBusMessage *message) 03046 { 03047 _dbus_return_val_if_fail (message != NULL, FALSE); 03048 03049 return !_dbus_header_get_flag (&message->header, 03050 DBUS_HEADER_FLAG_NO_AUTO_START); 03051 } 03052 03053 03066 dbus_bool_t 03067 dbus_message_set_path (DBusMessage *message, 03068 const char *object_path) 03069 { 03070 _dbus_return_val_if_fail (message != NULL, FALSE); 03071 _dbus_return_val_if_fail (!message->locked, FALSE); 03072 _dbus_return_val_if_fail (object_path == NULL || 03073 _dbus_check_is_valid_path (object_path), 03074 FALSE); 03075 03076 return set_or_delete_string_field (message, 03077 DBUS_HEADER_FIELD_PATH, 03078 DBUS_TYPE_OBJECT_PATH, 03079 object_path); 03080 } 03081 03095 const char* 03096 dbus_message_get_path (DBusMessage *message) 03097 { 03098 const char *v; 03099 03100 _dbus_return_val_if_fail (message != NULL, NULL); 03101 03102 v = NULL; /* in case field doesn't exist */ 03103 _dbus_header_get_field_basic (&message->header, 03104 DBUS_HEADER_FIELD_PATH, 03105 DBUS_TYPE_OBJECT_PATH, 03106 (void *) &v); 03107 return v; 03108 } 03109 03119 dbus_bool_t 03120 dbus_message_has_path (DBusMessage *message, 03121 const char *path) 03122 { 03123 const char *msg_path; 03124 msg_path = dbus_message_get_path (message); 03125 03126 if (msg_path == NULL) 03127 { 03128 if (path == NULL) 03129 return TRUE; 03130 else 03131 return FALSE; 03132 } 03133 03134 if (path == NULL) 03135 return FALSE; 03136 03137 if (strcmp (msg_path, path) == 0) 03138 return TRUE; 03139 03140 return FALSE; 03141 } 03142 03163 dbus_bool_t 03164 dbus_message_get_path_decomposed (DBusMessage *message, 03165 char ***path) 03166 { 03167 const char *v; 03168 03169 _dbus_return_val_if_fail (message != NULL, FALSE); 03170 _dbus_return_val_if_fail (path != NULL, FALSE); 03171 03172 *path = NULL; 03173 03174 v = dbus_message_get_path (message); 03175 if (v != NULL) 03176 { 03177 if (!_dbus_decompose_path (v, strlen (v), 03178 path, NULL)) 03179 return FALSE; 03180 } 03181 return TRUE; 03182 } 03183 03197 dbus_bool_t 03198 dbus_message_set_interface (DBusMessage *message, 03199 const char *iface) 03200 { 03201 _dbus_return_val_if_fail (message != NULL, FALSE); 03202 _dbus_return_val_if_fail (!message->locked, FALSE); 03203 _dbus_return_val_if_fail (iface == NULL || 03204 _dbus_check_is_valid_interface (iface), 03205 FALSE); 03206 03207 return set_or_delete_string_field (message, 03208 DBUS_HEADER_FIELD_INTERFACE, 03209 DBUS_TYPE_STRING, 03210 iface); 03211 } 03212 03226 const char* 03227 dbus_message_get_interface (DBusMessage *message) 03228 { 03229 const char *v; 03230 03231 _dbus_return_val_if_fail (message != NULL, NULL); 03232 03233 v = NULL; /* in case field doesn't exist */ 03234 _dbus_header_get_field_basic (&message->header, 03235 DBUS_HEADER_FIELD_INTERFACE, 03236 DBUS_TYPE_STRING, 03237 (void *) &v); 03238 return v; 03239 } 03240 03248 dbus_bool_t 03249 dbus_message_has_interface (DBusMessage *message, 03250 const char *iface) 03251 { 03252 const char *msg_interface; 03253 msg_interface = dbus_message_get_interface (message); 03254 03255 if (msg_interface == NULL) 03256 { 03257 if (iface == NULL) 03258 return TRUE; 03259 else 03260 return FALSE; 03261 } 03262 03263 if (iface == NULL) 03264 return FALSE; 03265 03266 if (strcmp (msg_interface, iface) == 0) 03267 return TRUE; 03268 03269 return FALSE; 03270 03271 } 03272 03285 dbus_bool_t 03286 dbus_message_set_member (DBusMessage *message, 03287 const char *member) 03288 { 03289 _dbus_return_val_if_fail (message != NULL, FALSE); 03290 _dbus_return_val_if_fail (!message->locked, FALSE); 03291 _dbus_return_val_if_fail (member == NULL || 03292 _dbus_check_is_valid_member (member), 03293 FALSE); 03294 03295 return set_or_delete_string_field (message, 03296 DBUS_HEADER_FIELD_MEMBER, 03297 DBUS_TYPE_STRING, 03298 member); 03299 } 03300 03312 const char* 03313 dbus_message_get_member (DBusMessage *message) 03314 { 03315 const char *v; 03316 03317 _dbus_return_val_if_fail (message != NULL, NULL); 03318 03319 v = NULL; /* in case field doesn't exist */ 03320 _dbus_header_get_field_basic (&message->header, 03321 DBUS_HEADER_FIELD_MEMBER, 03322 DBUS_TYPE_STRING, 03323 (void *) &v); 03324 return v; 03325 } 03326 03334 dbus_bool_t 03335 dbus_message_has_member (DBusMessage *message, 03336 const char *member) 03337 { 03338 const char *msg_member; 03339 msg_member = dbus_message_get_member (message); 03340 03341 if (msg_member == NULL) 03342 { 03343 if (member == NULL) 03344 return TRUE; 03345 else 03346 return FALSE; 03347 } 03348 03349 if (member == NULL) 03350 return FALSE; 03351 03352 if (strcmp (msg_member, member) == 0) 03353 return TRUE; 03354 03355 return FALSE; 03356 03357 } 03358 03370 dbus_bool_t 03371 dbus_message_set_error_name (DBusMessage *message, 03372 const char *error_name) 03373 { 03374 _dbus_return_val_if_fail (message != NULL, FALSE); 03375 _dbus_return_val_if_fail (!message->locked, FALSE); 03376 _dbus_return_val_if_fail (error_name == NULL || 03377 _dbus_check_is_valid_error_name (error_name), 03378 FALSE); 03379 03380 return set_or_delete_string_field (message, 03381 DBUS_HEADER_FIELD_ERROR_NAME, 03382 DBUS_TYPE_STRING, 03383 error_name); 03384 } 03385 03396 const char* 03397 dbus_message_get_error_name (DBusMessage *message) 03398 { 03399 const char *v; 03400 03401 _dbus_return_val_if_fail (message != NULL, NULL); 03402 03403 v = NULL; /* in case field doesn't exist */ 03404 _dbus_header_get_field_basic (&message->header, 03405 DBUS_HEADER_FIELD_ERROR_NAME, 03406 DBUS_TYPE_STRING, 03407 (void *) &v); 03408 return v; 03409 } 03410 03424 dbus_bool_t 03425 dbus_message_set_destination (DBusMessage *message, 03426 const char *destination) 03427 { 03428 _dbus_return_val_if_fail (message != NULL, FALSE); 03429 _dbus_return_val_if_fail (!message->locked, FALSE); 03430 _dbus_return_val_if_fail (destination == NULL || 03431 _dbus_check_is_valid_bus_name (destination), 03432 FALSE); 03433 03434 return set_or_delete_string_field (message, 03435 DBUS_HEADER_FIELD_DESTINATION, 03436 DBUS_TYPE_STRING, 03437 destination); 03438 } 03439 03449 const char* 03450 dbus_message_get_destination (DBusMessage *message) 03451 { 03452 const char *v; 03453 03454 _dbus_return_val_if_fail (message != NULL, NULL); 03455 03456 v = NULL; /* in case field doesn't exist */ 03457 _dbus_header_get_field_basic (&message->header, 03458 DBUS_HEADER_FIELD_DESTINATION, 03459 DBUS_TYPE_STRING, 03460 (void *) &v); 03461 return v; 03462 } 03463 03478 dbus_bool_t 03479 dbus_message_set_sender (DBusMessage *message, 03480 const char *sender) 03481 { 03482 _dbus_return_val_if_fail (message != NULL, FALSE); 03483 _dbus_return_val_if_fail (!message->locked, FALSE); 03484 _dbus_return_val_if_fail (sender == NULL || 03485 _dbus_check_is_valid_bus_name (sender), 03486 FALSE); 03487 03488 return set_or_delete_string_field (message, 03489 DBUS_HEADER_FIELD_SENDER, 03490 DBUS_TYPE_STRING, 03491 sender); 03492 } 03493 03509 const char* 03510 dbus_message_get_sender (DBusMessage *message) 03511 { 03512 const char *v; 03513 03514 _dbus_return_val_if_fail (message != NULL, NULL); 03515 03516 v = NULL; /* in case field doesn't exist */ 03517 _dbus_header_get_field_basic (&message->header, 03518 DBUS_HEADER_FIELD_SENDER, 03519 DBUS_TYPE_STRING, 03520 (void *) &v); 03521 return v; 03522 } 03523 03542 const char* 03543 dbus_message_get_signature (DBusMessage *message) 03544 { 03545 const DBusString *type_str; 03546 int type_pos; 03547 03548 _dbus_return_val_if_fail (message != NULL, NULL); 03549 03550 get_const_signature (&message->header, &type_str, &type_pos); 03551 03552 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03553 } 03554 03555 static dbus_bool_t 03556 _dbus_message_has_type_interface_member (DBusMessage *message, 03557 int type, 03558 const char *iface, 03559 const char *member) 03560 { 03561 const char *n; 03562 03563 _dbus_assert (message != NULL); 03564 _dbus_assert (iface != NULL); 03565 _dbus_assert (member != NULL); 03566 03567 if (dbus_message_get_type (message) != type) 03568 return FALSE; 03569 03570 /* Optimize by checking the short member name first 03571 * instead of the longer interface name 03572 */ 03573 03574 n = dbus_message_get_member (message); 03575 03576 if (n && strcmp (n, member) == 0) 03577 { 03578 n = dbus_message_get_interface (message); 03579 03580 if (n == NULL || strcmp (n, iface) == 0) 03581 return TRUE; 03582 } 03583 03584 return FALSE; 03585 } 03586 03601 dbus_bool_t 03602 dbus_message_is_method_call (DBusMessage *message, 03603 const char *iface, 03604 const char *method) 03605 { 03606 _dbus_return_val_if_fail (message != NULL, FALSE); 03607 _dbus_return_val_if_fail (iface != NULL, FALSE); 03608 _dbus_return_val_if_fail (method != NULL, FALSE); 03609 /* don't check that interface/method are valid since it would be 03610 * expensive, and not catch many common errors 03611 */ 03612 03613 return _dbus_message_has_type_interface_member (message, 03614 DBUS_MESSAGE_TYPE_METHOD_CALL, 03615 iface, method); 03616 } 03617 03629 dbus_bool_t 03630 dbus_message_is_signal (DBusMessage *message, 03631 const char *iface, 03632 const char *signal_name) 03633 { 03634 _dbus_return_val_if_fail (message != NULL, FALSE); 03635 _dbus_return_val_if_fail (iface != NULL, FALSE); 03636 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03637 /* don't check that interface/name are valid since it would be 03638 * expensive, and not catch many common errors 03639 */ 03640 03641 return _dbus_message_has_type_interface_member (message, 03642 DBUS_MESSAGE_TYPE_SIGNAL, 03643 iface, signal_name); 03644 } 03645 03656 dbus_bool_t 03657 dbus_message_is_error (DBusMessage *message, 03658 const char *error_name) 03659 { 03660 const char *n; 03661 03662 _dbus_return_val_if_fail (message != NULL, FALSE); 03663 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03664 /* don't check that error_name is valid since it would be expensive, 03665 * and not catch many common errors 03666 */ 03667 03668 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03669 return FALSE; 03670 03671 n = dbus_message_get_error_name (message); 03672 03673 if (n && strcmp (n, error_name) == 0) 03674 return TRUE; 03675 else 03676 return FALSE; 03677 } 03678 03689 dbus_bool_t 03690 dbus_message_has_destination (DBusMessage *message, 03691 const char *name) 03692 { 03693 const char *s; 03694 03695 _dbus_return_val_if_fail (message != NULL, FALSE); 03696 _dbus_return_val_if_fail (name != NULL, FALSE); 03697 /* don't check that name is valid since it would be expensive, and 03698 * not catch many common errors 03699 */ 03700 03701 s = dbus_message_get_destination (message); 03702 03703 if (s && strcmp (s, name) == 0) 03704 return TRUE; 03705 else 03706 return FALSE; 03707 } 03708 03724 dbus_bool_t 03725 dbus_message_has_sender (DBusMessage *message, 03726 const char *name) 03727 { 03728 const char *s; 03729 03730 _dbus_return_val_if_fail (message != NULL, FALSE); 03731 _dbus_return_val_if_fail (name != NULL, FALSE); 03732 /* don't check that name is valid since it would be expensive, and 03733 * not catch many common errors 03734 */ 03735 03736 s = dbus_message_get_sender (message); 03737 03738 if (s && strcmp (s, name) == 0) 03739 return TRUE; 03740 else 03741 return FALSE; 03742 } 03743 03753 dbus_bool_t 03754 dbus_message_has_signature (DBusMessage *message, 03755 const char *signature) 03756 { 03757 const char *s; 03758 03759 _dbus_return_val_if_fail (message != NULL, FALSE); 03760 _dbus_return_val_if_fail (signature != NULL, FALSE); 03761 /* don't check that signature is valid since it would be expensive, 03762 * and not catch many common errors 03763 */ 03764 03765 s = dbus_message_get_signature (message); 03766 03767 if (s && strcmp (s, signature) == 0) 03768 return TRUE; 03769 else 03770 return FALSE; 03771 } 03772 03795 dbus_bool_t 03796 dbus_set_error_from_message (DBusError *error, 03797 DBusMessage *message) 03798 { 03799 const char *str; 03800 03801 _dbus_return_val_if_fail (message != NULL, FALSE); 03802 _dbus_return_val_if_error_is_set (error, FALSE); 03803 03804 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03805 return FALSE; 03806 03807 str = NULL; 03808 dbus_message_get_args (message, NULL, 03809 DBUS_TYPE_STRING, &str, 03810 DBUS_TYPE_INVALID); 03811 03812 dbus_set_error (error, dbus_message_get_error_name (message), 03813 str ? "%s" : NULL, str); 03814 03815 return TRUE; 03816 } 03817 03824 dbus_bool_t 03825 dbus_message_contains_unix_fds(DBusMessage *message) 03826 { 03827 #ifdef HAVE_UNIX_FD_PASSING 03828 _dbus_assert(message); 03829 03830 return message->n_unix_fds > 0; 03831 #else 03832 return FALSE; 03833 #endif 03834 } 03835 03854 #define INITIAL_LOADER_DATA_LEN 32 03855 03862 DBusMessageLoader* 03863 _dbus_message_loader_new (void) 03864 { 03865 DBusMessageLoader *loader; 03866 03867 loader = dbus_new0 (DBusMessageLoader, 1); 03868 if (loader == NULL) 03869 return NULL; 03870 03871 loader->refcount = 1; 03872 03873 loader->corrupted = FALSE; 03874 loader->corruption_reason = DBUS_VALID; 03875 03876 /* this can be configured by the app, but defaults to the protocol max */ 03877 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03878 03879 /* We set a very relatively conservative default here since due to how 03880 SCM_RIGHTS works we need to preallocate an fd array of the maximum 03881 number of unix fds we want to receive in advance. A 03882 try-and-reallocate loop is not possible. */ 03883 loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS; 03884 03885 if (!_dbus_string_init (&loader->data)) 03886 { 03887 dbus_free (loader); 03888 return NULL; 03889 } 03890 03891 /* preallocate the buffer for speed, ignore failure */ 03892 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03893 _dbus_string_set_length (&loader->data, 0); 03894 03895 #ifdef HAVE_UNIX_FD_PASSING 03896 loader->unix_fds = NULL; 03897 loader->n_unix_fds = loader->n_unix_fds_allocated = 0; 03898 loader->unix_fds_outstanding = FALSE; 03899 #endif 03900 03901 return loader; 03902 } 03903 03910 DBusMessageLoader * 03911 _dbus_message_loader_ref (DBusMessageLoader *loader) 03912 { 03913 loader->refcount += 1; 03914 03915 return loader; 03916 } 03917 03924 void 03925 _dbus_message_loader_unref (DBusMessageLoader *loader) 03926 { 03927 loader->refcount -= 1; 03928 if (loader->refcount == 0) 03929 { 03930 #ifdef HAVE_UNIX_FD_PASSING 03931 close_unix_fds(loader->unix_fds, &loader->n_unix_fds); 03932 dbus_free(loader->unix_fds); 03933 #endif 03934 _dbus_list_foreach (&loader->messages, 03935 (DBusForeachFunction) dbus_message_unref, 03936 NULL); 03937 _dbus_list_clear (&loader->messages); 03938 _dbus_string_free (&loader->data); 03939 dbus_free (loader); 03940 } 03941 } 03942 03961 void 03962 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 03963 DBusString **buffer) 03964 { 03965 _dbus_assert (!loader->buffer_outstanding); 03966 03967 *buffer = &loader->data; 03968 03969 loader->buffer_outstanding = TRUE; 03970 } 03971 03981 void 03982 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 03983 DBusString *buffer) 03984 { 03985 _dbus_assert (loader->buffer_outstanding); 03986 _dbus_assert (buffer == &loader->data); 03987 03988 loader->buffer_outstanding = FALSE; 03989 } 03990 04001 dbus_bool_t 04002 _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, 04003 int **fds, 04004 unsigned *max_n_fds) 04005 { 04006 #ifdef HAVE_UNIX_FD_PASSING 04007 _dbus_assert (!loader->unix_fds_outstanding); 04008 04009 /* Allocate space where we can put the fds we read. We allocate 04010 space for max_message_unix_fds since this is an 04011 upper limit how many fds can be received within a single 04012 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic 04013 we are allocating the maximum possible array size right from the 04014 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed 04015 there is no better way. */ 04016 04017 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds) 04018 { 04019 int *a = dbus_realloc(loader->unix_fds, 04020 loader->max_message_unix_fds * sizeof(loader->unix_fds[0])); 04021 04022 if (!a) 04023 return FALSE; 04024 04025 loader->unix_fds = a; 04026 loader->n_unix_fds_allocated = loader->max_message_unix_fds; 04027 } 04028 04029 *fds = loader->unix_fds + loader->n_unix_fds; 04030 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds; 04031 04032 loader->unix_fds_outstanding = TRUE; 04033 return TRUE; 04034 #else 04035 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 04036 return FALSE; 04037 #endif 04038 } 04039 04050 void 04051 _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, 04052 int *fds, 04053 unsigned n_fds) 04054 { 04055 #ifdef HAVE_UNIX_FD_PASSING 04056 _dbus_assert(loader->unix_fds_outstanding); 04057 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds); 04058 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated); 04059 04060 loader->n_unix_fds += n_fds; 04061 loader->unix_fds_outstanding = FALSE; 04062 04063 if (n_fds && loader->unix_fds_change) 04064 loader->unix_fds_change (loader->unix_fds_change_data); 04065 #else 04066 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 04067 #endif 04068 } 04069 04070 /* 04071 * FIXME when we move the header out of the buffer, that memmoves all 04072 * buffered messages. Kind of crappy. 04073 * 04074 * Also we copy the header and body, which is kind of crappy. To 04075 * avoid this, we have to allow header and body to be in a single 04076 * memory block, which is good for messages we read and bad for 04077 * messages we are creating. But we could move_len() the buffer into 04078 * this single memory block, and move_len() will just swap the buffers 04079 * if you're moving the entire buffer replacing the dest string. 04080 * 04081 * We could also have the message loader tell the transport how many 04082 * bytes to read; so it would first ask for some arbitrary number like 04083 * 256, then if the message was incomplete it would use the 04084 * header/body len to ask for exactly the size of the message (or 04085 * blocks the size of a typical kernel buffer for the socket). That 04086 * way we don't get trailing bytes in the buffer that have to be 04087 * memmoved. Though I suppose we also don't have a chance of reading a 04088 * bunch of small messages at once, so the optimization may be stupid. 04089 * 04090 * Another approach would be to keep a "start" index into 04091 * loader->data and only delete it occasionally, instead of after 04092 * each message is loaded. 04093 * 04094 * load_message() returns FALSE if not enough memory OR the loader was corrupted 04095 */ 04096 static dbus_bool_t 04097 load_message (DBusMessageLoader *loader, 04098 DBusMessage *message, 04099 int byte_order, 04100 int fields_array_len, 04101 int header_len, 04102 int body_len) 04103 { 04104 dbus_bool_t oom; 04105 DBusValidity validity; 04106 const DBusString *type_str; 04107 int type_pos; 04108 DBusValidationMode mode; 04109 dbus_uint32_t n_unix_fds = 0; 04110 04111 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 04112 04113 oom = FALSE; 04114 04115 #if 0 04116 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 04117 #endif 04118 04119 /* 1. VALIDATE AND COPY OVER HEADER */ 04120 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 04121 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 04122 04123 if (!_dbus_header_load (&message->header, 04124 mode, 04125 &validity, 04126 byte_order, 04127 fields_array_len, 04128 header_len, 04129 body_len, 04130 &loader->data, 0, 04131 _dbus_string_get_length (&loader->data))) 04132 { 04133 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 04134 04135 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 04136 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 04137 _dbus_assert (validity != DBUS_VALID); 04138 04139 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 04140 oom = TRUE; 04141 else 04142 { 04143 loader->corrupted = TRUE; 04144 loader->corruption_reason = validity; 04145 } 04146 goto failed; 04147 } 04148 04149 _dbus_assert (validity == DBUS_VALID); 04150 04151 /* 2. VALIDATE BODY */ 04152 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 04153 { 04154 get_const_signature (&message->header, &type_str, &type_pos); 04155 04156 /* Because the bytes_remaining arg is NULL, this validates that the 04157 * body is the right length 04158 */ 04159 validity = _dbus_validate_body_with_reason (type_str, 04160 type_pos, 04161 byte_order, 04162 NULL, 04163 &loader->data, 04164 header_len, 04165 body_len); 04166 if (validity != DBUS_VALID) 04167 { 04168 _dbus_verbose ("Failed to validate message body code %d\n", validity); 04169 04170 loader->corrupted = TRUE; 04171 loader->corruption_reason = validity; 04172 04173 goto failed; 04174 } 04175 } 04176 04177 /* 3. COPY OVER UNIX FDS */ 04178 _dbus_header_get_field_basic(&message->header, 04179 DBUS_HEADER_FIELD_UNIX_FDS, 04180 DBUS_TYPE_UINT32, 04181 &n_unix_fds); 04182 04183 #ifdef HAVE_UNIX_FD_PASSING 04184 04185 if (n_unix_fds > loader->n_unix_fds) 04186 { 04187 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n", 04188 n_unix_fds, loader->n_unix_fds); 04189 04190 loader->corrupted = TRUE; 04191 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04192 goto failed; 04193 } 04194 04195 /* If this was a recycled message there might still be 04196 some memory allocated for the fds */ 04197 dbus_free(message->unix_fds); 04198 04199 if (n_unix_fds > 0) 04200 { 04201 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0])); 04202 if (message->unix_fds == NULL) 04203 { 04204 _dbus_verbose ("Failed to allocate file descriptor array\n"); 04205 oom = TRUE; 04206 goto failed; 04207 } 04208 04209 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; 04210 loader->n_unix_fds -= n_unix_fds; 04211 memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0])); 04212 04213 if (loader->unix_fds_change) 04214 loader->unix_fds_change (loader->unix_fds_change_data); 04215 } 04216 else 04217 message->unix_fds = NULL; 04218 04219 #else 04220 04221 if (n_unix_fds > 0) 04222 { 04223 _dbus_verbose ("Hmm, message claims to come with file descriptors " 04224 "but that's not supported on our platform, disconnecting.\n"); 04225 04226 loader->corrupted = TRUE; 04227 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04228 goto failed; 04229 } 04230 04231 #endif 04232 04233 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 04234 04235 if (!_dbus_list_append (&loader->messages, message)) 04236 { 04237 _dbus_verbose ("Failed to append new message to loader queue\n"); 04238 oom = TRUE; 04239 goto failed; 04240 } 04241 04242 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 04243 _dbus_assert (_dbus_string_get_length (&loader->data) >= 04244 (header_len + body_len)); 04245 04246 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 04247 { 04248 _dbus_verbose ("Failed to move body into new message\n"); 04249 oom = TRUE; 04250 goto failed; 04251 } 04252 04253 _dbus_string_delete (&loader->data, 0, header_len + body_len); 04254 04255 /* don't waste more than 2k of memory */ 04256 _dbus_string_compact (&loader->data, 2048); 04257 04258 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 04259 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 04260 04261 _dbus_verbose ("Loaded message %p\n", message); 04262 04263 _dbus_assert (!oom); 04264 _dbus_assert (!loader->corrupted); 04265 _dbus_assert (loader->messages != NULL); 04266 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04267 04268 return TRUE; 04269 04270 failed: 04271 04272 /* Clean up */ 04273 04274 /* does nothing if the message isn't in the list */ 04275 _dbus_list_remove_last (&loader->messages, message); 04276 04277 if (oom) 04278 _dbus_assert (!loader->corrupted); 04279 else 04280 _dbus_assert (loader->corrupted); 04281 04282 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 04283 04284 return FALSE; 04285 } 04286 04301 dbus_bool_t 04302 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 04303 { 04304 while (!loader->corrupted && 04305 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 04306 { 04307 DBusValidity validity; 04308 int byte_order, fields_array_len, header_len, body_len; 04309 04310 if (_dbus_header_have_message_untrusted (loader->max_message_size, 04311 &validity, 04312 &byte_order, 04313 &fields_array_len, 04314 &header_len, 04315 &body_len, 04316 &loader->data, 0, 04317 _dbus_string_get_length (&loader->data))) 04318 { 04319 DBusMessage *message; 04320 04321 _dbus_assert (validity == DBUS_VALID); 04322 04323 message = dbus_message_new_empty_header (); 04324 if (message == NULL) 04325 return FALSE; 04326 04327 if (!load_message (loader, message, 04328 byte_order, fields_array_len, 04329 header_len, body_len)) 04330 { 04331 dbus_message_unref (message); 04332 /* load_message() returns false if corrupted or OOM; if 04333 * corrupted then return TRUE for not OOM 04334 */ 04335 return loader->corrupted; 04336 } 04337 04338 _dbus_assert (loader->messages != NULL); 04339 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04340 } 04341 else 04342 { 04343 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 04344 validity); 04345 if (validity != DBUS_VALID) 04346 { 04347 loader->corrupted = TRUE; 04348 loader->corruption_reason = validity; 04349 } 04350 return TRUE; 04351 } 04352 } 04353 04354 return TRUE; 04355 } 04356 04364 DBusMessage* 04365 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 04366 { 04367 if (loader->messages) 04368 return loader->messages->data; 04369 else 04370 return NULL; 04371 } 04372 04381 DBusMessage* 04382 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 04383 { 04384 return _dbus_list_pop_first (&loader->messages); 04385 } 04386 04395 DBusList* 04396 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 04397 { 04398 return _dbus_list_pop_first_link (&loader->messages); 04399 } 04400 04407 void 04408 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 04409 DBusList *link) 04410 { 04411 _dbus_list_prepend_link (&loader->messages, link); 04412 } 04413 04423 dbus_bool_t 04424 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 04425 { 04426 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04427 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04428 return loader->corrupted; 04429 } 04430 04437 DBusValidity 04438 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 04439 { 04440 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04441 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04442 04443 return loader->corruption_reason; 04444 } 04445 04452 void 04453 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 04454 long size) 04455 { 04456 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 04457 { 04458 _dbus_verbose ("clamping requested max message size %ld to %d\n", 04459 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 04460 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 04461 } 04462 loader->max_message_size = size; 04463 } 04464 04471 long 04472 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 04473 { 04474 return loader->max_message_size; 04475 } 04476 04483 void 04484 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, 04485 long n) 04486 { 04487 if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS) 04488 { 04489 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n", 04490 n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS); 04491 n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS; 04492 } 04493 loader->max_message_unix_fds = n; 04494 } 04495 04502 long 04503 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) 04504 { 04505 return loader->max_message_unix_fds; 04506 } 04507 04513 int 04514 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader) 04515 { 04516 #ifdef HAVE_UNIX_FD_PASSING 04517 return loader->n_unix_fds; 04518 #else 04519 return 0; 04520 #endif 04521 } 04522 04531 void 04532 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader, 04533 void (* callback) (void *), 04534 void *data) 04535 { 04536 #ifdef HAVE_UNIX_FD_PASSING 04537 loader->unix_fds_change = callback; 04538 loader->unix_fds_change_data = data; 04539 #endif 04540 } 04541 04542 static DBusDataSlotAllocator slot_allocator = 04543 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots)); 04544 04559 dbus_bool_t 04560 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 04561 { 04562 return _dbus_data_slot_allocator_alloc (&slot_allocator, 04563 slot_p); 04564 } 04565 04577 void 04578 dbus_message_free_data_slot (dbus_int32_t *slot_p) 04579 { 04580 _dbus_return_if_fail (*slot_p >= 0); 04581 04582 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 04583 } 04584 04598 dbus_bool_t 04599 dbus_message_set_data (DBusMessage *message, 04600 dbus_int32_t slot, 04601 void *data, 04602 DBusFreeFunction free_data_func) 04603 { 04604 DBusFreeFunction old_free_func; 04605 void *old_data; 04606 dbus_bool_t retval; 04607 04608 _dbus_return_val_if_fail (message != NULL, FALSE); 04609 _dbus_return_val_if_fail (slot >= 0, FALSE); 04610 04611 retval = _dbus_data_slot_list_set (&slot_allocator, 04612 &message->slot_list, 04613 slot, data, free_data_func, 04614 &old_free_func, &old_data); 04615 04616 if (retval) 04617 { 04618 /* Do the actual free outside the message lock */ 04619 if (old_free_func) 04620 (* old_free_func) (old_data); 04621 } 04622 04623 return retval; 04624 } 04625 04634 void* 04635 dbus_message_get_data (DBusMessage *message, 04636 dbus_int32_t slot) 04637 { 04638 void *res; 04639 04640 _dbus_return_val_if_fail (message != NULL, NULL); 04641 04642 res = _dbus_data_slot_list_get (&slot_allocator, 04643 &message->slot_list, 04644 slot); 04645 04646 return res; 04647 } 04648 04662 int 04663 dbus_message_type_from_string (const char *type_str) 04664 { 04665 if (strcmp (type_str, "method_call") == 0) 04666 return DBUS_MESSAGE_TYPE_METHOD_CALL; 04667 if (strcmp (type_str, "method_return") == 0) 04668 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 04669 else if (strcmp (type_str, "signal") == 0) 04670 return DBUS_MESSAGE_TYPE_SIGNAL; 04671 else if (strcmp (type_str, "error") == 0) 04672 return DBUS_MESSAGE_TYPE_ERROR; 04673 else 04674 return DBUS_MESSAGE_TYPE_INVALID; 04675 } 04676 04690 const char * 04691 dbus_message_type_to_string (int type) 04692 { 04693 switch (type) 04694 { 04695 case DBUS_MESSAGE_TYPE_METHOD_CALL: 04696 return "method_call"; 04697 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 04698 return "method_return"; 04699 case DBUS_MESSAGE_TYPE_SIGNAL: 04700 return "signal"; 04701 case DBUS_MESSAGE_TYPE_ERROR: 04702 return "error"; 04703 default: 04704 return "invalid"; 04705 } 04706 } 04707 04720 dbus_bool_t 04721 dbus_message_marshal (DBusMessage *msg, 04722 char **marshalled_data_p, 04723 int *len_p) 04724 { 04725 DBusString tmp; 04726 dbus_bool_t was_locked; 04727 04728 _dbus_return_val_if_fail (msg != NULL, FALSE); 04729 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04730 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04731 04732 if (!_dbus_string_init (&tmp)) 04733 return FALSE; 04734 04735 /* Ensure the message is locked, to ensure the length header is filled in. */ 04736 was_locked = msg->locked; 04737 04738 if (!was_locked) 04739 dbus_message_lock (msg); 04740 04741 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04742 goto fail; 04743 04744 *len_p = _dbus_string_get_length (&tmp); 04745 04746 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04747 goto fail; 04748 04749 *len_p = _dbus_string_get_length (&tmp); 04750 04751 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04752 goto fail; 04753 04754 _dbus_string_free (&tmp); 04755 04756 if (!was_locked) 04757 msg->locked = FALSE; 04758 04759 return TRUE; 04760 04761 fail: 04762 _dbus_string_free (&tmp); 04763 04764 if (!was_locked) 04765 msg->locked = FALSE; 04766 04767 return FALSE; 04768 } 04769 04782 DBusMessage * 04783 dbus_message_demarshal (const char *str, 04784 int len, 04785 DBusError *error) 04786 { 04787 DBusMessageLoader *loader; 04788 DBusString *buffer; 04789 DBusMessage *msg; 04790 04791 _dbus_return_val_if_fail (str != NULL, NULL); 04792 04793 loader = _dbus_message_loader_new (); 04794 04795 if (loader == NULL) 04796 return NULL; 04797 04798 _dbus_message_loader_get_buffer (loader, &buffer); 04799 04800 if (!_dbus_string_append_len (buffer, str, len)) 04801 goto fail_oom; 04802 04803 _dbus_message_loader_return_buffer (loader, buffer); 04804 04805 if (!_dbus_message_loader_queue_messages (loader)) 04806 goto fail_oom; 04807 04808 if (_dbus_message_loader_get_is_corrupted (loader)) 04809 goto fail_corrupt; 04810 04811 msg = _dbus_message_loader_pop_message (loader); 04812 04813 if (!msg) 04814 goto fail_oom; 04815 04816 _dbus_message_loader_unref (loader); 04817 return msg; 04818 04819 fail_corrupt: 04820 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04821 _dbus_validity_to_error_message (loader->corruption_reason)); 04822 _dbus_message_loader_unref (loader); 04823 return NULL; 04824 04825 fail_oom: 04826 _DBUS_SET_OOM (error); 04827 _dbus_message_loader_unref (loader); 04828 return NULL; 04829 } 04830 04843 int 04844 dbus_message_demarshal_bytes_needed(const char *buf, 04845 int len) 04846 { 04847 DBusString str; 04848 int byte_order, fields_array_len, header_len, body_len; 04849 DBusValidity validity = DBUS_VALID; 04850 int have_message; 04851 04852 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04853 return 0; 04854 04855 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04856 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04857 _dbus_string_init_const_len (&str, buf, len); 04858 04859 validity = DBUS_VALID; 04860 have_message 04861 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04862 &validity, &byte_order, 04863 &fields_array_len, 04864 &header_len, 04865 &body_len, 04866 &str, 0, 04867 len); 04868 _dbus_string_free (&str); 04869 04870 if (validity == DBUS_VALID) 04871 { 04872 _dbus_assert (have_message || (header_len + body_len) > len); 04873 (void) have_message; /* unused unless asserting */ 04874 return header_len + body_len; 04875 } 04876 else 04877 { 04878 return -1; /* broken! */ 04879 } 04880 } 04881 04884 /* tests in dbus-message-util.c */
1.7.6.1