D-Bus
1.6.8
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-message.c DBusMessage object 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc. 00005 * Copyright (C) 2002, 2003 CodeFactory AB 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include <config.h> 00026 #include "dbus-internals.h" 00027 #include "dbus-marshal-recursive.h" 00028 #include "dbus-marshal-validate.h" 00029 #include "dbus-marshal-byteswap.h" 00030 #include "dbus-marshal-header.h" 00031 #include "dbus-signature.h" 00032 #include "dbus-message-private.h" 00033 #include "dbus-object-tree.h" 00034 #include "dbus-memory.h" 00035 #include "dbus-list.h" 00036 #include "dbus-threads-internal.h" 00037 #ifdef HAVE_UNIX_FD_PASSING 00038 #include "dbus-sysdeps-unix.h" 00039 #endif 00040 00041 #include <string.h> 00042 00043 #define _DBUS_TYPE_IS_STRINGLIKE(type) \ 00044 (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \ 00045 type == DBUS_TYPE_OBJECT_PATH) 00046 00047 static void dbus_message_finalize (DBusMessage *message); 00048 00059 #ifdef DBUS_BUILD_TESTS 00060 static dbus_bool_t 00061 _dbus_enable_message_cache (void) 00062 { 00063 static int enabled = -1; 00064 00065 if (enabled < 0) 00066 { 00067 const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE"); 00068 00069 enabled = TRUE; 00070 00071 if (s && *s) 00072 { 00073 if (*s == '0') 00074 enabled = FALSE; 00075 else if (*s == '1') 00076 enabled = TRUE; 00077 else 00078 _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'", 00079 s); 00080 } 00081 } 00082 00083 return enabled; 00084 } 00085 #else 00086 /* constant expression, should be optimized away */ 00087 # define _dbus_enable_message_cache() (TRUE) 00088 #endif 00089 00090 #ifndef _dbus_message_trace_ref 00091 void 00092 _dbus_message_trace_ref (DBusMessage *message, 00093 int old_refcount, 00094 int new_refcount, 00095 const char *why) 00096 { 00097 static int enabled = -1; 00098 00099 _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why, 00100 "DBUS_MESSAGE_TRACE", &enabled); 00101 } 00102 #endif 00103 00104 /* Not thread locked, but strictly const/read-only so should be OK 00105 */ 00107 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, ""); 00108 00109 /* these have wacky values to help trap uninitialized iterators; 00110 * but has to fit in 3 bits 00111 */ 00112 enum { 00113 DBUS_MESSAGE_ITER_TYPE_READER = 3, 00114 DBUS_MESSAGE_ITER_TYPE_WRITER = 7 00115 }; 00116 00118 typedef struct DBusMessageRealIter DBusMessageRealIter; 00119 00125 struct DBusMessageRealIter 00126 { 00127 DBusMessage *message; 00128 dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 00129 dbus_uint32_t iter_type : 3; 00130 dbus_uint32_t sig_refcount : 8; 00131 union 00132 { 00133 DBusTypeWriter writer; 00134 DBusTypeReader reader; 00135 } u; 00136 }; 00137 00138 static void 00139 get_const_signature (DBusHeader *header, 00140 const DBusString **type_str_p, 00141 int *type_pos_p) 00142 { 00143 if (_dbus_header_get_field_raw (header, 00144 DBUS_HEADER_FIELD_SIGNATURE, 00145 type_str_p, 00146 type_pos_p)) 00147 { 00148 *type_pos_p += 1; /* skip the signature length which is 1 byte */ 00149 } 00150 else 00151 { 00152 *type_str_p = &_dbus_empty_signature_str; 00153 *type_pos_p = 0; 00154 } 00155 } 00156 00162 static void 00163 _dbus_message_byteswap (DBusMessage *message) 00164 { 00165 const DBusString *type_str; 00166 int type_pos; 00167 char byte_order; 00168 00169 byte_order = _dbus_header_get_byte_order (&message->header); 00170 00171 if (byte_order == DBUS_COMPILER_BYTE_ORDER) 00172 return; 00173 00174 _dbus_verbose ("Swapping message into compiler byte order\n"); 00175 00176 get_const_signature (&message->header, &type_str, &type_pos); 00177 00178 _dbus_marshal_byteswap (type_str, type_pos, 00179 byte_order, 00180 DBUS_COMPILER_BYTE_ORDER, 00181 &message->body, 0); 00182 00183 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER); 00184 _dbus_assert (_dbus_header_get_byte_order (&message->header) == 00185 DBUS_COMPILER_BYTE_ORDER); 00186 } 00187 00194 #define ensure_byte_order(message) _dbus_message_byteswap (message) 00195 00206 void 00207 _dbus_message_get_network_data (DBusMessage *message, 00208 const DBusString **header, 00209 const DBusString **body) 00210 { 00211 _dbus_assert (message->locked); 00212 00213 *header = &message->header.data; 00214 *body = &message->body; 00215 } 00216 00226 void _dbus_message_get_unix_fds(DBusMessage *message, 00227 const int **fds, 00228 unsigned *n_fds) 00229 { 00230 _dbus_assert (message->locked); 00231 00232 #ifdef HAVE_UNIX_FD_PASSING 00233 *fds = message->unix_fds; 00234 *n_fds = message->n_unix_fds; 00235 #else 00236 *fds = NULL; 00237 *n_fds = 0; 00238 #endif 00239 } 00240 00252 void 00253 dbus_message_set_serial (DBusMessage *message, 00254 dbus_uint32_t serial) 00255 { 00256 _dbus_return_if_fail (message != NULL); 00257 _dbus_return_if_fail (!message->locked); 00258 00259 _dbus_header_set_serial (&message->header, serial); 00260 } 00261 00278 void 00279 _dbus_message_add_counter_link (DBusMessage *message, 00280 DBusList *link) 00281 { 00282 /* right now we don't recompute the delta when message 00283 * size changes, and that's OK for current purposes 00284 * I think, but could be important to change later. 00285 * Do recompute it whenever there are no outstanding counters, 00286 * since it's basically free. 00287 */ 00288 if (message->counters == NULL) 00289 { 00290 message->size_counter_delta = 00291 _dbus_string_get_length (&message->header.data) + 00292 _dbus_string_get_length (&message->body); 00293 00294 #ifdef HAVE_UNIX_FD_PASSING 00295 message->unix_fd_counter_delta = message->n_unix_fds; 00296 #endif 00297 00298 #if 0 00299 _dbus_verbose ("message has size %ld\n", 00300 message->size_counter_delta); 00301 #endif 00302 } 00303 00304 _dbus_list_append_link (&message->counters, link); 00305 00306 _dbus_counter_adjust_size (link->data, message->size_counter_delta); 00307 00308 #ifdef HAVE_UNIX_FD_PASSING 00309 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta); 00310 #endif 00311 } 00312 00327 dbus_bool_t 00328 _dbus_message_add_counter (DBusMessage *message, 00329 DBusCounter *counter) 00330 { 00331 DBusList *link; 00332 00333 link = _dbus_list_alloc_link (counter); 00334 if (link == NULL) 00335 return FALSE; 00336 00337 _dbus_counter_ref (counter); 00338 _dbus_message_add_counter_link (message, link); 00339 00340 return TRUE; 00341 } 00342 00350 void 00351 _dbus_message_remove_counter (DBusMessage *message, 00352 DBusCounter *counter) 00353 { 00354 DBusList *link; 00355 00356 link = _dbus_list_find_last (&message->counters, 00357 counter); 00358 _dbus_assert (link != NULL); 00359 00360 _dbus_list_remove_link (&message->counters, link); 00361 00362 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00363 00364 #ifdef HAVE_UNIX_FD_PASSING 00365 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00366 #endif 00367 00368 _dbus_counter_notify (counter); 00369 _dbus_counter_unref (counter); 00370 } 00371 00382 void 00383 dbus_message_lock (DBusMessage *message) 00384 { 00385 if (!message->locked) 00386 { 00387 _dbus_header_update_lengths (&message->header, 00388 _dbus_string_get_length (&message->body)); 00389 00390 /* must have a signature if you have a body */ 00391 _dbus_assert (_dbus_string_get_length (&message->body) == 0 || 00392 dbus_message_get_signature (message) != NULL); 00393 00394 message->locked = TRUE; 00395 } 00396 } 00397 00398 static dbus_bool_t 00399 set_or_delete_string_field (DBusMessage *message, 00400 int field, 00401 int typecode, 00402 const char *value) 00403 { 00404 if (value == NULL) 00405 return _dbus_header_delete_field (&message->header, field); 00406 else 00407 return _dbus_header_set_field_basic (&message->header, 00408 field, 00409 typecode, 00410 &value); 00411 } 00412 00413 #if 0 00414 /* Probably we don't need to use this */ 00438 static dbus_bool_t 00439 _dbus_message_set_signature (DBusMessage *message, 00440 const char *signature) 00441 { 00442 _dbus_return_val_if_fail (message != NULL, FALSE); 00443 _dbus_return_val_if_fail (!message->locked, FALSE); 00444 _dbus_return_val_if_fail (signature == NULL || 00445 _dbus_check_is_valid_signature (signature)); 00446 /* can't delete the signature if you have a message body */ 00447 _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || 00448 signature != NULL); 00449 00450 return set_or_delete_string_field (message, 00451 DBUS_HEADER_FIELD_SIGNATURE, 00452 DBUS_TYPE_SIGNATURE, 00453 signature); 00454 } 00455 #endif 00456 00457 /* Message Cache 00458 * 00459 * We cache some DBusMessage to reduce the overhead of allocating 00460 * them. In my profiling this consistently made about an 8% 00461 * difference. It avoids the malloc for the message, the malloc for 00462 * the slot list, the malloc for the header string and body string, 00463 * and the associated free() calls. It does introduce another global 00464 * lock which could be a performance issue in certain cases. 00465 * 00466 * For the echo client/server the round trip time goes from around 00467 * .000077 to .000069 with the message cache on my laptop. The sysprof 00468 * change is as follows (numbers are cumulative percentage): 00469 * 00470 * with message cache implemented as array as it is now (0.000069 per): 00471 * new_empty_header 1.46 00472 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache) 00473 * mutex_unlock 0.25 00474 * self 0.41 00475 * unref 2.24 00476 * self 0.68 00477 * list_clear 0.43 00478 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache) 00479 * mutex_unlock 0.25 00480 * 00481 * with message cache implemented as list (0.000070 per roundtrip): 00482 * new_empty_header 2.72 00483 * list_pop_first 1.88 00484 * unref 3.3 00485 * list_prepend 1.63 00486 * 00487 * without cache (0.000077 per roundtrip): 00488 * new_empty_header 6.7 00489 * string_init_preallocated 3.43 00490 * dbus_malloc 2.43 00491 * dbus_malloc0 2.59 00492 * 00493 * unref 4.02 00494 * string_free 1.82 00495 * dbus_free 1.63 00496 * dbus_free 0.71 00497 * 00498 * If you implement the message_cache with a list, the primary reason 00499 * it's slower is that you add another thread lock (on the DBusList 00500 * mempool). 00501 */ 00502 00504 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE 00505 00507 #define MAX_MESSAGE_CACHE_SIZE 5 00508 00509 _DBUS_DEFINE_GLOBAL_LOCK (message_cache); 00510 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; 00511 static int message_cache_count = 0; 00512 static dbus_bool_t message_cache_shutdown_registered = FALSE; 00513 00514 static void 00515 dbus_message_cache_shutdown (void *data) 00516 { 00517 int i; 00518 00519 _DBUS_LOCK (message_cache); 00520 00521 i = 0; 00522 while (i < MAX_MESSAGE_CACHE_SIZE) 00523 { 00524 if (message_cache[i]) 00525 dbus_message_finalize (message_cache[i]); 00526 00527 ++i; 00528 } 00529 00530 message_cache_count = 0; 00531 message_cache_shutdown_registered = FALSE; 00532 00533 _DBUS_UNLOCK (message_cache); 00534 } 00535 00543 static DBusMessage* 00544 dbus_message_get_cached (void) 00545 { 00546 DBusMessage *message; 00547 int i; 00548 00549 message = NULL; 00550 00551 _DBUS_LOCK (message_cache); 00552 00553 _dbus_assert (message_cache_count >= 0); 00554 00555 if (message_cache_count == 0) 00556 { 00557 _DBUS_UNLOCK (message_cache); 00558 return NULL; 00559 } 00560 00561 /* This is not necessarily true unless count > 0, and 00562 * message_cache is uninitialized until the shutdown is 00563 * registered 00564 */ 00565 _dbus_assert (message_cache_shutdown_registered); 00566 00567 i = 0; 00568 while (i < MAX_MESSAGE_CACHE_SIZE) 00569 { 00570 if (message_cache[i]) 00571 { 00572 message = message_cache[i]; 00573 message_cache[i] = NULL; 00574 message_cache_count -= 1; 00575 break; 00576 } 00577 ++i; 00578 } 00579 _dbus_assert (message_cache_count >= 0); 00580 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00581 _dbus_assert (message != NULL); 00582 00583 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00584 00585 _dbus_assert (message->counters == NULL); 00586 00587 _DBUS_UNLOCK (message_cache); 00588 00589 return message; 00590 } 00591 00592 #ifdef HAVE_UNIX_FD_PASSING 00593 static void 00594 close_unix_fds(int *fds, unsigned *n_fds) 00595 { 00596 DBusError e; 00597 int i; 00598 00599 if (*n_fds <= 0) 00600 return; 00601 00602 dbus_error_init(&e); 00603 00604 for (i = 0; i < *n_fds; i++) 00605 { 00606 if (!_dbus_close(fds[i], &e)) 00607 { 00608 _dbus_warn("Failed to close file descriptor: %s\n", e.message); 00609 dbus_error_free(&e); 00610 } 00611 } 00612 00613 *n_fds = 0; 00614 00615 /* We don't free the array here, in case we can recycle it later */ 00616 } 00617 #endif 00618 00619 static void 00620 free_counter (void *element, 00621 void *data) 00622 { 00623 DBusCounter *counter = element; 00624 DBusMessage *message = data; 00625 00626 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00627 #ifdef HAVE_UNIX_FD_PASSING 00628 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00629 #endif 00630 00631 _dbus_counter_notify (counter); 00632 _dbus_counter_unref (counter); 00633 } 00634 00640 static void 00641 dbus_message_cache_or_finalize (DBusMessage *message) 00642 { 00643 dbus_bool_t was_cached; 00644 int i; 00645 00646 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00647 00648 /* This calls application code and has to be done first thing 00649 * without holding the lock 00650 */ 00651 _dbus_data_slot_list_clear (&message->slot_list); 00652 00653 _dbus_list_foreach (&message->counters, 00654 free_counter, message); 00655 _dbus_list_clear (&message->counters); 00656 00657 #ifdef HAVE_UNIX_FD_PASSING 00658 close_unix_fds(message->unix_fds, &message->n_unix_fds); 00659 #endif 00660 00661 was_cached = FALSE; 00662 00663 _DBUS_LOCK (message_cache); 00664 00665 if (!message_cache_shutdown_registered) 00666 { 00667 _dbus_assert (message_cache_count == 0); 00668 00669 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL)) 00670 goto out; 00671 00672 i = 0; 00673 while (i < MAX_MESSAGE_CACHE_SIZE) 00674 { 00675 message_cache[i] = NULL; 00676 ++i; 00677 } 00678 00679 message_cache_shutdown_registered = TRUE; 00680 } 00681 00682 _dbus_assert (message_cache_count >= 0); 00683 00684 if (!_dbus_enable_message_cache ()) 00685 goto out; 00686 00687 if ((_dbus_string_get_length (&message->header.data) + 00688 _dbus_string_get_length (&message->body)) > 00689 MAX_MESSAGE_SIZE_TO_CACHE) 00690 goto out; 00691 00692 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE) 00693 goto out; 00694 00695 /* Find empty slot */ 00696 i = 0; 00697 while (message_cache[i] != NULL) 00698 ++i; 00699 00700 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00701 00702 _dbus_assert (message_cache[i] == NULL); 00703 message_cache[i] = message; 00704 message_cache_count += 1; 00705 was_cached = TRUE; 00706 #ifndef DBUS_DISABLE_CHECKS 00707 message->in_cache = TRUE; 00708 #endif 00709 00710 out: 00711 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00712 00713 _DBUS_UNLOCK (message_cache); 00714 00715 if (!was_cached) 00716 dbus_message_finalize (message); 00717 } 00718 00719 #ifndef DBUS_DISABLE_CHECKS 00720 static dbus_bool_t 00721 _dbus_message_iter_check (DBusMessageRealIter *iter) 00722 { 00723 char byte_order; 00724 00725 if (iter == NULL) 00726 { 00727 _dbus_warn_check_failed ("dbus message iterator is NULL\n"); 00728 return FALSE; 00729 } 00730 00731 byte_order = _dbus_header_get_byte_order (&iter->message->header); 00732 00733 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER) 00734 { 00735 if (iter->u.reader.byte_order != byte_order) 00736 { 00737 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n"); 00738 return FALSE; 00739 } 00740 /* because we swap the message into compiler order when you init an iter */ 00741 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); 00742 } 00743 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) 00744 { 00745 if (iter->u.writer.byte_order != byte_order) 00746 { 00747 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n"); 00748 return FALSE; 00749 } 00750 /* because we swap the message into compiler order when you init an iter */ 00751 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); 00752 } 00753 else 00754 { 00755 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n"); 00756 return FALSE; 00757 } 00758 00759 if (iter->changed_stamp != iter->message->changed_stamp) 00760 { 00761 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); 00762 return FALSE; 00763 } 00764 00765 return TRUE; 00766 } 00767 #endif /* DBUS_DISABLE_CHECKS */ 00768 00783 dbus_bool_t 00784 _dbus_message_iter_get_args_valist (DBusMessageIter *iter, 00785 DBusError *error, 00786 int first_arg_type, 00787 va_list var_args) 00788 { 00789 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 00790 int spec_type, msg_type, i; 00791 dbus_bool_t retval; 00792 00793 _dbus_assert (_dbus_message_iter_check (real)); 00794 00795 retval = FALSE; 00796 00797 spec_type = first_arg_type; 00798 i = 0; 00799 00800 while (spec_type != DBUS_TYPE_INVALID) 00801 { 00802 msg_type = dbus_message_iter_get_arg_type (iter); 00803 00804 if (msg_type != spec_type) 00805 { 00806 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00807 "Argument %d is specified to be of type \"%s\", but " 00808 "is actually of type \"%s\"\n", i, 00809 _dbus_type_to_string (spec_type), 00810 _dbus_type_to_string (msg_type)); 00811 00812 goto out; 00813 } 00814 00815 if (spec_type == DBUS_TYPE_UNIX_FD) 00816 { 00817 #ifdef HAVE_UNIX_FD_PASSING 00818 DBusBasicValue idx; 00819 int *pfd, nfd; 00820 00821 pfd = va_arg (var_args, int*); 00822 _dbus_assert(pfd); 00823 00824 _dbus_type_reader_read_basic(&real->u.reader, &idx); 00825 00826 if (idx.u32 >= real->message->n_unix_fds) 00827 { 00828 dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE, 00829 "Message refers to file descriptor at index %i," 00830 "but has only %i descriptors attached.\n", 00831 idx.u32, 00832 real->message->n_unix_fds); 00833 goto out; 00834 } 00835 00836 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0) 00837 goto out; 00838 00839 *pfd = nfd; 00840 #else 00841 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00842 "Platform does not support file desciptor passing.\n"); 00843 goto out; 00844 #endif 00845 } 00846 else if (dbus_type_is_basic (spec_type)) 00847 { 00848 DBusBasicValue *ptr; 00849 00850 ptr = va_arg (var_args, DBusBasicValue*); 00851 00852 _dbus_assert (ptr != NULL); 00853 00854 _dbus_type_reader_read_basic (&real->u.reader, 00855 ptr); 00856 } 00857 else if (spec_type == DBUS_TYPE_ARRAY) 00858 { 00859 int element_type; 00860 int spec_element_type; 00861 const DBusBasicValue **ptr; 00862 int *n_elements_p; 00863 DBusTypeReader array; 00864 00865 spec_element_type = va_arg (var_args, int); 00866 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 00867 00868 if (spec_element_type != element_type) 00869 { 00870 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00871 "Argument %d is specified to be an array of \"%s\", but " 00872 "is actually an array of \"%s\"\n", 00873 i, 00874 _dbus_type_to_string (spec_element_type), 00875 _dbus_type_to_string (element_type)); 00876 00877 goto out; 00878 } 00879 00880 if (dbus_type_is_fixed (spec_element_type) && 00881 element_type != DBUS_TYPE_UNIX_FD) 00882 { 00883 ptr = va_arg (var_args, const DBusBasicValue**); 00884 n_elements_p = va_arg (var_args, int*); 00885 00886 _dbus_assert (ptr != NULL); 00887 _dbus_assert (n_elements_p != NULL); 00888 00889 _dbus_type_reader_recurse (&real->u.reader, &array); 00890 00891 _dbus_type_reader_read_fixed_multi (&array, 00892 (void *) ptr, n_elements_p); 00893 } 00894 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type)) 00895 { 00896 char ***str_array_p; 00897 int n_elements; 00898 char **str_array; 00899 00900 str_array_p = va_arg (var_args, char***); 00901 n_elements_p = va_arg (var_args, int*); 00902 00903 _dbus_assert (str_array_p != NULL); 00904 _dbus_assert (n_elements_p != NULL); 00905 00906 /* Count elements in the array */ 00907 _dbus_type_reader_recurse (&real->u.reader, &array); 00908 00909 n_elements = 0; 00910 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 00911 { 00912 ++n_elements; 00913 _dbus_type_reader_next (&array); 00914 } 00915 00916 str_array = dbus_new0 (char*, n_elements + 1); 00917 if (str_array == NULL) 00918 { 00919 _DBUS_SET_OOM (error); 00920 goto out; 00921 } 00922 00923 /* Now go through and dup each string */ 00924 _dbus_type_reader_recurse (&real->u.reader, &array); 00925 00926 i = 0; 00927 while (i < n_elements) 00928 { 00929 const char *s; 00930 _dbus_type_reader_read_basic (&array, 00931 (void *) &s); 00932 00933 str_array[i] = _dbus_strdup (s); 00934 if (str_array[i] == NULL) 00935 { 00936 dbus_free_string_array (str_array); 00937 _DBUS_SET_OOM (error); 00938 goto out; 00939 } 00940 00941 ++i; 00942 00943 if (!_dbus_type_reader_next (&array)) 00944 _dbus_assert (i == n_elements); 00945 } 00946 00947 _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); 00948 _dbus_assert (i == n_elements); 00949 _dbus_assert (str_array[i] == NULL); 00950 00951 *str_array_p = str_array; 00952 *n_elements_p = n_elements; 00953 } 00954 #ifndef DBUS_DISABLE_CHECKS 00955 else 00956 { 00957 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", 00958 _DBUS_FUNCTION_NAME); 00959 goto out; 00960 } 00961 #endif 00962 } 00963 #ifndef DBUS_DISABLE_CHECKS 00964 else 00965 { 00966 _dbus_warn ("you can only read arrays and basic types with %s for now\n", 00967 _DBUS_FUNCTION_NAME); 00968 goto out; 00969 } 00970 #endif 00971 00972 spec_type = va_arg (var_args, int); 00973 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) 00974 { 00975 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00976 "Message has only %d arguments, but more were expected", i); 00977 goto out; 00978 } 00979 00980 i++; 00981 } 00982 00983 retval = TRUE; 00984 00985 out: 00986 00987 return retval; 00988 } 00989 01048 dbus_uint32_t 01049 dbus_message_get_serial (DBusMessage *message) 01050 { 01051 _dbus_return_val_if_fail (message != NULL, 0); 01052 01053 return _dbus_header_get_serial (&message->header); 01054 } 01055 01064 dbus_bool_t 01065 dbus_message_set_reply_serial (DBusMessage *message, 01066 dbus_uint32_t reply_serial) 01067 { 01068 _dbus_return_val_if_fail (message != NULL, FALSE); 01069 _dbus_return_val_if_fail (!message->locked, FALSE); 01070 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */ 01071 01072 return _dbus_header_set_field_basic (&message->header, 01073 DBUS_HEADER_FIELD_REPLY_SERIAL, 01074 DBUS_TYPE_UINT32, 01075 &reply_serial); 01076 } 01077 01084 dbus_uint32_t 01085 dbus_message_get_reply_serial (DBusMessage *message) 01086 { 01087 dbus_uint32_t v_UINT32; 01088 01089 _dbus_return_val_if_fail (message != NULL, 0); 01090 01091 if (_dbus_header_get_field_basic (&message->header, 01092 DBUS_HEADER_FIELD_REPLY_SERIAL, 01093 DBUS_TYPE_UINT32, 01094 &v_UINT32)) 01095 return v_UINT32; 01096 else 01097 return 0; 01098 } 01099 01100 static void 01101 dbus_message_finalize (DBusMessage *message) 01102 { 01103 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01104 01105 /* This calls application callbacks! */ 01106 _dbus_data_slot_list_free (&message->slot_list); 01107 01108 _dbus_list_foreach (&message->counters, 01109 free_counter, message); 01110 _dbus_list_clear (&message->counters); 01111 01112 _dbus_header_free (&message->header); 01113 _dbus_string_free (&message->body); 01114 01115 #ifdef HAVE_UNIX_FD_PASSING 01116 close_unix_fds(message->unix_fds, &message->n_unix_fds); 01117 dbus_free(message->unix_fds); 01118 #endif 01119 01120 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01121 01122 dbus_free (message); 01123 } 01124 01125 static DBusMessage* 01126 dbus_message_new_empty_header (void) 01127 { 01128 DBusMessage *message; 01129 dbus_bool_t from_cache; 01130 01131 message = dbus_message_get_cached (); 01132 01133 if (message != NULL) 01134 { 01135 from_cache = TRUE; 01136 } 01137 else 01138 { 01139 from_cache = FALSE; 01140 message = dbus_new0 (DBusMessage, 1); 01141 if (message == NULL) 01142 return NULL; 01143 #ifndef DBUS_DISABLE_CHECKS 01144 message->generation = _dbus_current_generation; 01145 #endif 01146 01147 #ifdef HAVE_UNIX_FD_PASSING 01148 message->unix_fds = NULL; 01149 message->n_unix_fds_allocated = 0; 01150 #endif 01151 } 01152 01153 _dbus_atomic_inc (&message->refcount); 01154 01155 _dbus_message_trace_ref (message, 0, 1, "new_empty_header"); 01156 01157 message->locked = FALSE; 01158 #ifndef DBUS_DISABLE_CHECKS 01159 message->in_cache = FALSE; 01160 #endif 01161 message->counters = NULL; 01162 message->size_counter_delta = 0; 01163 message->changed_stamp = 0; 01164 01165 #ifdef HAVE_UNIX_FD_PASSING 01166 message->n_unix_fds = 0; 01167 message->n_unix_fds_allocated = 0; 01168 message->unix_fd_counter_delta = 0; 01169 #endif 01170 01171 if (!from_cache) 01172 _dbus_data_slot_list_init (&message->slot_list); 01173 01174 if (from_cache) 01175 { 01176 _dbus_header_reinit (&message->header); 01177 _dbus_string_set_length (&message->body, 0); 01178 } 01179 else 01180 { 01181 if (!_dbus_header_init (&message->header)) 01182 { 01183 dbus_free (message); 01184 return NULL; 01185 } 01186 01187 if (!_dbus_string_init_preallocated (&message->body, 32)) 01188 { 01189 _dbus_header_free (&message->header); 01190 dbus_free (message); 01191 return NULL; 01192 } 01193 } 01194 01195 return message; 01196 } 01197 01210 DBusMessage* 01211 dbus_message_new (int message_type) 01212 { 01213 DBusMessage *message; 01214 01215 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL); 01216 01217 message = dbus_message_new_empty_header (); 01218 if (message == NULL) 01219 return NULL; 01220 01221 if (!_dbus_header_create (&message->header, 01222 DBUS_COMPILER_BYTE_ORDER, 01223 message_type, 01224 NULL, NULL, NULL, NULL, NULL)) 01225 { 01226 dbus_message_unref (message); 01227 return NULL; 01228 } 01229 01230 return message; 01231 } 01232 01254 DBusMessage* 01255 dbus_message_new_method_call (const char *destination, 01256 const char *path, 01257 const char *interface, 01258 const char *method) 01259 { 01260 DBusMessage *message; 01261 01262 _dbus_return_val_if_fail (path != NULL, NULL); 01263 _dbus_return_val_if_fail (method != NULL, NULL); 01264 _dbus_return_val_if_fail (destination == NULL || 01265 _dbus_check_is_valid_bus_name (destination), NULL); 01266 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01267 _dbus_return_val_if_fail (interface == NULL || 01268 _dbus_check_is_valid_interface (interface), NULL); 01269 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); 01270 01271 message = dbus_message_new_empty_header (); 01272 if (message == NULL) 01273 return NULL; 01274 01275 if (!_dbus_header_create (&message->header, 01276 DBUS_COMPILER_BYTE_ORDER, 01277 DBUS_MESSAGE_TYPE_METHOD_CALL, 01278 destination, path, interface, method, NULL)) 01279 { 01280 dbus_message_unref (message); 01281 return NULL; 01282 } 01283 01284 return message; 01285 } 01286 01294 DBusMessage* 01295 dbus_message_new_method_return (DBusMessage *method_call) 01296 { 01297 DBusMessage *message; 01298 const char *sender; 01299 01300 _dbus_return_val_if_fail (method_call != NULL, NULL); 01301 01302 sender = dbus_message_get_sender (method_call); 01303 01304 /* sender is allowed to be null here in peer-to-peer case */ 01305 01306 message = dbus_message_new_empty_header (); 01307 if (message == NULL) 01308 return NULL; 01309 01310 if (!_dbus_header_create (&message->header, 01311 DBUS_COMPILER_BYTE_ORDER, 01312 DBUS_MESSAGE_TYPE_METHOD_RETURN, 01313 sender, NULL, NULL, NULL, NULL)) 01314 { 01315 dbus_message_unref (message); 01316 return NULL; 01317 } 01318 01319 dbus_message_set_no_reply (message, TRUE); 01320 01321 if (!dbus_message_set_reply_serial (message, 01322 dbus_message_get_serial (method_call))) 01323 { 01324 dbus_message_unref (message); 01325 return NULL; 01326 } 01327 01328 return message; 01329 } 01330 01345 DBusMessage* 01346 dbus_message_new_signal (const char *path, 01347 const char *interface, 01348 const char *name) 01349 { 01350 DBusMessage *message; 01351 01352 _dbus_return_val_if_fail (path != NULL, NULL); 01353 _dbus_return_val_if_fail (interface != NULL, NULL); 01354 _dbus_return_val_if_fail (name != NULL, NULL); 01355 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01356 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL); 01357 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); 01358 01359 message = dbus_message_new_empty_header (); 01360 if (message == NULL) 01361 return NULL; 01362 01363 if (!_dbus_header_create (&message->header, 01364 DBUS_COMPILER_BYTE_ORDER, 01365 DBUS_MESSAGE_TYPE_SIGNAL, 01366 NULL, path, interface, name, NULL)) 01367 { 01368 dbus_message_unref (message); 01369 return NULL; 01370 } 01371 01372 dbus_message_set_no_reply (message, TRUE); 01373 01374 return message; 01375 } 01376 01391 DBusMessage* 01392 dbus_message_new_error (DBusMessage *reply_to, 01393 const char *error_name, 01394 const char *error_message) 01395 { 01396 DBusMessage *message; 01397 const char *sender; 01398 DBusMessageIter iter; 01399 01400 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01401 _dbus_return_val_if_fail (error_name != NULL, NULL); 01402 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01403 01404 sender = dbus_message_get_sender (reply_to); 01405 01406 /* sender may be NULL for non-message-bus case or 01407 * when the message bus is dealing with an unregistered 01408 * connection. 01409 */ 01410 message = dbus_message_new_empty_header (); 01411 if (message == NULL) 01412 return NULL; 01413 01414 if (!_dbus_header_create (&message->header, 01415 DBUS_COMPILER_BYTE_ORDER, 01416 DBUS_MESSAGE_TYPE_ERROR, 01417 sender, NULL, NULL, NULL, error_name)) 01418 { 01419 dbus_message_unref (message); 01420 return NULL; 01421 } 01422 01423 dbus_message_set_no_reply (message, TRUE); 01424 01425 if (!dbus_message_set_reply_serial (message, 01426 dbus_message_get_serial (reply_to))) 01427 { 01428 dbus_message_unref (message); 01429 return NULL; 01430 } 01431 01432 if (error_message != NULL) 01433 { 01434 dbus_message_iter_init_append (message, &iter); 01435 if (!dbus_message_iter_append_basic (&iter, 01436 DBUS_TYPE_STRING, 01437 &error_message)) 01438 { 01439 dbus_message_unref (message); 01440 return NULL; 01441 } 01442 } 01443 01444 return message; 01445 } 01446 01463 DBusMessage* 01464 dbus_message_new_error_printf (DBusMessage *reply_to, 01465 const char *error_name, 01466 const char *error_format, 01467 ...) 01468 { 01469 va_list args; 01470 DBusString str; 01471 DBusMessage *message; 01472 01473 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01474 _dbus_return_val_if_fail (error_name != NULL, NULL); 01475 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01476 01477 if (!_dbus_string_init (&str)) 01478 return NULL; 01479 01480 va_start (args, error_format); 01481 01482 if (_dbus_string_append_printf_valist (&str, error_format, args)) 01483 message = dbus_message_new_error (reply_to, error_name, 01484 _dbus_string_get_const_data (&str)); 01485 else 01486 message = NULL; 01487 01488 _dbus_string_free (&str); 01489 01490 va_end (args); 01491 01492 return message; 01493 } 01494 01495 01508 DBusMessage * 01509 dbus_message_copy (const DBusMessage *message) 01510 { 01511 DBusMessage *retval; 01512 01513 _dbus_return_val_if_fail (message != NULL, NULL); 01514 01515 retval = dbus_new0 (DBusMessage, 1); 01516 if (retval == NULL) 01517 return NULL; 01518 01519 _dbus_atomic_inc (&retval->refcount); 01520 01521 retval->locked = FALSE; 01522 #ifndef DBUS_DISABLE_CHECKS 01523 retval->generation = message->generation; 01524 #endif 01525 01526 if (!_dbus_header_copy (&message->header, &retval->header)) 01527 { 01528 dbus_free (retval); 01529 return NULL; 01530 } 01531 01532 if (!_dbus_string_init_preallocated (&retval->body, 01533 _dbus_string_get_length (&message->body))) 01534 { 01535 _dbus_header_free (&retval->header); 01536 dbus_free (retval); 01537 return NULL; 01538 } 01539 01540 if (!_dbus_string_copy (&message->body, 0, 01541 &retval->body, 0)) 01542 goto failed_copy; 01543 01544 #ifdef HAVE_UNIX_FD_PASSING 01545 retval->unix_fds = dbus_new(int, message->n_unix_fds); 01546 if (retval->unix_fds == NULL && message->n_unix_fds > 0) 01547 goto failed_copy; 01548 01549 retval->n_unix_fds_allocated = message->n_unix_fds; 01550 01551 for (retval->n_unix_fds = 0; 01552 retval->n_unix_fds < message->n_unix_fds; 01553 retval->n_unix_fds++) 01554 { 01555 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL); 01556 01557 if (retval->unix_fds[retval->n_unix_fds] < 0) 01558 goto failed_copy; 01559 } 01560 01561 #endif 01562 01563 _dbus_message_trace_ref (retval, 0, 1, "copy"); 01564 return retval; 01565 01566 failed_copy: 01567 _dbus_header_free (&retval->header); 01568 _dbus_string_free (&retval->body); 01569 01570 #ifdef HAVE_UNIX_FD_PASSING 01571 close_unix_fds(retval->unix_fds, &retval->n_unix_fds); 01572 dbus_free(retval->unix_fds); 01573 #endif 01574 01575 dbus_free (retval); 01576 01577 return NULL; 01578 } 01579 01580 01588 DBusMessage * 01589 dbus_message_ref (DBusMessage *message) 01590 { 01591 dbus_int32_t old_refcount; 01592 01593 _dbus_return_val_if_fail (message != NULL, NULL); 01594 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); 01595 _dbus_return_val_if_fail (!message->in_cache, NULL); 01596 01597 old_refcount = _dbus_atomic_inc (&message->refcount); 01598 _dbus_assert (old_refcount >= 1); 01599 _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref"); 01600 01601 return message; 01602 } 01603 01611 void 01612 dbus_message_unref (DBusMessage *message) 01613 { 01614 dbus_int32_t old_refcount; 01615 01616 _dbus_return_if_fail (message != NULL); 01617 _dbus_return_if_fail (message->generation == _dbus_current_generation); 01618 _dbus_return_if_fail (!message->in_cache); 01619 01620 old_refcount = _dbus_atomic_dec (&message->refcount); 01621 01622 _dbus_assert (old_refcount >= 1); 01623 01624 _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref"); 01625 01626 if (old_refcount == 1) 01627 { 01628 /* Calls application callbacks! */ 01629 dbus_message_cache_or_finalize (message); 01630 } 01631 } 01632 01643 int 01644 dbus_message_get_type (DBusMessage *message) 01645 { 01646 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID); 01647 01648 return _dbus_header_get_message_type (&message->header); 01649 } 01650 01713 dbus_bool_t 01714 dbus_message_append_args (DBusMessage *message, 01715 int first_arg_type, 01716 ...) 01717 { 01718 dbus_bool_t retval; 01719 va_list var_args; 01720 01721 _dbus_return_val_if_fail (message != NULL, FALSE); 01722 01723 va_start (var_args, first_arg_type); 01724 retval = dbus_message_append_args_valist (message, 01725 first_arg_type, 01726 var_args); 01727 va_end (var_args); 01728 01729 return retval; 01730 } 01731 01745 dbus_bool_t 01746 dbus_message_append_args_valist (DBusMessage *message, 01747 int first_arg_type, 01748 va_list var_args) 01749 { 01750 int type; 01751 DBusMessageIter iter; 01752 01753 _dbus_return_val_if_fail (message != NULL, FALSE); 01754 01755 type = first_arg_type; 01756 01757 dbus_message_iter_init_append (message, &iter); 01758 01759 while (type != DBUS_TYPE_INVALID) 01760 { 01761 if (dbus_type_is_basic (type)) 01762 { 01763 const DBusBasicValue *value; 01764 value = va_arg (var_args, const DBusBasicValue*); 01765 01766 if (!dbus_message_iter_append_basic (&iter, 01767 type, 01768 value)) 01769 goto failed; 01770 } 01771 else if (type == DBUS_TYPE_ARRAY) 01772 { 01773 int element_type; 01774 DBusMessageIter array; 01775 char buf[2]; 01776 01777 element_type = va_arg (var_args, int); 01778 01779 buf[0] = element_type; 01780 buf[1] = '\0'; 01781 if (!dbus_message_iter_open_container (&iter, 01782 DBUS_TYPE_ARRAY, 01783 buf, 01784 &array)) 01785 goto failed; 01786 01787 if (dbus_type_is_fixed (element_type) && 01788 element_type != DBUS_TYPE_UNIX_FD) 01789 { 01790 const DBusBasicValue **value; 01791 int n_elements; 01792 01793 value = va_arg (var_args, const DBusBasicValue**); 01794 n_elements = va_arg (var_args, int); 01795 01796 if (!dbus_message_iter_append_fixed_array (&array, 01797 element_type, 01798 value, 01799 n_elements)) { 01800 dbus_message_iter_abandon_container (&iter, &array); 01801 goto failed; 01802 } 01803 } 01804 else if (_DBUS_TYPE_IS_STRINGLIKE (element_type)) 01805 { 01806 const char ***value_p; 01807 const char **value; 01808 int n_elements; 01809 int i; 01810 01811 value_p = va_arg (var_args, const char***); 01812 n_elements = va_arg (var_args, int); 01813 01814 value = *value_p; 01815 01816 i = 0; 01817 while (i < n_elements) 01818 { 01819 if (!dbus_message_iter_append_basic (&array, 01820 element_type, 01821 &value[i])) { 01822 dbus_message_iter_abandon_container (&iter, &array); 01823 goto failed; 01824 } 01825 ++i; 01826 } 01827 } 01828 else 01829 { 01830 _dbus_warn ("arrays of %s can't be appended with %s for now\n", 01831 _dbus_type_to_string (element_type), 01832 _DBUS_FUNCTION_NAME); 01833 goto failed; 01834 } 01835 01836 if (!dbus_message_iter_close_container (&iter, &array)) 01837 goto failed; 01838 } 01839 #ifndef DBUS_DISABLE_CHECKS 01840 else 01841 { 01842 _dbus_warn ("type %s isn't supported yet in %s\n", 01843 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME); 01844 goto failed; 01845 } 01846 #endif 01847 01848 type = va_arg (var_args, int); 01849 } 01850 01851 return TRUE; 01852 01853 failed: 01854 return FALSE; 01855 } 01856 01901 dbus_bool_t 01902 dbus_message_get_args (DBusMessage *message, 01903 DBusError *error, 01904 int first_arg_type, 01905 ...) 01906 { 01907 dbus_bool_t retval; 01908 va_list var_args; 01909 01910 _dbus_return_val_if_fail (message != NULL, FALSE); 01911 _dbus_return_val_if_error_is_set (error, FALSE); 01912 01913 va_start (var_args, first_arg_type); 01914 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args); 01915 va_end (var_args); 01916 01917 return retval; 01918 } 01919 01930 dbus_bool_t 01931 dbus_message_get_args_valist (DBusMessage *message, 01932 DBusError *error, 01933 int first_arg_type, 01934 va_list var_args) 01935 { 01936 DBusMessageIter iter; 01937 01938 _dbus_return_val_if_fail (message != NULL, FALSE); 01939 _dbus_return_val_if_error_is_set (error, FALSE); 01940 01941 dbus_message_iter_init (message, &iter); 01942 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); 01943 } 01944 01945 static void 01946 _dbus_message_iter_init_common (DBusMessage *message, 01947 DBusMessageRealIter *real, 01948 int iter_type) 01949 { 01950 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); 01951 01952 /* Since the iterator will read or write who-knows-what from the 01953 * message, we need to get in the right byte order 01954 */ 01955 ensure_byte_order (message); 01956 01957 real->message = message; 01958 real->changed_stamp = message->changed_stamp; 01959 real->iter_type = iter_type; 01960 real->sig_refcount = 0; 01961 } 01962 01985 dbus_bool_t 01986 dbus_message_iter_init (DBusMessage *message, 01987 DBusMessageIter *iter) 01988 { 01989 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01990 const DBusString *type_str; 01991 int type_pos; 01992 01993 _dbus_return_val_if_fail (message != NULL, FALSE); 01994 _dbus_return_val_if_fail (iter != NULL, FALSE); 01995 01996 get_const_signature (&message->header, &type_str, &type_pos); 01997 01998 _dbus_message_iter_init_common (message, real, 01999 DBUS_MESSAGE_ITER_TYPE_READER); 02000 02001 _dbus_type_reader_init (&real->u.reader, 02002 _dbus_header_get_byte_order (&message->header), 02003 type_str, type_pos, 02004 &message->body, 02005 0); 02006 02007 return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID; 02008 } 02009 02016 dbus_bool_t 02017 dbus_message_iter_has_next (DBusMessageIter *iter) 02018 { 02019 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02020 02021 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 02022 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02023 02024 return _dbus_type_reader_has_next (&real->u.reader); 02025 } 02026 02035 dbus_bool_t 02036 dbus_message_iter_next (DBusMessageIter *iter) 02037 { 02038 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02039 02040 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 02041 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02042 02043 return _dbus_type_reader_next (&real->u.reader); 02044 } 02045 02060 int 02061 dbus_message_iter_get_arg_type (DBusMessageIter *iter) 02062 { 02063 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02064 02065 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02066 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02067 02068 return _dbus_type_reader_get_current_type (&real->u.reader); 02069 } 02070 02079 int 02080 dbus_message_iter_get_element_type (DBusMessageIter *iter) 02081 { 02082 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02083 02084 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02085 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); 02086 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 02087 02088 return _dbus_type_reader_get_element_type (&real->u.reader); 02089 } 02090 02116 void 02117 dbus_message_iter_recurse (DBusMessageIter *iter, 02118 DBusMessageIter *sub) 02119 { 02120 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02121 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02122 02123 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02124 _dbus_return_if_fail (sub != NULL); 02125 02126 *real_sub = *real; 02127 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader); 02128 } 02129 02141 char * 02142 dbus_message_iter_get_signature (DBusMessageIter *iter) 02143 { 02144 const DBusString *sig; 02145 DBusString retstr; 02146 char *ret; 02147 int start, len; 02148 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02149 02150 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL); 02151 02152 if (!_dbus_string_init (&retstr)) 02153 return NULL; 02154 02155 _dbus_type_reader_get_signature (&real->u.reader, &sig, 02156 &start, &len); 02157 if (!_dbus_string_append_len (&retstr, 02158 _dbus_string_get_const_data (sig) + start, 02159 len)) 02160 return NULL; 02161 if (!_dbus_string_steal_data (&retstr, &ret)) 02162 return NULL; 02163 _dbus_string_free (&retstr); 02164 return ret; 02165 } 02166 02214 void 02215 dbus_message_iter_get_basic (DBusMessageIter *iter, 02216 void *value) 02217 { 02218 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02219 02220 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02221 _dbus_return_if_fail (value != NULL); 02222 02223 if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD) 02224 { 02225 #ifdef HAVE_UNIX_FD_PASSING 02226 DBusBasicValue idx; 02227 02228 _dbus_type_reader_read_basic(&real->u.reader, &idx); 02229 02230 if (idx.u32 >= real->message->n_unix_fds) { 02231 /* Hmm, we cannot really signal an error here, so let's make 02232 sure to return an invalid fd. */ 02233 *((int*) value) = -1; 02234 return; 02235 } 02236 02237 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL); 02238 #else 02239 *((int*) value) = -1; 02240 #endif 02241 } 02242 else 02243 { 02244 _dbus_type_reader_read_basic (&real->u.reader, 02245 value); 02246 } 02247 } 02248 02267 int 02268 dbus_message_iter_get_array_len (DBusMessageIter *iter) 02269 { 02270 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02271 02272 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02273 02274 return _dbus_type_reader_get_array_length (&real->u.reader); 02275 } 02276 02312 void 02313 dbus_message_iter_get_fixed_array (DBusMessageIter *iter, 02314 void *value, 02315 int *n_elements) 02316 { 02317 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02318 #ifndef DBUS_DISABLE_CHECKS 02319 int subtype = _dbus_type_reader_get_current_type(&real->u.reader); 02320 02321 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02322 _dbus_return_if_fail (value != NULL); 02323 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) || 02324 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD)); 02325 #endif 02326 02327 _dbus_type_reader_read_fixed_multi (&real->u.reader, 02328 value, n_elements); 02329 } 02330 02342 void 02343 dbus_message_iter_init_append (DBusMessage *message, 02344 DBusMessageIter *iter) 02345 { 02346 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02347 02348 _dbus_return_if_fail (message != NULL); 02349 _dbus_return_if_fail (iter != NULL); 02350 02351 _dbus_message_iter_init_common (message, real, 02352 DBUS_MESSAGE_ITER_TYPE_WRITER); 02353 02354 /* We create the signature string and point iterators at it "on demand" 02355 * when a value is actually appended. That means that init() never fails 02356 * due to OOM. 02357 */ 02358 _dbus_type_writer_init_types_delayed (&real->u.writer, 02359 _dbus_header_get_byte_order (&message->header), 02360 &message->body, 02361 _dbus_string_get_length (&message->body)); 02362 } 02363 02372 static dbus_bool_t 02373 _dbus_message_iter_open_signature (DBusMessageRealIter *real) 02374 { 02375 DBusString *str; 02376 const DBusString *current_sig; 02377 int current_sig_pos; 02378 02379 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02380 02381 if (real->u.writer.type_str != NULL) 02382 { 02383 _dbus_assert (real->sig_refcount > 0); 02384 real->sig_refcount += 1; 02385 return TRUE; 02386 } 02387 02388 str = dbus_new (DBusString, 1); 02389 if (str == NULL) 02390 return FALSE; 02391 02392 if (!_dbus_header_get_field_raw (&real->message->header, 02393 DBUS_HEADER_FIELD_SIGNATURE, 02394 ¤t_sig, ¤t_sig_pos)) 02395 current_sig = NULL; 02396 02397 if (current_sig) 02398 { 02399 int current_len; 02400 02401 current_len = _dbus_string_get_byte (current_sig, current_sig_pos); 02402 current_sig_pos += 1; /* move on to sig data */ 02403 02404 if (!_dbus_string_init_preallocated (str, current_len + 4)) 02405 { 02406 dbus_free (str); 02407 return FALSE; 02408 } 02409 02410 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len, 02411 str, 0)) 02412 { 02413 _dbus_string_free (str); 02414 dbus_free (str); 02415 return FALSE; 02416 } 02417 } 02418 else 02419 { 02420 if (!_dbus_string_init_preallocated (str, 4)) 02421 { 02422 dbus_free (str); 02423 return FALSE; 02424 } 02425 } 02426 02427 real->sig_refcount = 1; 02428 02429 _dbus_type_writer_add_types (&real->u.writer, 02430 str, _dbus_string_get_length (str)); 02431 return TRUE; 02432 } 02433 02443 static dbus_bool_t 02444 _dbus_message_iter_close_signature (DBusMessageRealIter *real) 02445 { 02446 DBusString *str; 02447 const char *v_STRING; 02448 dbus_bool_t retval; 02449 02450 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02451 _dbus_assert (real->u.writer.type_str != NULL); 02452 _dbus_assert (real->sig_refcount > 0); 02453 02454 real->sig_refcount -= 1; 02455 02456 if (real->sig_refcount > 0) 02457 return TRUE; 02458 _dbus_assert (real->sig_refcount == 0); 02459 02460 retval = TRUE; 02461 02462 str = real->u.writer.type_str; 02463 02464 v_STRING = _dbus_string_get_const_data (str); 02465 if (!_dbus_header_set_field_basic (&real->message->header, 02466 DBUS_HEADER_FIELD_SIGNATURE, 02467 DBUS_TYPE_SIGNATURE, 02468 &v_STRING)) 02469 retval = FALSE; 02470 02471 _dbus_type_writer_remove_types (&real->u.writer); 02472 _dbus_string_free (str); 02473 dbus_free (str); 02474 02475 return retval; 02476 } 02477 02485 static void 02486 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real) 02487 { 02488 DBusString *str; 02489 02490 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02491 _dbus_assert (real->u.writer.type_str != NULL); 02492 _dbus_assert (real->sig_refcount > 0); 02493 02494 real->sig_refcount -= 1; 02495 02496 if (real->sig_refcount > 0) 02497 return; 02498 _dbus_assert (real->sig_refcount == 0); 02499 02500 str = real->u.writer.type_str; 02501 02502 _dbus_type_writer_remove_types (&real->u.writer); 02503 _dbus_string_free (str); 02504 dbus_free (str); 02505 } 02506 02507 #ifndef DBUS_DISABLE_CHECKS 02508 static dbus_bool_t 02509 _dbus_message_iter_append_check (DBusMessageRealIter *iter) 02510 { 02511 if (!_dbus_message_iter_check (iter)) 02512 return FALSE; 02513 02514 if (iter->message->locked) 02515 { 02516 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n"); 02517 return FALSE; 02518 } 02519 02520 return TRUE; 02521 } 02522 #endif /* DBUS_DISABLE_CHECKS */ 02523 02524 #ifdef HAVE_UNIX_FD_PASSING 02525 static int * 02526 expand_fd_array(DBusMessage *m, 02527 unsigned n) 02528 { 02529 _dbus_assert(m); 02530 02531 /* This makes space for adding n new fds to the array and returns a 02532 pointer to the place were the first fd should be put. */ 02533 02534 if (m->n_unix_fds + n > m->n_unix_fds_allocated) 02535 { 02536 unsigned k; 02537 int *p; 02538 02539 /* Make twice as much space as necessary */ 02540 k = (m->n_unix_fds + n) * 2; 02541 02542 /* Allocate at least four */ 02543 if (k < 4) 02544 k = 4; 02545 02546 p = dbus_realloc(m->unix_fds, k * sizeof(int)); 02547 if (p == NULL) 02548 return NULL; 02549 02550 m->unix_fds = p; 02551 m->n_unix_fds_allocated = k; 02552 } 02553 02554 return m->unix_fds + m->n_unix_fds; 02555 } 02556 #endif 02557 02577 dbus_bool_t 02578 dbus_message_iter_append_basic (DBusMessageIter *iter, 02579 int type, 02580 const void *value) 02581 { 02582 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02583 dbus_bool_t ret; 02584 02585 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02586 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02587 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE); 02588 _dbus_return_val_if_fail (value != NULL, FALSE); 02589 02590 #ifndef DBUS_DISABLE_CHECKS 02591 switch (type) 02592 { 02593 const char * const *string_p; 02594 const dbus_bool_t *bool_p; 02595 02596 case DBUS_TYPE_STRING: 02597 string_p = value; 02598 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE); 02599 break; 02600 02601 case DBUS_TYPE_OBJECT_PATH: 02602 string_p = value; 02603 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE); 02604 break; 02605 02606 case DBUS_TYPE_SIGNATURE: 02607 string_p = value; 02608 _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE); 02609 break; 02610 02611 case DBUS_TYPE_BOOLEAN: 02612 bool_p = value; 02613 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE); 02614 break; 02615 02616 default: 02617 { 02618 /* nothing to check, all possible values are allowed */ 02619 } 02620 } 02621 #endif 02622 02623 if (!_dbus_message_iter_open_signature (real)) 02624 return FALSE; 02625 02626 if (type == DBUS_TYPE_UNIX_FD) 02627 { 02628 #ifdef HAVE_UNIX_FD_PASSING 02629 int *fds; 02630 dbus_uint32_t u; 02631 02632 /* First step, include the fd in the fd list of this message */ 02633 if (!(fds = expand_fd_array(real->message, 1))) 02634 return FALSE; 02635 02636 *fds = _dbus_dup(*(int*) value, NULL); 02637 if (*fds < 0) 02638 return FALSE; 02639 02640 u = real->message->n_unix_fds; 02641 02642 /* Second step, write the index to the fd */ 02643 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) { 02644 _dbus_close(*fds, NULL); 02645 return FALSE; 02646 } 02647 02648 real->message->n_unix_fds += 1; 02649 u += 1; 02650 02651 /* Final step, update the header accordingly */ 02652 ret = _dbus_header_set_field_basic (&real->message->header, 02653 DBUS_HEADER_FIELD_UNIX_FDS, 02654 DBUS_TYPE_UINT32, 02655 &u); 02656 02657 /* If any of these operations fail the message is 02658 hosed. However, no memory or fds should be leaked since what 02659 has been added to message has been added to the message, and 02660 can hence be accounted for when the message is being 02661 freed. */ 02662 #else 02663 ret = FALSE; 02664 #endif 02665 } 02666 else 02667 { 02668 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02669 } 02670 02671 if (!_dbus_message_iter_close_signature (real)) 02672 ret = FALSE; 02673 02674 return ret; 02675 } 02676 02712 dbus_bool_t 02713 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02714 int element_type, 02715 const void *value, 02716 int n_elements) 02717 { 02718 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02719 dbus_bool_t ret; 02720 02721 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02722 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02723 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); 02724 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02725 _dbus_return_val_if_fail (value != NULL, FALSE); 02726 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02727 _dbus_return_val_if_fail (n_elements <= 02728 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02729 FALSE); 02730 02731 #ifndef DBUS_DISABLE_CHECKS 02732 if (element_type == DBUS_TYPE_BOOLEAN) 02733 { 02734 const dbus_bool_t * const *bools = value; 02735 int i; 02736 02737 for (i = 0; i < n_elements; i++) 02738 { 02739 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE); 02740 } 02741 } 02742 #endif 02743 02744 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02745 02746 return ret; 02747 } 02748 02770 dbus_bool_t 02771 dbus_message_iter_open_container (DBusMessageIter *iter, 02772 int type, 02773 const char *contained_signature, 02774 DBusMessageIter *sub) 02775 { 02776 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02777 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02778 DBusString contained_str; 02779 02780 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02781 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02782 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02783 _dbus_return_val_if_fail (sub != NULL, FALSE); 02784 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02785 contained_signature == NULL) || 02786 (type == DBUS_TYPE_DICT_ENTRY && 02787 contained_signature == NULL) || 02788 (type == DBUS_TYPE_VARIANT && 02789 contained_signature != NULL) || 02790 (type == DBUS_TYPE_ARRAY && 02791 contained_signature != NULL), FALSE); 02792 02793 /* this would fail if the contained_signature is a dict entry, since 02794 * dict entries are invalid signatures standalone (they must be in 02795 * an array) 02796 */ 02797 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02798 (contained_signature == NULL || 02799 _dbus_check_is_valid_signature (contained_signature)), 02800 FALSE); 02801 02802 if (!_dbus_message_iter_open_signature (real)) 02803 return FALSE; 02804 02805 *real_sub = *real; 02806 02807 if (contained_signature != NULL) 02808 { 02809 _dbus_string_init_const (&contained_str, contained_signature); 02810 02811 return _dbus_type_writer_recurse (&real->u.writer, 02812 type, 02813 &contained_str, 0, 02814 &real_sub->u.writer); 02815 } 02816 else 02817 { 02818 return _dbus_type_writer_recurse (&real->u.writer, 02819 type, 02820 NULL, 0, 02821 &real_sub->u.writer); 02822 } 02823 } 02824 02825 02839 dbus_bool_t 02840 dbus_message_iter_close_container (DBusMessageIter *iter, 02841 DBusMessageIter *sub) 02842 { 02843 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02844 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02845 dbus_bool_t ret; 02846 02847 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02848 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02849 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 02850 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02851 02852 ret = _dbus_type_writer_unrecurse (&real->u.writer, 02853 &real_sub->u.writer); 02854 02855 if (!_dbus_message_iter_close_signature (real)) 02856 ret = FALSE; 02857 02858 return ret; 02859 } 02860 02872 void 02873 dbus_message_iter_abandon_container (DBusMessageIter *iter, 02874 DBusMessageIter *sub) 02875 { 02876 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02877 #ifndef DBUS_DISABLE_CHECKS 02878 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02879 02880 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 02881 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02882 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 02883 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02884 #endif 02885 02886 _dbus_message_iter_abandon_signature (real); 02887 } 02888 02905 void 02906 dbus_message_set_no_reply (DBusMessage *message, 02907 dbus_bool_t no_reply) 02908 { 02909 _dbus_return_if_fail (message != NULL); 02910 _dbus_return_if_fail (!message->locked); 02911 02912 _dbus_header_toggle_flag (&message->header, 02913 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 02914 no_reply); 02915 } 02916 02924 dbus_bool_t 02925 dbus_message_get_no_reply (DBusMessage *message) 02926 { 02927 _dbus_return_val_if_fail (message != NULL, FALSE); 02928 02929 return _dbus_header_get_flag (&message->header, 02930 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 02931 } 02932 02947 void 02948 dbus_message_set_auto_start (DBusMessage *message, 02949 dbus_bool_t auto_start) 02950 { 02951 _dbus_return_if_fail (message != NULL); 02952 _dbus_return_if_fail (!message->locked); 02953 02954 _dbus_header_toggle_flag (&message->header, 02955 DBUS_HEADER_FLAG_NO_AUTO_START, 02956 !auto_start); 02957 } 02958 02966 dbus_bool_t 02967 dbus_message_get_auto_start (DBusMessage *message) 02968 { 02969 _dbus_return_val_if_fail (message != NULL, FALSE); 02970 02971 return !_dbus_header_get_flag (&message->header, 02972 DBUS_HEADER_FLAG_NO_AUTO_START); 02973 } 02974 02975 02988 dbus_bool_t 02989 dbus_message_set_path (DBusMessage *message, 02990 const char *object_path) 02991 { 02992 _dbus_return_val_if_fail (message != NULL, FALSE); 02993 _dbus_return_val_if_fail (!message->locked, FALSE); 02994 _dbus_return_val_if_fail (object_path == NULL || 02995 _dbus_check_is_valid_path (object_path), 02996 FALSE); 02997 02998 return set_or_delete_string_field (message, 02999 DBUS_HEADER_FIELD_PATH, 03000 DBUS_TYPE_OBJECT_PATH, 03001 object_path); 03002 } 03003 03017 const char* 03018 dbus_message_get_path (DBusMessage *message) 03019 { 03020 const char *v; 03021 03022 _dbus_return_val_if_fail (message != NULL, NULL); 03023 03024 v = NULL; /* in case field doesn't exist */ 03025 _dbus_header_get_field_basic (&message->header, 03026 DBUS_HEADER_FIELD_PATH, 03027 DBUS_TYPE_OBJECT_PATH, 03028 (void *) &v); 03029 return v; 03030 } 03031 03041 dbus_bool_t 03042 dbus_message_has_path (DBusMessage *message, 03043 const char *path) 03044 { 03045 const char *msg_path; 03046 msg_path = dbus_message_get_path (message); 03047 03048 if (msg_path == NULL) 03049 { 03050 if (path == NULL) 03051 return TRUE; 03052 else 03053 return FALSE; 03054 } 03055 03056 if (path == NULL) 03057 return FALSE; 03058 03059 if (strcmp (msg_path, path) == 0) 03060 return TRUE; 03061 03062 return FALSE; 03063 } 03064 03085 dbus_bool_t 03086 dbus_message_get_path_decomposed (DBusMessage *message, 03087 char ***path) 03088 { 03089 const char *v; 03090 03091 _dbus_return_val_if_fail (message != NULL, FALSE); 03092 _dbus_return_val_if_fail (path != NULL, FALSE); 03093 03094 *path = NULL; 03095 03096 v = dbus_message_get_path (message); 03097 if (v != NULL) 03098 { 03099 if (!_dbus_decompose_path (v, strlen (v), 03100 path, NULL)) 03101 return FALSE; 03102 } 03103 return TRUE; 03104 } 03105 03119 dbus_bool_t 03120 dbus_message_set_interface (DBusMessage *message, 03121 const char *interface) 03122 { 03123 _dbus_return_val_if_fail (message != NULL, FALSE); 03124 _dbus_return_val_if_fail (!message->locked, FALSE); 03125 _dbus_return_val_if_fail (interface == NULL || 03126 _dbus_check_is_valid_interface (interface), 03127 FALSE); 03128 03129 return set_or_delete_string_field (message, 03130 DBUS_HEADER_FIELD_INTERFACE, 03131 DBUS_TYPE_STRING, 03132 interface); 03133 } 03134 03148 const char* 03149 dbus_message_get_interface (DBusMessage *message) 03150 { 03151 const char *v; 03152 03153 _dbus_return_val_if_fail (message != NULL, NULL); 03154 03155 v = NULL; /* in case field doesn't exist */ 03156 _dbus_header_get_field_basic (&message->header, 03157 DBUS_HEADER_FIELD_INTERFACE, 03158 DBUS_TYPE_STRING, 03159 (void *) &v); 03160 return v; 03161 } 03162 03170 dbus_bool_t 03171 dbus_message_has_interface (DBusMessage *message, 03172 const char *interface) 03173 { 03174 const char *msg_interface; 03175 msg_interface = dbus_message_get_interface (message); 03176 03177 if (msg_interface == NULL) 03178 { 03179 if (interface == NULL) 03180 return TRUE; 03181 else 03182 return FALSE; 03183 } 03184 03185 if (interface == NULL) 03186 return FALSE; 03187 03188 if (strcmp (msg_interface, interface) == 0) 03189 return TRUE; 03190 03191 return FALSE; 03192 03193 } 03194 03207 dbus_bool_t 03208 dbus_message_set_member (DBusMessage *message, 03209 const char *member) 03210 { 03211 _dbus_return_val_if_fail (message != NULL, FALSE); 03212 _dbus_return_val_if_fail (!message->locked, FALSE); 03213 _dbus_return_val_if_fail (member == NULL || 03214 _dbus_check_is_valid_member (member), 03215 FALSE); 03216 03217 return set_or_delete_string_field (message, 03218 DBUS_HEADER_FIELD_MEMBER, 03219 DBUS_TYPE_STRING, 03220 member); 03221 } 03222 03234 const char* 03235 dbus_message_get_member (DBusMessage *message) 03236 { 03237 const char *v; 03238 03239 _dbus_return_val_if_fail (message != NULL, NULL); 03240 03241 v = NULL; /* in case field doesn't exist */ 03242 _dbus_header_get_field_basic (&message->header, 03243 DBUS_HEADER_FIELD_MEMBER, 03244 DBUS_TYPE_STRING, 03245 (void *) &v); 03246 return v; 03247 } 03248 03256 dbus_bool_t 03257 dbus_message_has_member (DBusMessage *message, 03258 const char *member) 03259 { 03260 const char *msg_member; 03261 msg_member = dbus_message_get_member (message); 03262 03263 if (msg_member == NULL) 03264 { 03265 if (member == NULL) 03266 return TRUE; 03267 else 03268 return FALSE; 03269 } 03270 03271 if (member == NULL) 03272 return FALSE; 03273 03274 if (strcmp (msg_member, member) == 0) 03275 return TRUE; 03276 03277 return FALSE; 03278 03279 } 03280 03292 dbus_bool_t 03293 dbus_message_set_error_name (DBusMessage *message, 03294 const char *error_name) 03295 { 03296 _dbus_return_val_if_fail (message != NULL, FALSE); 03297 _dbus_return_val_if_fail (!message->locked, FALSE); 03298 _dbus_return_val_if_fail (error_name == NULL || 03299 _dbus_check_is_valid_error_name (error_name), 03300 FALSE); 03301 03302 return set_or_delete_string_field (message, 03303 DBUS_HEADER_FIELD_ERROR_NAME, 03304 DBUS_TYPE_STRING, 03305 error_name); 03306 } 03307 03318 const char* 03319 dbus_message_get_error_name (DBusMessage *message) 03320 { 03321 const char *v; 03322 03323 _dbus_return_val_if_fail (message != NULL, NULL); 03324 03325 v = NULL; /* in case field doesn't exist */ 03326 _dbus_header_get_field_basic (&message->header, 03327 DBUS_HEADER_FIELD_ERROR_NAME, 03328 DBUS_TYPE_STRING, 03329 (void *) &v); 03330 return v; 03331 } 03332 03346 dbus_bool_t 03347 dbus_message_set_destination (DBusMessage *message, 03348 const char *destination) 03349 { 03350 _dbus_return_val_if_fail (message != NULL, FALSE); 03351 _dbus_return_val_if_fail (!message->locked, FALSE); 03352 _dbus_return_val_if_fail (destination == NULL || 03353 _dbus_check_is_valid_bus_name (destination), 03354 FALSE); 03355 03356 return set_or_delete_string_field (message, 03357 DBUS_HEADER_FIELD_DESTINATION, 03358 DBUS_TYPE_STRING, 03359 destination); 03360 } 03361 03371 const char* 03372 dbus_message_get_destination (DBusMessage *message) 03373 { 03374 const char *v; 03375 03376 _dbus_return_val_if_fail (message != NULL, NULL); 03377 03378 v = NULL; /* in case field doesn't exist */ 03379 _dbus_header_get_field_basic (&message->header, 03380 DBUS_HEADER_FIELD_DESTINATION, 03381 DBUS_TYPE_STRING, 03382 (void *) &v); 03383 return v; 03384 } 03385 03400 dbus_bool_t 03401 dbus_message_set_sender (DBusMessage *message, 03402 const char *sender) 03403 { 03404 _dbus_return_val_if_fail (message != NULL, FALSE); 03405 _dbus_return_val_if_fail (!message->locked, FALSE); 03406 _dbus_return_val_if_fail (sender == NULL || 03407 _dbus_check_is_valid_bus_name (sender), 03408 FALSE); 03409 03410 return set_or_delete_string_field (message, 03411 DBUS_HEADER_FIELD_SENDER, 03412 DBUS_TYPE_STRING, 03413 sender); 03414 } 03415 03431 const char* 03432 dbus_message_get_sender (DBusMessage *message) 03433 { 03434 const char *v; 03435 03436 _dbus_return_val_if_fail (message != NULL, NULL); 03437 03438 v = NULL; /* in case field doesn't exist */ 03439 _dbus_header_get_field_basic (&message->header, 03440 DBUS_HEADER_FIELD_SENDER, 03441 DBUS_TYPE_STRING, 03442 (void *) &v); 03443 return v; 03444 } 03445 03464 const char* 03465 dbus_message_get_signature (DBusMessage *message) 03466 { 03467 const DBusString *type_str; 03468 int type_pos; 03469 03470 _dbus_return_val_if_fail (message != NULL, NULL); 03471 03472 get_const_signature (&message->header, &type_str, &type_pos); 03473 03474 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03475 } 03476 03477 static dbus_bool_t 03478 _dbus_message_has_type_interface_member (DBusMessage *message, 03479 int type, 03480 const char *interface, 03481 const char *member) 03482 { 03483 const char *n; 03484 03485 _dbus_assert (message != NULL); 03486 _dbus_assert (interface != NULL); 03487 _dbus_assert (member != NULL); 03488 03489 if (dbus_message_get_type (message) != type) 03490 return FALSE; 03491 03492 /* Optimize by checking the short member name first 03493 * instead of the longer interface name 03494 */ 03495 03496 n = dbus_message_get_member (message); 03497 03498 if (n && strcmp (n, member) == 0) 03499 { 03500 n = dbus_message_get_interface (message); 03501 03502 if (n == NULL || strcmp (n, interface) == 0) 03503 return TRUE; 03504 } 03505 03506 return FALSE; 03507 } 03508 03523 dbus_bool_t 03524 dbus_message_is_method_call (DBusMessage *message, 03525 const char *interface, 03526 const char *method) 03527 { 03528 _dbus_return_val_if_fail (message != NULL, FALSE); 03529 _dbus_return_val_if_fail (interface != NULL, FALSE); 03530 _dbus_return_val_if_fail (method != NULL, FALSE); 03531 /* don't check that interface/method are valid since it would be 03532 * expensive, and not catch many common errors 03533 */ 03534 03535 return _dbus_message_has_type_interface_member (message, 03536 DBUS_MESSAGE_TYPE_METHOD_CALL, 03537 interface, method); 03538 } 03539 03551 dbus_bool_t 03552 dbus_message_is_signal (DBusMessage *message, 03553 const char *interface, 03554 const char *signal_name) 03555 { 03556 _dbus_return_val_if_fail (message != NULL, FALSE); 03557 _dbus_return_val_if_fail (interface != NULL, FALSE); 03558 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03559 /* don't check that interface/name are valid since it would be 03560 * expensive, and not catch many common errors 03561 */ 03562 03563 return _dbus_message_has_type_interface_member (message, 03564 DBUS_MESSAGE_TYPE_SIGNAL, 03565 interface, signal_name); 03566 } 03567 03578 dbus_bool_t 03579 dbus_message_is_error (DBusMessage *message, 03580 const char *error_name) 03581 { 03582 const char *n; 03583 03584 _dbus_return_val_if_fail (message != NULL, FALSE); 03585 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03586 /* don't check that error_name is valid since it would be expensive, 03587 * and not catch many common errors 03588 */ 03589 03590 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03591 return FALSE; 03592 03593 n = dbus_message_get_error_name (message); 03594 03595 if (n && strcmp (n, error_name) == 0) 03596 return TRUE; 03597 else 03598 return FALSE; 03599 } 03600 03611 dbus_bool_t 03612 dbus_message_has_destination (DBusMessage *message, 03613 const char *name) 03614 { 03615 const char *s; 03616 03617 _dbus_return_val_if_fail (message != NULL, FALSE); 03618 _dbus_return_val_if_fail (name != NULL, FALSE); 03619 /* don't check that name is valid since it would be expensive, and 03620 * not catch many common errors 03621 */ 03622 03623 s = dbus_message_get_destination (message); 03624 03625 if (s && strcmp (s, name) == 0) 03626 return TRUE; 03627 else 03628 return FALSE; 03629 } 03630 03646 dbus_bool_t 03647 dbus_message_has_sender (DBusMessage *message, 03648 const char *name) 03649 { 03650 const char *s; 03651 03652 _dbus_return_val_if_fail (message != NULL, FALSE); 03653 _dbus_return_val_if_fail (name != NULL, FALSE); 03654 /* don't check that name is valid since it would be expensive, and 03655 * not catch many common errors 03656 */ 03657 03658 s = dbus_message_get_sender (message); 03659 03660 if (s && strcmp (s, name) == 0) 03661 return TRUE; 03662 else 03663 return FALSE; 03664 } 03665 03675 dbus_bool_t 03676 dbus_message_has_signature (DBusMessage *message, 03677 const char *signature) 03678 { 03679 const char *s; 03680 03681 _dbus_return_val_if_fail (message != NULL, FALSE); 03682 _dbus_return_val_if_fail (signature != NULL, FALSE); 03683 /* don't check that signature is valid since it would be expensive, 03684 * and not catch many common errors 03685 */ 03686 03687 s = dbus_message_get_signature (message); 03688 03689 if (s && strcmp (s, signature) == 0) 03690 return TRUE; 03691 else 03692 return FALSE; 03693 } 03694 03717 dbus_bool_t 03718 dbus_set_error_from_message (DBusError *error, 03719 DBusMessage *message) 03720 { 03721 const char *str; 03722 03723 _dbus_return_val_if_fail (message != NULL, FALSE); 03724 _dbus_return_val_if_error_is_set (error, FALSE); 03725 03726 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03727 return FALSE; 03728 03729 str = NULL; 03730 dbus_message_get_args (message, NULL, 03731 DBUS_TYPE_STRING, &str, 03732 DBUS_TYPE_INVALID); 03733 03734 dbus_set_error (error, dbus_message_get_error_name (message), 03735 str ? "%s" : NULL, str); 03736 03737 return TRUE; 03738 } 03739 03746 dbus_bool_t 03747 dbus_message_contains_unix_fds(DBusMessage *message) 03748 { 03749 #ifdef HAVE_UNIX_FD_PASSING 03750 _dbus_assert(message); 03751 03752 return message->n_unix_fds > 0; 03753 #else 03754 return FALSE; 03755 #endif 03756 } 03757 03776 #define INITIAL_LOADER_DATA_LEN 32 03777 03784 DBusMessageLoader* 03785 _dbus_message_loader_new (void) 03786 { 03787 DBusMessageLoader *loader; 03788 03789 loader = dbus_new0 (DBusMessageLoader, 1); 03790 if (loader == NULL) 03791 return NULL; 03792 03793 loader->refcount = 1; 03794 03795 loader->corrupted = FALSE; 03796 loader->corruption_reason = DBUS_VALID; 03797 03798 /* this can be configured by the app, but defaults to the protocol max */ 03799 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03800 03801 /* We set a very relatively conservative default here since due to how 03802 SCM_RIGHTS works we need to preallocate an fd array of the maximum 03803 number of unix fds we want to receive in advance. A 03804 try-and-reallocate loop is not possible. */ 03805 loader->max_message_unix_fds = 1024; 03806 03807 if (!_dbus_string_init (&loader->data)) 03808 { 03809 dbus_free (loader); 03810 return NULL; 03811 } 03812 03813 /* preallocate the buffer for speed, ignore failure */ 03814 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03815 _dbus_string_set_length (&loader->data, 0); 03816 03817 #ifdef HAVE_UNIX_FD_PASSING 03818 loader->unix_fds = NULL; 03819 loader->n_unix_fds = loader->n_unix_fds_allocated = 0; 03820 loader->unix_fds_outstanding = FALSE; 03821 #endif 03822 03823 return loader; 03824 } 03825 03832 DBusMessageLoader * 03833 _dbus_message_loader_ref (DBusMessageLoader *loader) 03834 { 03835 loader->refcount += 1; 03836 03837 return loader; 03838 } 03839 03846 void 03847 _dbus_message_loader_unref (DBusMessageLoader *loader) 03848 { 03849 loader->refcount -= 1; 03850 if (loader->refcount == 0) 03851 { 03852 #ifdef HAVE_UNIX_FD_PASSING 03853 close_unix_fds(loader->unix_fds, &loader->n_unix_fds); 03854 dbus_free(loader->unix_fds); 03855 #endif 03856 _dbus_list_foreach (&loader->messages, 03857 (DBusForeachFunction) dbus_message_unref, 03858 NULL); 03859 _dbus_list_clear (&loader->messages); 03860 _dbus_string_free (&loader->data); 03861 dbus_free (loader); 03862 } 03863 } 03864 03883 void 03884 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 03885 DBusString **buffer) 03886 { 03887 _dbus_assert (!loader->buffer_outstanding); 03888 03889 *buffer = &loader->data; 03890 03891 loader->buffer_outstanding = TRUE; 03892 } 03893 03904 void 03905 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 03906 DBusString *buffer, 03907 int bytes_read) 03908 { 03909 _dbus_assert (loader->buffer_outstanding); 03910 _dbus_assert (buffer == &loader->data); 03911 03912 loader->buffer_outstanding = FALSE; 03913 } 03914 03925 dbus_bool_t 03926 _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, 03927 int **fds, 03928 unsigned *max_n_fds) 03929 { 03930 #ifdef HAVE_UNIX_FD_PASSING 03931 _dbus_assert (!loader->unix_fds_outstanding); 03932 03933 /* Allocate space where we can put the fds we read. We allocate 03934 space for max_message_unix_fds since this is an 03935 upper limit how many fds can be received within a single 03936 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic 03937 we are allocating the maximum possible array size right from the 03938 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed 03939 there is no better way. */ 03940 03941 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds) 03942 { 03943 int *a = dbus_realloc(loader->unix_fds, 03944 loader->max_message_unix_fds * sizeof(loader->unix_fds[0])); 03945 03946 if (!a) 03947 return FALSE; 03948 03949 loader->unix_fds = a; 03950 loader->n_unix_fds_allocated = loader->max_message_unix_fds; 03951 } 03952 03953 *fds = loader->unix_fds + loader->n_unix_fds; 03954 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds; 03955 03956 loader->unix_fds_outstanding = TRUE; 03957 return TRUE; 03958 #else 03959 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03960 return FALSE; 03961 #endif 03962 } 03963 03974 void 03975 _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, 03976 int *fds, 03977 unsigned n_fds) 03978 { 03979 #ifdef HAVE_UNIX_FD_PASSING 03980 _dbus_assert(loader->unix_fds_outstanding); 03981 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds); 03982 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated); 03983 03984 loader->n_unix_fds += n_fds; 03985 loader->unix_fds_outstanding = FALSE; 03986 #else 03987 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03988 #endif 03989 } 03990 03991 /* 03992 * FIXME when we move the header out of the buffer, that memmoves all 03993 * buffered messages. Kind of crappy. 03994 * 03995 * Also we copy the header and body, which is kind of crappy. To 03996 * avoid this, we have to allow header and body to be in a single 03997 * memory block, which is good for messages we read and bad for 03998 * messages we are creating. But we could move_len() the buffer into 03999 * this single memory block, and move_len() will just swap the buffers 04000 * if you're moving the entire buffer replacing the dest string. 04001 * 04002 * We could also have the message loader tell the transport how many 04003 * bytes to read; so it would first ask for some arbitrary number like 04004 * 256, then if the message was incomplete it would use the 04005 * header/body len to ask for exactly the size of the message (or 04006 * blocks the size of a typical kernel buffer for the socket). That 04007 * way we don't get trailing bytes in the buffer that have to be 04008 * memmoved. Though I suppose we also don't have a chance of reading a 04009 * bunch of small messages at once, so the optimization may be stupid. 04010 * 04011 * Another approach would be to keep a "start" index into 04012 * loader->data and only delete it occasionally, instead of after 04013 * each message is loaded. 04014 * 04015 * load_message() returns FALSE if not enough memory OR the loader was corrupted 04016 */ 04017 static dbus_bool_t 04018 load_message (DBusMessageLoader *loader, 04019 DBusMessage *message, 04020 int byte_order, 04021 int fields_array_len, 04022 int header_len, 04023 int body_len) 04024 { 04025 dbus_bool_t oom; 04026 DBusValidity validity; 04027 const DBusString *type_str; 04028 int type_pos; 04029 DBusValidationMode mode; 04030 dbus_uint32_t n_unix_fds = 0; 04031 04032 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 04033 04034 oom = FALSE; 04035 04036 #if 0 04037 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 04038 #endif 04039 04040 /* 1. VALIDATE AND COPY OVER HEADER */ 04041 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 04042 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 04043 04044 if (!_dbus_header_load (&message->header, 04045 mode, 04046 &validity, 04047 byte_order, 04048 fields_array_len, 04049 header_len, 04050 body_len, 04051 &loader->data, 0, 04052 _dbus_string_get_length (&loader->data))) 04053 { 04054 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 04055 04056 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 04057 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 04058 _dbus_assert (validity != DBUS_VALID); 04059 04060 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 04061 oom = TRUE; 04062 else 04063 { 04064 loader->corrupted = TRUE; 04065 loader->corruption_reason = validity; 04066 } 04067 goto failed; 04068 } 04069 04070 _dbus_assert (validity == DBUS_VALID); 04071 04072 /* 2. VALIDATE BODY */ 04073 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 04074 { 04075 get_const_signature (&message->header, &type_str, &type_pos); 04076 04077 /* Because the bytes_remaining arg is NULL, this validates that the 04078 * body is the right length 04079 */ 04080 validity = _dbus_validate_body_with_reason (type_str, 04081 type_pos, 04082 byte_order, 04083 NULL, 04084 &loader->data, 04085 header_len, 04086 body_len); 04087 if (validity != DBUS_VALID) 04088 { 04089 _dbus_verbose ("Failed to validate message body code %d\n", validity); 04090 04091 loader->corrupted = TRUE; 04092 loader->corruption_reason = validity; 04093 04094 goto failed; 04095 } 04096 } 04097 04098 /* 3. COPY OVER UNIX FDS */ 04099 _dbus_header_get_field_basic(&message->header, 04100 DBUS_HEADER_FIELD_UNIX_FDS, 04101 DBUS_TYPE_UINT32, 04102 &n_unix_fds); 04103 04104 #ifdef HAVE_UNIX_FD_PASSING 04105 04106 if (n_unix_fds > loader->n_unix_fds) 04107 { 04108 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n", 04109 n_unix_fds, loader->n_unix_fds); 04110 04111 loader->corrupted = TRUE; 04112 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04113 goto failed; 04114 } 04115 04116 /* If this was a recycled message there might still be 04117 some memory allocated for the fds */ 04118 dbus_free(message->unix_fds); 04119 04120 if (n_unix_fds > 0) 04121 { 04122 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0])); 04123 if (message->unix_fds == NULL) 04124 { 04125 _dbus_verbose ("Failed to allocate file descriptor array\n"); 04126 oom = TRUE; 04127 goto failed; 04128 } 04129 04130 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; 04131 loader->n_unix_fds -= n_unix_fds; 04132 memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds); 04133 } 04134 else 04135 message->unix_fds = NULL; 04136 04137 #else 04138 04139 if (n_unix_fds > 0) 04140 { 04141 _dbus_verbose ("Hmm, message claims to come with file descriptors " 04142 "but that's not supported on our platform, disconnecting.\n"); 04143 04144 loader->corrupted = TRUE; 04145 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04146 goto failed; 04147 } 04148 04149 #endif 04150 04151 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 04152 04153 if (!_dbus_list_append (&loader->messages, message)) 04154 { 04155 _dbus_verbose ("Failed to append new message to loader queue\n"); 04156 oom = TRUE; 04157 goto failed; 04158 } 04159 04160 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 04161 _dbus_assert (_dbus_string_get_length (&loader->data) >= 04162 (header_len + body_len)); 04163 04164 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 04165 { 04166 _dbus_verbose ("Failed to move body into new message\n"); 04167 oom = TRUE; 04168 goto failed; 04169 } 04170 04171 _dbus_string_delete (&loader->data, 0, header_len + body_len); 04172 04173 /* don't waste more than 2k of memory */ 04174 _dbus_string_compact (&loader->data, 2048); 04175 04176 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 04177 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 04178 04179 _dbus_verbose ("Loaded message %p\n", message); 04180 04181 _dbus_assert (!oom); 04182 _dbus_assert (!loader->corrupted); 04183 _dbus_assert (loader->messages != NULL); 04184 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04185 04186 return TRUE; 04187 04188 failed: 04189 04190 /* Clean up */ 04191 04192 /* does nothing if the message isn't in the list */ 04193 _dbus_list_remove_last (&loader->messages, message); 04194 04195 if (oom) 04196 _dbus_assert (!loader->corrupted); 04197 else 04198 _dbus_assert (loader->corrupted); 04199 04200 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 04201 04202 return FALSE; 04203 } 04204 04219 dbus_bool_t 04220 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 04221 { 04222 while (!loader->corrupted && 04223 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 04224 { 04225 DBusValidity validity; 04226 int byte_order, fields_array_len, header_len, body_len; 04227 04228 if (_dbus_header_have_message_untrusted (loader->max_message_size, 04229 &validity, 04230 &byte_order, 04231 &fields_array_len, 04232 &header_len, 04233 &body_len, 04234 &loader->data, 0, 04235 _dbus_string_get_length (&loader->data))) 04236 { 04237 DBusMessage *message; 04238 04239 _dbus_assert (validity == DBUS_VALID); 04240 04241 message = dbus_message_new_empty_header (); 04242 if (message == NULL) 04243 return FALSE; 04244 04245 if (!load_message (loader, message, 04246 byte_order, fields_array_len, 04247 header_len, body_len)) 04248 { 04249 dbus_message_unref (message); 04250 /* load_message() returns false if corrupted or OOM; if 04251 * corrupted then return TRUE for not OOM 04252 */ 04253 return loader->corrupted; 04254 } 04255 04256 _dbus_assert (loader->messages != NULL); 04257 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04258 } 04259 else 04260 { 04261 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 04262 validity); 04263 if (validity != DBUS_VALID) 04264 { 04265 loader->corrupted = TRUE; 04266 loader->corruption_reason = validity; 04267 } 04268 return TRUE; 04269 } 04270 } 04271 04272 return TRUE; 04273 } 04274 04282 DBusMessage* 04283 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 04284 { 04285 if (loader->messages) 04286 return loader->messages->data; 04287 else 04288 return NULL; 04289 } 04290 04299 DBusMessage* 04300 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 04301 { 04302 return _dbus_list_pop_first (&loader->messages); 04303 } 04304 04313 DBusList* 04314 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 04315 { 04316 return _dbus_list_pop_first_link (&loader->messages); 04317 } 04318 04325 void 04326 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 04327 DBusList *link) 04328 { 04329 _dbus_list_prepend_link (&loader->messages, link); 04330 } 04331 04341 dbus_bool_t 04342 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 04343 { 04344 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04345 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04346 return loader->corrupted; 04347 } 04348 04355 DBusValidity 04356 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 04357 { 04358 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04359 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04360 04361 return loader->corruption_reason; 04362 } 04363 04370 void 04371 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 04372 long size) 04373 { 04374 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 04375 { 04376 _dbus_verbose ("clamping requested max message size %ld to %d\n", 04377 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 04378 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 04379 } 04380 loader->max_message_size = size; 04381 } 04382 04389 long 04390 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 04391 { 04392 return loader->max_message_size; 04393 } 04394 04401 void 04402 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, 04403 long n) 04404 { 04405 if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS) 04406 { 04407 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n", 04408 n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS); 04409 n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS; 04410 } 04411 loader->max_message_unix_fds = n; 04412 } 04413 04420 long 04421 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) 04422 { 04423 return loader->max_message_unix_fds; 04424 } 04425 04426 static DBusDataSlotAllocator slot_allocator; 04427 _DBUS_DEFINE_GLOBAL_LOCK (message_slots); 04428 04443 dbus_bool_t 04444 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 04445 { 04446 return _dbus_data_slot_allocator_alloc (&slot_allocator, 04447 &_DBUS_LOCK_NAME (message_slots), 04448 slot_p); 04449 } 04450 04462 void 04463 dbus_message_free_data_slot (dbus_int32_t *slot_p) 04464 { 04465 _dbus_return_if_fail (*slot_p >= 0); 04466 04467 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 04468 } 04469 04483 dbus_bool_t 04484 dbus_message_set_data (DBusMessage *message, 04485 dbus_int32_t slot, 04486 void *data, 04487 DBusFreeFunction free_data_func) 04488 { 04489 DBusFreeFunction old_free_func; 04490 void *old_data; 04491 dbus_bool_t retval; 04492 04493 _dbus_return_val_if_fail (message != NULL, FALSE); 04494 _dbus_return_val_if_fail (slot >= 0, FALSE); 04495 04496 retval = _dbus_data_slot_list_set (&slot_allocator, 04497 &message->slot_list, 04498 slot, data, free_data_func, 04499 &old_free_func, &old_data); 04500 04501 if (retval) 04502 { 04503 /* Do the actual free outside the message lock */ 04504 if (old_free_func) 04505 (* old_free_func) (old_data); 04506 } 04507 04508 return retval; 04509 } 04510 04519 void* 04520 dbus_message_get_data (DBusMessage *message, 04521 dbus_int32_t slot) 04522 { 04523 void *res; 04524 04525 _dbus_return_val_if_fail (message != NULL, NULL); 04526 04527 res = _dbus_data_slot_list_get (&slot_allocator, 04528 &message->slot_list, 04529 slot); 04530 04531 return res; 04532 } 04533 04547 int 04548 dbus_message_type_from_string (const char *type_str) 04549 { 04550 if (strcmp (type_str, "method_call") == 0) 04551 return DBUS_MESSAGE_TYPE_METHOD_CALL; 04552 if (strcmp (type_str, "method_return") == 0) 04553 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 04554 else if (strcmp (type_str, "signal") == 0) 04555 return DBUS_MESSAGE_TYPE_SIGNAL; 04556 else if (strcmp (type_str, "error") == 0) 04557 return DBUS_MESSAGE_TYPE_ERROR; 04558 else 04559 return DBUS_MESSAGE_TYPE_INVALID; 04560 } 04561 04575 const char * 04576 dbus_message_type_to_string (int type) 04577 { 04578 switch (type) 04579 { 04580 case DBUS_MESSAGE_TYPE_METHOD_CALL: 04581 return "method_call"; 04582 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 04583 return "method_return"; 04584 case DBUS_MESSAGE_TYPE_SIGNAL: 04585 return "signal"; 04586 case DBUS_MESSAGE_TYPE_ERROR: 04587 return "error"; 04588 default: 04589 return "invalid"; 04590 } 04591 } 04592 04605 dbus_bool_t 04606 dbus_message_marshal (DBusMessage *msg, 04607 char **marshalled_data_p, 04608 int *len_p) 04609 { 04610 DBusString tmp; 04611 dbus_bool_t was_locked; 04612 04613 _dbus_return_val_if_fail (msg != NULL, FALSE); 04614 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04615 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04616 04617 if (!_dbus_string_init (&tmp)) 04618 return FALSE; 04619 04620 /* Ensure the message is locked, to ensure the length header is filled in. */ 04621 was_locked = msg->locked; 04622 04623 if (!was_locked) 04624 dbus_message_lock (msg); 04625 04626 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04627 goto fail; 04628 04629 *len_p = _dbus_string_get_length (&tmp); 04630 04631 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04632 goto fail; 04633 04634 *len_p = _dbus_string_get_length (&tmp); 04635 04636 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04637 goto fail; 04638 04639 _dbus_string_free (&tmp); 04640 04641 if (!was_locked) 04642 msg->locked = FALSE; 04643 04644 return TRUE; 04645 04646 fail: 04647 _dbus_string_free (&tmp); 04648 04649 if (!was_locked) 04650 msg->locked = FALSE; 04651 04652 return FALSE; 04653 } 04654 04667 DBusMessage * 04668 dbus_message_demarshal (const char *str, 04669 int len, 04670 DBusError *error) 04671 { 04672 DBusMessageLoader *loader; 04673 DBusString *buffer; 04674 DBusMessage *msg; 04675 04676 _dbus_return_val_if_fail (str != NULL, NULL); 04677 04678 loader = _dbus_message_loader_new (); 04679 04680 if (loader == NULL) 04681 return NULL; 04682 04683 _dbus_message_loader_get_buffer (loader, &buffer); 04684 _dbus_string_append_len (buffer, str, len); 04685 _dbus_message_loader_return_buffer (loader, buffer, len); 04686 04687 if (!_dbus_message_loader_queue_messages (loader)) 04688 goto fail_oom; 04689 04690 if (_dbus_message_loader_get_is_corrupted (loader)) 04691 goto fail_corrupt; 04692 04693 msg = _dbus_message_loader_pop_message (loader); 04694 04695 if (!msg) 04696 goto fail_oom; 04697 04698 _dbus_message_loader_unref (loader); 04699 return msg; 04700 04701 fail_corrupt: 04702 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04703 _dbus_validity_to_error_message (loader->corruption_reason)); 04704 _dbus_message_loader_unref (loader); 04705 return NULL; 04706 04707 fail_oom: 04708 _DBUS_SET_OOM (error); 04709 _dbus_message_loader_unref (loader); 04710 return NULL; 04711 } 04712 04726 int 04727 dbus_message_demarshal_bytes_needed(const char *buf, 04728 int len) 04729 { 04730 DBusString str; 04731 int byte_order, fields_array_len, header_len, body_len; 04732 DBusValidity validity = DBUS_VALID; 04733 int have_message; 04734 04735 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04736 return 0; 04737 04738 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04739 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04740 _dbus_string_init_const_len (&str, buf, len); 04741 04742 validity = DBUS_VALID; 04743 have_message 04744 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04745 &validity, &byte_order, 04746 &fields_array_len, 04747 &header_len, 04748 &body_len, 04749 &str, 0, 04750 len); 04751 _dbus_string_free (&str); 04752 04753 if (validity == DBUS_VALID) 04754 { 04755 _dbus_assert (have_message || (header_len + body_len) > len); 04756 (void) have_message; /* unused unless asserting */ 04757 return header_len + body_len; 04758 } 04759 else 04760 { 04761 return -1; /* broken! */ 04762 } 04763 } 04764 04767 /* tests in dbus-message-util.c */