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