|
D-Bus
1.5.8
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-message.c DBusMessage object 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc. 00005 * Copyright (C) 2002, 2003 CodeFactory AB 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include <config.h> 00026 #include "dbus-internals.h" 00027 #include "dbus-marshal-recursive.h" 00028 #include "dbus-marshal-validate.h" 00029 #include "dbus-marshal-byteswap.h" 00030 #include "dbus-marshal-header.h" 00031 #include "dbus-signature.h" 00032 #include "dbus-message-private.h" 00033 #include "dbus-object-tree.h" 00034 #include "dbus-memory.h" 00035 #include "dbus-list.h" 00036 #include "dbus-threads-internal.h" 00037 #ifdef HAVE_UNIX_FD_PASSING 00038 #include "dbus-sysdeps-unix.h" 00039 #endif 00040 00041 #include <string.h> 00042 00043 static void dbus_message_finalize (DBusMessage *message); 00044 00055 /* Not thread locked, but strictly const/read-only so should be OK 00056 */ 00058 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, ""); 00059 00060 /* these have wacky values to help trap uninitialized iterators; 00061 * but has to fit in 3 bits 00062 */ 00063 enum { 00064 DBUS_MESSAGE_ITER_TYPE_READER = 3, 00065 DBUS_MESSAGE_ITER_TYPE_WRITER = 7 00066 }; 00067 00069 typedef struct DBusMessageRealIter DBusMessageRealIter; 00070 00076 struct DBusMessageRealIter 00077 { 00078 DBusMessage *message; 00079 dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; 00080 dbus_uint32_t iter_type : 3; 00081 dbus_uint32_t sig_refcount : 8; 00082 union 00083 { 00084 DBusTypeWriter writer; 00085 DBusTypeReader reader; 00086 } u; 00087 }; 00088 00089 static void 00090 get_const_signature (DBusHeader *header, 00091 const DBusString **type_str_p, 00092 int *type_pos_p) 00093 { 00094 if (_dbus_header_get_field_raw (header, 00095 DBUS_HEADER_FIELD_SIGNATURE, 00096 type_str_p, 00097 type_pos_p)) 00098 { 00099 *type_pos_p += 1; /* skip the signature length which is 1 byte */ 00100 } 00101 else 00102 { 00103 *type_str_p = &_dbus_empty_signature_str; 00104 *type_pos_p = 0; 00105 } 00106 } 00107 00113 static void 00114 _dbus_message_byteswap (DBusMessage *message) 00115 { 00116 const DBusString *type_str; 00117 int type_pos; 00118 char byte_order; 00119 00120 byte_order = _dbus_header_get_byte_order (&message->header); 00121 00122 if (byte_order == DBUS_COMPILER_BYTE_ORDER) 00123 return; 00124 00125 _dbus_verbose ("Swapping message into compiler byte order\n"); 00126 00127 get_const_signature (&message->header, &type_str, &type_pos); 00128 00129 _dbus_marshal_byteswap (type_str, type_pos, 00130 byte_order, 00131 DBUS_COMPILER_BYTE_ORDER, 00132 &message->body, 0); 00133 00134 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER); 00135 _dbus_assert (_dbus_header_get_byte_order (&message->header) == 00136 DBUS_COMPILER_BYTE_ORDER); 00137 } 00138 00145 #define ensure_byte_order(message) _dbus_message_byteswap (message) 00146 00157 void 00158 _dbus_message_get_network_data (DBusMessage *message, 00159 const DBusString **header, 00160 const DBusString **body) 00161 { 00162 _dbus_assert (message->locked); 00163 00164 *header = &message->header.data; 00165 *body = &message->body; 00166 } 00167 00177 void _dbus_message_get_unix_fds(DBusMessage *message, 00178 const int **fds, 00179 unsigned *n_fds) 00180 { 00181 _dbus_assert (message->locked); 00182 00183 #ifdef HAVE_UNIX_FD_PASSING 00184 *fds = message->unix_fds; 00185 *n_fds = message->n_unix_fds; 00186 #else 00187 *fds = NULL; 00188 *n_fds = 0; 00189 #endif 00190 } 00191 00203 void 00204 dbus_message_set_serial (DBusMessage *message, 00205 dbus_uint32_t serial) 00206 { 00207 _dbus_return_if_fail (message != NULL); 00208 _dbus_return_if_fail (!message->locked); 00209 00210 _dbus_header_set_serial (&message->header, serial); 00211 } 00212 00229 void 00230 _dbus_message_add_counter_link (DBusMessage *message, 00231 DBusList *link) 00232 { 00233 /* right now we don't recompute the delta when message 00234 * size changes, and that's OK for current purposes 00235 * I think, but could be important to change later. 00236 * Do recompute it whenever there are no outstanding counters, 00237 * since it's basically free. 00238 */ 00239 if (message->counters == NULL) 00240 { 00241 message->size_counter_delta = 00242 _dbus_string_get_length (&message->header.data) + 00243 _dbus_string_get_length (&message->body); 00244 00245 #ifdef HAVE_UNIX_FD_PASSING 00246 message->unix_fd_counter_delta = message->n_unix_fds; 00247 #endif 00248 00249 #if 0 00250 _dbus_verbose ("message has size %ld\n", 00251 message->size_counter_delta); 00252 #endif 00253 } 00254 00255 _dbus_list_append_link (&message->counters, link); 00256 00257 _dbus_counter_adjust_size (link->data, message->size_counter_delta); 00258 00259 #ifdef HAVE_UNIX_FD_PASSING 00260 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta); 00261 #endif 00262 } 00263 00278 dbus_bool_t 00279 _dbus_message_add_counter (DBusMessage *message, 00280 DBusCounter *counter) 00281 { 00282 DBusList *link; 00283 00284 link = _dbus_list_alloc_link (counter); 00285 if (link == NULL) 00286 return FALSE; 00287 00288 _dbus_counter_ref (counter); 00289 _dbus_message_add_counter_link (message, link); 00290 00291 return TRUE; 00292 } 00293 00301 void 00302 _dbus_message_remove_counter (DBusMessage *message, 00303 DBusCounter *counter) 00304 { 00305 DBusList *link; 00306 00307 link = _dbus_list_find_last (&message->counters, 00308 counter); 00309 _dbus_assert (link != NULL); 00310 00311 _dbus_list_remove_link (&message->counters, link); 00312 00313 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00314 00315 #ifdef HAVE_UNIX_FD_PASSING 00316 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00317 #endif 00318 00319 _dbus_counter_notify (counter); 00320 _dbus_counter_unref (counter); 00321 } 00322 00333 void 00334 dbus_message_lock (DBusMessage *message) 00335 { 00336 if (!message->locked) 00337 { 00338 _dbus_header_update_lengths (&message->header, 00339 _dbus_string_get_length (&message->body)); 00340 00341 /* must have a signature if you have a body */ 00342 _dbus_assert (_dbus_string_get_length (&message->body) == 0 || 00343 dbus_message_get_signature (message) != NULL); 00344 00345 message->locked = TRUE; 00346 } 00347 } 00348 00349 static dbus_bool_t 00350 set_or_delete_string_field (DBusMessage *message, 00351 int field, 00352 int typecode, 00353 const char *value) 00354 { 00355 if (value == NULL) 00356 return _dbus_header_delete_field (&message->header, field); 00357 else 00358 return _dbus_header_set_field_basic (&message->header, 00359 field, 00360 typecode, 00361 &value); 00362 } 00363 00364 #if 0 00365 /* Probably we don't need to use this */ 00389 static dbus_bool_t 00390 _dbus_message_set_signature (DBusMessage *message, 00391 const char *signature) 00392 { 00393 _dbus_return_val_if_fail (message != NULL, FALSE); 00394 _dbus_return_val_if_fail (!message->locked, FALSE); 00395 _dbus_return_val_if_fail (signature == NULL || 00396 _dbus_check_is_valid_signature (signature)); 00397 /* can't delete the signature if you have a message body */ 00398 _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 || 00399 signature != NULL); 00400 00401 return set_or_delete_string_field (message, 00402 DBUS_HEADER_FIELD_SIGNATURE, 00403 DBUS_TYPE_SIGNATURE, 00404 signature); 00405 } 00406 #endif 00407 00408 /* Message Cache 00409 * 00410 * We cache some DBusMessage to reduce the overhead of allocating 00411 * them. In my profiling this consistently made about an 8% 00412 * difference. It avoids the malloc for the message, the malloc for 00413 * the slot list, the malloc for the header string and body string, 00414 * and the associated free() calls. It does introduce another global 00415 * lock which could be a performance issue in certain cases. 00416 * 00417 * For the echo client/server the round trip time goes from around 00418 * .000077 to .000069 with the message cache on my laptop. The sysprof 00419 * change is as follows (numbers are cumulative percentage): 00420 * 00421 * with message cache implemented as array as it is now (0.000069 per): 00422 * new_empty_header 1.46 00423 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache) 00424 * mutex_unlock 0.25 00425 * self 0.41 00426 * unref 2.24 00427 * self 0.68 00428 * list_clear 0.43 00429 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache) 00430 * mutex_unlock 0.25 00431 * 00432 * with message cache implemented as list (0.000070 per roundtrip): 00433 * new_empty_header 2.72 00434 * list_pop_first 1.88 00435 * unref 3.3 00436 * list_prepend 1.63 00437 * 00438 * without cache (0.000077 per roundtrip): 00439 * new_empty_header 6.7 00440 * string_init_preallocated 3.43 00441 * dbus_malloc 2.43 00442 * dbus_malloc0 2.59 00443 * 00444 * unref 4.02 00445 * string_free 1.82 00446 * dbus_free 1.63 00447 * dbus_free 0.71 00448 * 00449 * If you implement the message_cache with a list, the primary reason 00450 * it's slower is that you add another thread lock (on the DBusList 00451 * mempool). 00452 */ 00453 00455 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE 00456 00458 #define MAX_MESSAGE_CACHE_SIZE 5 00459 00460 _DBUS_DEFINE_GLOBAL_LOCK (message_cache); 00461 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; 00462 static int message_cache_count = 0; 00463 static dbus_bool_t message_cache_shutdown_registered = FALSE; 00464 00465 static void 00466 dbus_message_cache_shutdown (void *data) 00467 { 00468 int i; 00469 00470 _DBUS_LOCK (message_cache); 00471 00472 i = 0; 00473 while (i < MAX_MESSAGE_CACHE_SIZE) 00474 { 00475 if (message_cache[i]) 00476 dbus_message_finalize (message_cache[i]); 00477 00478 ++i; 00479 } 00480 00481 message_cache_count = 0; 00482 message_cache_shutdown_registered = FALSE; 00483 00484 _DBUS_UNLOCK (message_cache); 00485 } 00486 00494 static DBusMessage* 00495 dbus_message_get_cached (void) 00496 { 00497 DBusMessage *message; 00498 int i; 00499 00500 message = NULL; 00501 00502 _DBUS_LOCK (message_cache); 00503 00504 _dbus_assert (message_cache_count >= 0); 00505 00506 if (message_cache_count == 0) 00507 { 00508 _DBUS_UNLOCK (message_cache); 00509 return NULL; 00510 } 00511 00512 /* This is not necessarily true unless count > 0, and 00513 * message_cache is uninitialized until the shutdown is 00514 * registered 00515 */ 00516 _dbus_assert (message_cache_shutdown_registered); 00517 00518 i = 0; 00519 while (i < MAX_MESSAGE_CACHE_SIZE) 00520 { 00521 if (message_cache[i]) 00522 { 00523 message = message_cache[i]; 00524 message_cache[i] = NULL; 00525 message_cache_count -= 1; 00526 break; 00527 } 00528 ++i; 00529 } 00530 _dbus_assert (message_cache_count >= 0); 00531 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00532 _dbus_assert (message != NULL); 00533 00534 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00535 00536 _dbus_assert (message->counters == NULL); 00537 00538 _DBUS_UNLOCK (message_cache); 00539 00540 return message; 00541 } 00542 00543 #ifdef HAVE_UNIX_FD_PASSING 00544 static void 00545 close_unix_fds(int *fds, unsigned *n_fds) 00546 { 00547 DBusError e; 00548 int i; 00549 00550 if (*n_fds <= 0) 00551 return; 00552 00553 dbus_error_init(&e); 00554 00555 for (i = 0; i < *n_fds; i++) 00556 { 00557 if (!_dbus_close(fds[i], &e)) 00558 { 00559 _dbus_warn("Failed to close file descriptor: %s\n", e.message); 00560 dbus_error_free(&e); 00561 } 00562 } 00563 00564 *n_fds = 0; 00565 00566 /* We don't free the array here, in case we can recycle it later */ 00567 } 00568 #endif 00569 00570 static void 00571 free_counter (void *element, 00572 void *data) 00573 { 00574 DBusCounter *counter = element; 00575 DBusMessage *message = data; 00576 00577 _dbus_counter_adjust_size (counter, - message->size_counter_delta); 00578 #ifdef HAVE_UNIX_FD_PASSING 00579 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta); 00580 #endif 00581 00582 _dbus_counter_notify (counter); 00583 _dbus_counter_unref (counter); 00584 } 00585 00591 static void 00592 dbus_message_cache_or_finalize (DBusMessage *message) 00593 { 00594 dbus_bool_t was_cached; 00595 int i; 00596 00597 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00598 00599 /* This calls application code and has to be done first thing 00600 * without holding the lock 00601 */ 00602 _dbus_data_slot_list_clear (&message->slot_list); 00603 00604 _dbus_list_foreach (&message->counters, 00605 free_counter, message); 00606 _dbus_list_clear (&message->counters); 00607 00608 #ifdef HAVE_UNIX_FD_PASSING 00609 close_unix_fds(message->unix_fds, &message->n_unix_fds); 00610 #endif 00611 00612 was_cached = FALSE; 00613 00614 _DBUS_LOCK (message_cache); 00615 00616 if (!message_cache_shutdown_registered) 00617 { 00618 _dbus_assert (message_cache_count == 0); 00619 00620 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL)) 00621 goto out; 00622 00623 i = 0; 00624 while (i < MAX_MESSAGE_CACHE_SIZE) 00625 { 00626 message_cache[i] = NULL; 00627 ++i; 00628 } 00629 00630 message_cache_shutdown_registered = TRUE; 00631 } 00632 00633 _dbus_assert (message_cache_count >= 0); 00634 00635 if ((_dbus_string_get_length (&message->header.data) + 00636 _dbus_string_get_length (&message->body)) > 00637 MAX_MESSAGE_SIZE_TO_CACHE) 00638 goto out; 00639 00640 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE) 00641 goto out; 00642 00643 /* Find empty slot */ 00644 i = 0; 00645 while (message_cache[i] != NULL) 00646 ++i; 00647 00648 _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE); 00649 00650 _dbus_assert (message_cache[i] == NULL); 00651 message_cache[i] = message; 00652 message_cache_count += 1; 00653 was_cached = TRUE; 00654 #ifndef DBUS_DISABLE_CHECKS 00655 message->in_cache = TRUE; 00656 #endif 00657 00658 out: 00659 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 00660 00661 _DBUS_UNLOCK (message_cache); 00662 00663 if (!was_cached) 00664 dbus_message_finalize (message); 00665 } 00666 00667 #ifndef DBUS_DISABLE_CHECKS 00668 static dbus_bool_t 00669 _dbus_message_iter_check (DBusMessageRealIter *iter) 00670 { 00671 char byte_order; 00672 00673 if (iter == NULL) 00674 { 00675 _dbus_warn_check_failed ("dbus message iterator is NULL\n"); 00676 return FALSE; 00677 } 00678 00679 byte_order = _dbus_header_get_byte_order (&iter->message->header); 00680 00681 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER) 00682 { 00683 if (iter->u.reader.byte_order != byte_order) 00684 { 00685 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n"); 00686 return FALSE; 00687 } 00688 /* because we swap the message into compiler order when you init an iter */ 00689 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER); 00690 } 00691 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER) 00692 { 00693 if (iter->u.writer.byte_order != byte_order) 00694 { 00695 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n"); 00696 return FALSE; 00697 } 00698 /* because we swap the message into compiler order when you init an iter */ 00699 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER); 00700 } 00701 else 00702 { 00703 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n"); 00704 return FALSE; 00705 } 00706 00707 if (iter->changed_stamp != iter->message->changed_stamp) 00708 { 00709 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); 00710 return FALSE; 00711 } 00712 00713 return TRUE; 00714 } 00715 #endif /* DBUS_DISABLE_CHECKS */ 00716 00731 dbus_bool_t 00732 _dbus_message_iter_get_args_valist (DBusMessageIter *iter, 00733 DBusError *error, 00734 int first_arg_type, 00735 va_list var_args) 00736 { 00737 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 00738 int spec_type, msg_type, i; 00739 dbus_bool_t retval; 00740 00741 _dbus_assert (_dbus_message_iter_check (real)); 00742 00743 retval = FALSE; 00744 00745 spec_type = first_arg_type; 00746 i = 0; 00747 00748 while (spec_type != DBUS_TYPE_INVALID) 00749 { 00750 msg_type = dbus_message_iter_get_arg_type (iter); 00751 00752 if (msg_type != spec_type) 00753 { 00754 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00755 "Argument %d is specified to be of type \"%s\", but " 00756 "is actually of type \"%s\"\n", i, 00757 _dbus_type_to_string (spec_type), 00758 _dbus_type_to_string (msg_type)); 00759 00760 goto out; 00761 } 00762 00763 if (spec_type == DBUS_TYPE_UNIX_FD) 00764 { 00765 #ifdef HAVE_UNIX_FD_PASSING 00766 DBusBasicValue idx; 00767 int *pfd, nfd; 00768 00769 pfd = va_arg (var_args, int*); 00770 _dbus_assert(pfd); 00771 00772 _dbus_type_reader_read_basic(&real->u.reader, &idx); 00773 00774 if (idx.u32 >= real->message->n_unix_fds) 00775 { 00776 dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE, 00777 "Message refers to file descriptor at index %i," 00778 "but has only %i descriptors attached.\n", 00779 idx.u32, 00780 real->message->n_unix_fds); 00781 goto out; 00782 } 00783 00784 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0) 00785 goto out; 00786 00787 *pfd = nfd; 00788 #else 00789 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00790 "Platform does not support file desciptor passing.\n"); 00791 goto out; 00792 #endif 00793 } 00794 else if (dbus_type_is_basic (spec_type)) 00795 { 00796 DBusBasicValue *ptr; 00797 00798 ptr = va_arg (var_args, DBusBasicValue*); 00799 00800 _dbus_assert (ptr != NULL); 00801 00802 _dbus_type_reader_read_basic (&real->u.reader, 00803 ptr); 00804 } 00805 else if (spec_type == DBUS_TYPE_ARRAY) 00806 { 00807 int element_type; 00808 int spec_element_type; 00809 const DBusBasicValue **ptr; 00810 int *n_elements_p; 00811 DBusTypeReader array; 00812 00813 spec_element_type = va_arg (var_args, int); 00814 element_type = _dbus_type_reader_get_element_type (&real->u.reader); 00815 00816 if (spec_element_type != element_type) 00817 { 00818 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00819 "Argument %d is specified to be an array of \"%s\", but " 00820 "is actually an array of \"%s\"\n", 00821 i, 00822 _dbus_type_to_string (spec_element_type), 00823 _dbus_type_to_string (element_type)); 00824 00825 goto out; 00826 } 00827 00828 if (dbus_type_is_fixed (spec_element_type) && 00829 element_type != DBUS_TYPE_UNIX_FD) 00830 { 00831 ptr = va_arg (var_args, const DBusBasicValue**); 00832 n_elements_p = va_arg (var_args, int*); 00833 00834 _dbus_assert (ptr != NULL); 00835 _dbus_assert (n_elements_p != NULL); 00836 00837 _dbus_type_reader_recurse (&real->u.reader, &array); 00838 00839 _dbus_type_reader_read_fixed_multi (&array, 00840 (void *) ptr, n_elements_p); 00841 } 00842 else if (spec_element_type == DBUS_TYPE_STRING || 00843 spec_element_type == DBUS_TYPE_SIGNATURE || 00844 spec_element_type == DBUS_TYPE_OBJECT_PATH) 00845 { 00846 char ***str_array_p; 00847 int n_elements; 00848 char **str_array; 00849 00850 str_array_p = va_arg (var_args, char***); 00851 n_elements_p = va_arg (var_args, int*); 00852 00853 _dbus_assert (str_array_p != NULL); 00854 _dbus_assert (n_elements_p != NULL); 00855 00856 /* Count elements in the array */ 00857 _dbus_type_reader_recurse (&real->u.reader, &array); 00858 00859 n_elements = 0; 00860 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 00861 { 00862 ++n_elements; 00863 _dbus_type_reader_next (&array); 00864 } 00865 00866 str_array = dbus_new0 (char*, n_elements + 1); 00867 if (str_array == NULL) 00868 { 00869 _DBUS_SET_OOM (error); 00870 goto out; 00871 } 00872 00873 /* Now go through and dup each string */ 00874 _dbus_type_reader_recurse (&real->u.reader, &array); 00875 00876 i = 0; 00877 while (i < n_elements) 00878 { 00879 const char *s; 00880 _dbus_type_reader_read_basic (&array, 00881 (void *) &s); 00882 00883 str_array[i] = _dbus_strdup (s); 00884 if (str_array[i] == NULL) 00885 { 00886 dbus_free_string_array (str_array); 00887 _DBUS_SET_OOM (error); 00888 goto out; 00889 } 00890 00891 ++i; 00892 00893 if (!_dbus_type_reader_next (&array)) 00894 _dbus_assert (i == n_elements); 00895 } 00896 00897 _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); 00898 _dbus_assert (i == n_elements); 00899 _dbus_assert (str_array[i] == NULL); 00900 00901 *str_array_p = str_array; 00902 *n_elements_p = n_elements; 00903 } 00904 #ifndef DBUS_DISABLE_CHECKS 00905 else 00906 { 00907 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", 00908 _DBUS_FUNCTION_NAME); 00909 goto out; 00910 } 00911 #endif 00912 } 00913 #ifndef DBUS_DISABLE_CHECKS 00914 else 00915 { 00916 _dbus_warn ("you can only read arrays and basic types with %s for now\n", 00917 _DBUS_FUNCTION_NAME); 00918 goto out; 00919 } 00920 #endif 00921 00922 spec_type = va_arg (var_args, int); 00923 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) 00924 { 00925 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 00926 "Message has only %d arguments, but more were expected", i); 00927 goto out; 00928 } 00929 00930 i++; 00931 } 00932 00933 retval = TRUE; 00934 00935 out: 00936 00937 return retval; 00938 } 00939 00998 dbus_uint32_t 00999 dbus_message_get_serial (DBusMessage *message) 01000 { 01001 _dbus_return_val_if_fail (message != NULL, 0); 01002 01003 return _dbus_header_get_serial (&message->header); 01004 } 01005 01014 dbus_bool_t 01015 dbus_message_set_reply_serial (DBusMessage *message, 01016 dbus_uint32_t reply_serial) 01017 { 01018 _dbus_return_val_if_fail (message != NULL, FALSE); 01019 _dbus_return_val_if_fail (!message->locked, FALSE); 01020 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */ 01021 01022 return _dbus_header_set_field_basic (&message->header, 01023 DBUS_HEADER_FIELD_REPLY_SERIAL, 01024 DBUS_TYPE_UINT32, 01025 &reply_serial); 01026 } 01027 01034 dbus_uint32_t 01035 dbus_message_get_reply_serial (DBusMessage *message) 01036 { 01037 dbus_uint32_t v_UINT32; 01038 01039 _dbus_return_val_if_fail (message != NULL, 0); 01040 01041 if (_dbus_header_get_field_basic (&message->header, 01042 DBUS_HEADER_FIELD_REPLY_SERIAL, 01043 DBUS_TYPE_UINT32, 01044 &v_UINT32)) 01045 return v_UINT32; 01046 else 01047 return 0; 01048 } 01049 01050 static void 01051 dbus_message_finalize (DBusMessage *message) 01052 { 01053 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01054 01055 /* This calls application callbacks! */ 01056 _dbus_data_slot_list_free (&message->slot_list); 01057 01058 _dbus_list_foreach (&message->counters, 01059 free_counter, message); 01060 _dbus_list_clear (&message->counters); 01061 01062 _dbus_header_free (&message->header); 01063 _dbus_string_free (&message->body); 01064 01065 #ifdef HAVE_UNIX_FD_PASSING 01066 close_unix_fds(message->unix_fds, &message->n_unix_fds); 01067 dbus_free(message->unix_fds); 01068 #endif 01069 01070 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0); 01071 01072 dbus_free (message); 01073 } 01074 01075 static DBusMessage* 01076 dbus_message_new_empty_header (void) 01077 { 01078 DBusMessage *message; 01079 dbus_bool_t from_cache; 01080 01081 message = dbus_message_get_cached (); 01082 01083 if (message != NULL) 01084 { 01085 from_cache = TRUE; 01086 } 01087 else 01088 { 01089 from_cache = FALSE; 01090 message = dbus_new0 (DBusMessage, 1); 01091 if (message == NULL) 01092 return NULL; 01093 #ifndef DBUS_DISABLE_CHECKS 01094 message->generation = _dbus_current_generation; 01095 #endif 01096 01097 #ifdef HAVE_UNIX_FD_PASSING 01098 message->unix_fds = NULL; 01099 message->n_unix_fds_allocated = 0; 01100 #endif 01101 } 01102 01103 _dbus_atomic_inc (&message->refcount); 01104 01105 message->locked = FALSE; 01106 #ifndef DBUS_DISABLE_CHECKS 01107 message->in_cache = FALSE; 01108 #endif 01109 message->counters = NULL; 01110 message->size_counter_delta = 0; 01111 message->changed_stamp = 0; 01112 01113 #ifdef HAVE_UNIX_FD_PASSING 01114 message->n_unix_fds = 0; 01115 message->n_unix_fds_allocated = 0; 01116 message->unix_fd_counter_delta = 0; 01117 #endif 01118 01119 if (!from_cache) 01120 _dbus_data_slot_list_init (&message->slot_list); 01121 01122 if (from_cache) 01123 { 01124 _dbus_header_reinit (&message->header); 01125 _dbus_string_set_length (&message->body, 0); 01126 } 01127 else 01128 { 01129 if (!_dbus_header_init (&message->header)) 01130 { 01131 dbus_free (message); 01132 return NULL; 01133 } 01134 01135 if (!_dbus_string_init_preallocated (&message->body, 32)) 01136 { 01137 _dbus_header_free (&message->header); 01138 dbus_free (message); 01139 return NULL; 01140 } 01141 } 01142 01143 return message; 01144 } 01145 01158 DBusMessage* 01159 dbus_message_new (int message_type) 01160 { 01161 DBusMessage *message; 01162 01163 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL); 01164 01165 message = dbus_message_new_empty_header (); 01166 if (message == NULL) 01167 return NULL; 01168 01169 if (!_dbus_header_create (&message->header, 01170 DBUS_COMPILER_BYTE_ORDER, 01171 message_type, 01172 NULL, NULL, NULL, NULL, NULL)) 01173 { 01174 dbus_message_unref (message); 01175 return NULL; 01176 } 01177 01178 return message; 01179 } 01180 01202 DBusMessage* 01203 dbus_message_new_method_call (const char *destination, 01204 const char *path, 01205 const char *interface, 01206 const char *method) 01207 { 01208 DBusMessage *message; 01209 01210 _dbus_return_val_if_fail (path != NULL, NULL); 01211 _dbus_return_val_if_fail (method != NULL, NULL); 01212 _dbus_return_val_if_fail (destination == NULL || 01213 _dbus_check_is_valid_bus_name (destination), NULL); 01214 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01215 _dbus_return_val_if_fail (interface == NULL || 01216 _dbus_check_is_valid_interface (interface), NULL); 01217 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL); 01218 01219 message = dbus_message_new_empty_header (); 01220 if (message == NULL) 01221 return NULL; 01222 01223 if (!_dbus_header_create (&message->header, 01224 DBUS_COMPILER_BYTE_ORDER, 01225 DBUS_MESSAGE_TYPE_METHOD_CALL, 01226 destination, path, interface, method, NULL)) 01227 { 01228 dbus_message_unref (message); 01229 return NULL; 01230 } 01231 01232 return message; 01233 } 01234 01242 DBusMessage* 01243 dbus_message_new_method_return (DBusMessage *method_call) 01244 { 01245 DBusMessage *message; 01246 const char *sender; 01247 01248 _dbus_return_val_if_fail (method_call != NULL, NULL); 01249 01250 sender = dbus_message_get_sender (method_call); 01251 01252 /* sender is allowed to be null here in peer-to-peer case */ 01253 01254 message = dbus_message_new_empty_header (); 01255 if (message == NULL) 01256 return NULL; 01257 01258 if (!_dbus_header_create (&message->header, 01259 DBUS_COMPILER_BYTE_ORDER, 01260 DBUS_MESSAGE_TYPE_METHOD_RETURN, 01261 sender, NULL, NULL, NULL, NULL)) 01262 { 01263 dbus_message_unref (message); 01264 return NULL; 01265 } 01266 01267 dbus_message_set_no_reply (message, TRUE); 01268 01269 if (!dbus_message_set_reply_serial (message, 01270 dbus_message_get_serial (method_call))) 01271 { 01272 dbus_message_unref (message); 01273 return NULL; 01274 } 01275 01276 return message; 01277 } 01278 01293 DBusMessage* 01294 dbus_message_new_signal (const char *path, 01295 const char *interface, 01296 const char *name) 01297 { 01298 DBusMessage *message; 01299 01300 _dbus_return_val_if_fail (path != NULL, NULL); 01301 _dbus_return_val_if_fail (interface != NULL, NULL); 01302 _dbus_return_val_if_fail (name != NULL, NULL); 01303 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL); 01304 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL); 01305 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL); 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_SIGNAL, 01314 NULL, path, interface, name, NULL)) 01315 { 01316 dbus_message_unref (message); 01317 return NULL; 01318 } 01319 01320 dbus_message_set_no_reply (message, TRUE); 01321 01322 return message; 01323 } 01324 01339 DBusMessage* 01340 dbus_message_new_error (DBusMessage *reply_to, 01341 const char *error_name, 01342 const char *error_message) 01343 { 01344 DBusMessage *message; 01345 const char *sender; 01346 DBusMessageIter iter; 01347 01348 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01349 _dbus_return_val_if_fail (error_name != NULL, NULL); 01350 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01351 01352 sender = dbus_message_get_sender (reply_to); 01353 01354 /* sender may be NULL for non-message-bus case or 01355 * when the message bus is dealing with an unregistered 01356 * connection. 01357 */ 01358 message = dbus_message_new_empty_header (); 01359 if (message == NULL) 01360 return NULL; 01361 01362 if (!_dbus_header_create (&message->header, 01363 DBUS_COMPILER_BYTE_ORDER, 01364 DBUS_MESSAGE_TYPE_ERROR, 01365 sender, NULL, NULL, NULL, error_name)) 01366 { 01367 dbus_message_unref (message); 01368 return NULL; 01369 } 01370 01371 dbus_message_set_no_reply (message, TRUE); 01372 01373 if (!dbus_message_set_reply_serial (message, 01374 dbus_message_get_serial (reply_to))) 01375 { 01376 dbus_message_unref (message); 01377 return NULL; 01378 } 01379 01380 if (error_message != NULL) 01381 { 01382 dbus_message_iter_init_append (message, &iter); 01383 if (!dbus_message_iter_append_basic (&iter, 01384 DBUS_TYPE_STRING, 01385 &error_message)) 01386 { 01387 dbus_message_unref (message); 01388 return NULL; 01389 } 01390 } 01391 01392 return message; 01393 } 01394 01411 DBusMessage* 01412 dbus_message_new_error_printf (DBusMessage *reply_to, 01413 const char *error_name, 01414 const char *error_format, 01415 ...) 01416 { 01417 va_list args; 01418 DBusString str; 01419 DBusMessage *message; 01420 01421 _dbus_return_val_if_fail (reply_to != NULL, NULL); 01422 _dbus_return_val_if_fail (error_name != NULL, NULL); 01423 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL); 01424 01425 if (!_dbus_string_init (&str)) 01426 return NULL; 01427 01428 va_start (args, error_format); 01429 01430 if (_dbus_string_append_printf_valist (&str, error_format, args)) 01431 message = dbus_message_new_error (reply_to, error_name, 01432 _dbus_string_get_const_data (&str)); 01433 else 01434 message = NULL; 01435 01436 _dbus_string_free (&str); 01437 01438 va_end (args); 01439 01440 return message; 01441 } 01442 01443 01456 DBusMessage * 01457 dbus_message_copy (const DBusMessage *message) 01458 { 01459 DBusMessage *retval; 01460 01461 _dbus_return_val_if_fail (message != NULL, NULL); 01462 01463 retval = dbus_new0 (DBusMessage, 1); 01464 if (retval == NULL) 01465 return NULL; 01466 01467 _dbus_atomic_inc (&retval->refcount); 01468 01469 retval->locked = FALSE; 01470 #ifndef DBUS_DISABLE_CHECKS 01471 retval->generation = message->generation; 01472 #endif 01473 01474 if (!_dbus_header_copy (&message->header, &retval->header)) 01475 { 01476 dbus_free (retval); 01477 return NULL; 01478 } 01479 01480 if (!_dbus_string_init_preallocated (&retval->body, 01481 _dbus_string_get_length (&message->body))) 01482 { 01483 _dbus_header_free (&retval->header); 01484 dbus_free (retval); 01485 return NULL; 01486 } 01487 01488 if (!_dbus_string_copy (&message->body, 0, 01489 &retval->body, 0)) 01490 goto failed_copy; 01491 01492 #ifdef HAVE_UNIX_FD_PASSING 01493 retval->unix_fds = dbus_new(int, message->n_unix_fds); 01494 if (retval->unix_fds == NULL && message->n_unix_fds > 0) 01495 goto failed_copy; 01496 01497 retval->n_unix_fds_allocated = message->n_unix_fds; 01498 01499 for (retval->n_unix_fds = 0; 01500 retval->n_unix_fds < message->n_unix_fds; 01501 retval->n_unix_fds++) 01502 { 01503 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL); 01504 01505 if (retval->unix_fds[retval->n_unix_fds] < 0) 01506 goto failed_copy; 01507 } 01508 01509 #endif 01510 01511 return retval; 01512 01513 failed_copy: 01514 _dbus_header_free (&retval->header); 01515 _dbus_string_free (&retval->body); 01516 01517 #ifdef HAVE_UNIX_FD_PASSING 01518 close_unix_fds(retval->unix_fds, &retval->n_unix_fds); 01519 dbus_free(retval->unix_fds); 01520 #endif 01521 01522 dbus_free (retval); 01523 01524 return NULL; 01525 } 01526 01527 01535 DBusMessage * 01536 dbus_message_ref (DBusMessage *message) 01537 { 01538 #ifndef DBUS_DISABLE_ASSERT 01539 dbus_int32_t old_refcount; 01540 #endif 01541 01542 _dbus_return_val_if_fail (message != NULL, NULL); 01543 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); 01544 _dbus_return_val_if_fail (!message->in_cache, NULL); 01545 01546 #ifdef DBUS_DISABLE_ASSERT 01547 _dbus_atomic_inc (&message->refcount); 01548 #else 01549 old_refcount = _dbus_atomic_inc (&message->refcount); 01550 _dbus_assert (old_refcount >= 1); 01551 #endif 01552 01553 return message; 01554 } 01555 01563 void 01564 dbus_message_unref (DBusMessage *message) 01565 { 01566 dbus_int32_t old_refcount; 01567 01568 _dbus_return_if_fail (message != NULL); 01569 _dbus_return_if_fail (message->generation == _dbus_current_generation); 01570 _dbus_return_if_fail (!message->in_cache); 01571 01572 old_refcount = _dbus_atomic_dec (&message->refcount); 01573 01574 _dbus_assert (old_refcount >= 1); 01575 01576 if (old_refcount == 1) 01577 { 01578 /* Calls application callbacks! */ 01579 dbus_message_cache_or_finalize (message); 01580 } 01581 } 01582 01593 int 01594 dbus_message_get_type (DBusMessage *message) 01595 { 01596 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID); 01597 01598 return _dbus_header_get_message_type (&message->header); 01599 } 01600 01663 dbus_bool_t 01664 dbus_message_append_args (DBusMessage *message, 01665 int first_arg_type, 01666 ...) 01667 { 01668 dbus_bool_t retval; 01669 va_list var_args; 01670 01671 _dbus_return_val_if_fail (message != NULL, FALSE); 01672 01673 va_start (var_args, first_arg_type); 01674 retval = dbus_message_append_args_valist (message, 01675 first_arg_type, 01676 var_args); 01677 va_end (var_args); 01678 01679 return retval; 01680 } 01681 01695 dbus_bool_t 01696 dbus_message_append_args_valist (DBusMessage *message, 01697 int first_arg_type, 01698 va_list var_args) 01699 { 01700 int type; 01701 DBusMessageIter iter; 01702 01703 _dbus_return_val_if_fail (message != NULL, FALSE); 01704 01705 type = first_arg_type; 01706 01707 dbus_message_iter_init_append (message, &iter); 01708 01709 while (type != DBUS_TYPE_INVALID) 01710 { 01711 if (dbus_type_is_basic (type)) 01712 { 01713 const DBusBasicValue *value; 01714 value = va_arg (var_args, const DBusBasicValue*); 01715 01716 if (!dbus_message_iter_append_basic (&iter, 01717 type, 01718 value)) 01719 goto failed; 01720 } 01721 else if (type == DBUS_TYPE_ARRAY) 01722 { 01723 int element_type; 01724 DBusMessageIter array; 01725 char buf[2]; 01726 01727 element_type = va_arg (var_args, int); 01728 01729 buf[0] = element_type; 01730 buf[1] = '\0'; 01731 if (!dbus_message_iter_open_container (&iter, 01732 DBUS_TYPE_ARRAY, 01733 buf, 01734 &array)) 01735 goto failed; 01736 01737 if (dbus_type_is_fixed (element_type) && 01738 element_type != DBUS_TYPE_UNIX_FD) 01739 { 01740 const DBusBasicValue **value; 01741 int n_elements; 01742 01743 value = va_arg (var_args, const DBusBasicValue**); 01744 n_elements = va_arg (var_args, int); 01745 01746 if (!dbus_message_iter_append_fixed_array (&array, 01747 element_type, 01748 value, 01749 n_elements)) { 01750 dbus_message_iter_abandon_container (&iter, &array); 01751 goto failed; 01752 } 01753 } 01754 else if (element_type == DBUS_TYPE_STRING || 01755 element_type == DBUS_TYPE_SIGNATURE || 01756 element_type == DBUS_TYPE_OBJECT_PATH) 01757 { 01758 const char ***value_p; 01759 const char **value; 01760 int n_elements; 01761 int i; 01762 01763 value_p = va_arg (var_args, const char***); 01764 n_elements = va_arg (var_args, int); 01765 01766 value = *value_p; 01767 01768 i = 0; 01769 while (i < n_elements) 01770 { 01771 if (!dbus_message_iter_append_basic (&array, 01772 element_type, 01773 &value[i])) { 01774 dbus_message_iter_abandon_container (&iter, &array); 01775 goto failed; 01776 } 01777 ++i; 01778 } 01779 } 01780 else 01781 { 01782 _dbus_warn ("arrays of %s can't be appended with %s for now\n", 01783 _dbus_type_to_string (element_type), 01784 _DBUS_FUNCTION_NAME); 01785 goto failed; 01786 } 01787 01788 if (!dbus_message_iter_close_container (&iter, &array)) 01789 goto failed; 01790 } 01791 #ifndef DBUS_DISABLE_CHECKS 01792 else 01793 { 01794 _dbus_warn ("type %s isn't supported yet in %s\n", 01795 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME); 01796 goto failed; 01797 } 01798 #endif 01799 01800 type = va_arg (var_args, int); 01801 } 01802 01803 return TRUE; 01804 01805 failed: 01806 return FALSE; 01807 } 01808 01853 dbus_bool_t 01854 dbus_message_get_args (DBusMessage *message, 01855 DBusError *error, 01856 int first_arg_type, 01857 ...) 01858 { 01859 dbus_bool_t retval; 01860 va_list var_args; 01861 01862 _dbus_return_val_if_fail (message != NULL, FALSE); 01863 _dbus_return_val_if_error_is_set (error, FALSE); 01864 01865 va_start (var_args, first_arg_type); 01866 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args); 01867 va_end (var_args); 01868 01869 return retval; 01870 } 01871 01882 dbus_bool_t 01883 dbus_message_get_args_valist (DBusMessage *message, 01884 DBusError *error, 01885 int first_arg_type, 01886 va_list var_args) 01887 { 01888 DBusMessageIter iter; 01889 01890 _dbus_return_val_if_fail (message != NULL, FALSE); 01891 _dbus_return_val_if_error_is_set (error, FALSE); 01892 01893 dbus_message_iter_init (message, &iter); 01894 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); 01895 } 01896 01897 static void 01898 _dbus_message_iter_init_common (DBusMessage *message, 01899 DBusMessageRealIter *real, 01900 int iter_type) 01901 { 01902 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter)); 01903 01904 /* Since the iterator will read or write who-knows-what from the 01905 * message, we need to get in the right byte order 01906 */ 01907 ensure_byte_order (message); 01908 01909 real->message = message; 01910 real->changed_stamp = message->changed_stamp; 01911 real->iter_type = iter_type; 01912 real->sig_refcount = 0; 01913 } 01914 01937 dbus_bool_t 01938 dbus_message_iter_init (DBusMessage *message, 01939 DBusMessageIter *iter) 01940 { 01941 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01942 const DBusString *type_str; 01943 int type_pos; 01944 01945 _dbus_return_val_if_fail (message != NULL, FALSE); 01946 _dbus_return_val_if_fail (iter != NULL, FALSE); 01947 01948 get_const_signature (&message->header, &type_str, &type_pos); 01949 01950 _dbus_message_iter_init_common (message, real, 01951 DBUS_MESSAGE_ITER_TYPE_READER); 01952 01953 _dbus_type_reader_init (&real->u.reader, 01954 _dbus_header_get_byte_order (&message->header), 01955 type_str, type_pos, 01956 &message->body, 01957 0); 01958 01959 return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID; 01960 } 01961 01968 dbus_bool_t 01969 dbus_message_iter_has_next (DBusMessageIter *iter) 01970 { 01971 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01972 01973 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01974 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01975 01976 return _dbus_type_reader_has_next (&real->u.reader); 01977 } 01978 01987 dbus_bool_t 01988 dbus_message_iter_next (DBusMessageIter *iter) 01989 { 01990 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 01991 01992 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE); 01993 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 01994 01995 return _dbus_type_reader_next (&real->u.reader); 01996 } 01997 02012 int 02013 dbus_message_iter_get_arg_type (DBusMessageIter *iter) 02014 { 02015 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02016 02017 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02018 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE); 02019 02020 return _dbus_type_reader_get_current_type (&real->u.reader); 02021 } 02022 02031 int 02032 dbus_message_iter_get_element_type (DBusMessageIter *iter) 02033 { 02034 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02035 02036 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID); 02037 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID); 02038 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID); 02039 02040 return _dbus_type_reader_get_element_type (&real->u.reader); 02041 } 02042 02068 void 02069 dbus_message_iter_recurse (DBusMessageIter *iter, 02070 DBusMessageIter *sub) 02071 { 02072 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02073 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02074 02075 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02076 _dbus_return_if_fail (sub != NULL); 02077 02078 *real_sub = *real; 02079 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader); 02080 } 02081 02093 char * 02094 dbus_message_iter_get_signature (DBusMessageIter *iter) 02095 { 02096 const DBusString *sig; 02097 DBusString retstr; 02098 char *ret; 02099 int start, len; 02100 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02101 02102 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL); 02103 02104 if (!_dbus_string_init (&retstr)) 02105 return NULL; 02106 02107 _dbus_type_reader_get_signature (&real->u.reader, &sig, 02108 &start, &len); 02109 if (!_dbus_string_append_len (&retstr, 02110 _dbus_string_get_const_data (sig) + start, 02111 len)) 02112 return NULL; 02113 if (!_dbus_string_steal_data (&retstr, &ret)) 02114 return NULL; 02115 _dbus_string_free (&retstr); 02116 return ret; 02117 } 02118 02166 void 02167 dbus_message_iter_get_basic (DBusMessageIter *iter, 02168 void *value) 02169 { 02170 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02171 02172 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02173 _dbus_return_if_fail (value != NULL); 02174 02175 if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD) 02176 { 02177 #ifdef HAVE_UNIX_FD_PASSING 02178 DBusBasicValue idx; 02179 02180 _dbus_type_reader_read_basic(&real->u.reader, &idx); 02181 02182 if (idx.u32 >= real->message->n_unix_fds) { 02183 /* Hmm, we cannot really signal an error here, so let's make 02184 sure to return an invalid fd. */ 02185 *((int*) value) = -1; 02186 return; 02187 } 02188 02189 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL); 02190 #else 02191 *((int*) value) = -1; 02192 #endif 02193 } 02194 else 02195 { 02196 _dbus_type_reader_read_basic (&real->u.reader, 02197 value); 02198 } 02199 } 02200 02219 int 02220 dbus_message_iter_get_array_len (DBusMessageIter *iter) 02221 { 02222 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02223 02224 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0); 02225 02226 return _dbus_type_reader_get_array_length (&real->u.reader); 02227 } 02228 02264 void 02265 dbus_message_iter_get_fixed_array (DBusMessageIter *iter, 02266 void *value, 02267 int *n_elements) 02268 { 02269 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02270 #ifndef DBUS_DISABLE_CHECKS 02271 int subtype = _dbus_type_reader_get_current_type(&real->u.reader); 02272 02273 _dbus_return_if_fail (_dbus_message_iter_check (real)); 02274 _dbus_return_if_fail (value != NULL); 02275 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) || 02276 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD)); 02277 #endif 02278 02279 _dbus_type_reader_read_fixed_multi (&real->u.reader, 02280 value, n_elements); 02281 } 02282 02294 void 02295 dbus_message_iter_init_append (DBusMessage *message, 02296 DBusMessageIter *iter) 02297 { 02298 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02299 02300 _dbus_return_if_fail (message != NULL); 02301 _dbus_return_if_fail (iter != NULL); 02302 02303 _dbus_message_iter_init_common (message, real, 02304 DBUS_MESSAGE_ITER_TYPE_WRITER); 02305 02306 /* We create the signature string and point iterators at it "on demand" 02307 * when a value is actually appended. That means that init() never fails 02308 * due to OOM. 02309 */ 02310 _dbus_type_writer_init_types_delayed (&real->u.writer, 02311 _dbus_header_get_byte_order (&message->header), 02312 &message->body, 02313 _dbus_string_get_length (&message->body)); 02314 } 02315 02324 static dbus_bool_t 02325 _dbus_message_iter_open_signature (DBusMessageRealIter *real) 02326 { 02327 DBusString *str; 02328 const DBusString *current_sig; 02329 int current_sig_pos; 02330 02331 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02332 02333 if (real->u.writer.type_str != NULL) 02334 { 02335 _dbus_assert (real->sig_refcount > 0); 02336 real->sig_refcount += 1; 02337 return TRUE; 02338 } 02339 02340 str = dbus_new (DBusString, 1); 02341 if (str == NULL) 02342 return FALSE; 02343 02344 if (!_dbus_header_get_field_raw (&real->message->header, 02345 DBUS_HEADER_FIELD_SIGNATURE, 02346 ¤t_sig, ¤t_sig_pos)) 02347 current_sig = NULL; 02348 02349 if (current_sig) 02350 { 02351 int current_len; 02352 02353 current_len = _dbus_string_get_byte (current_sig, current_sig_pos); 02354 current_sig_pos += 1; /* move on to sig data */ 02355 02356 if (!_dbus_string_init_preallocated (str, current_len + 4)) 02357 { 02358 dbus_free (str); 02359 return FALSE; 02360 } 02361 02362 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len, 02363 str, 0)) 02364 { 02365 _dbus_string_free (str); 02366 dbus_free (str); 02367 return FALSE; 02368 } 02369 } 02370 else 02371 { 02372 if (!_dbus_string_init_preallocated (str, 4)) 02373 { 02374 dbus_free (str); 02375 return FALSE; 02376 } 02377 } 02378 02379 real->sig_refcount = 1; 02380 02381 _dbus_type_writer_add_types (&real->u.writer, 02382 str, _dbus_string_get_length (str)); 02383 return TRUE; 02384 } 02385 02395 static dbus_bool_t 02396 _dbus_message_iter_close_signature (DBusMessageRealIter *real) 02397 { 02398 DBusString *str; 02399 const char *v_STRING; 02400 dbus_bool_t retval; 02401 02402 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02403 _dbus_assert (real->u.writer.type_str != NULL); 02404 _dbus_assert (real->sig_refcount > 0); 02405 02406 real->sig_refcount -= 1; 02407 02408 if (real->sig_refcount > 0) 02409 return TRUE; 02410 _dbus_assert (real->sig_refcount == 0); 02411 02412 retval = TRUE; 02413 02414 str = real->u.writer.type_str; 02415 02416 v_STRING = _dbus_string_get_const_data (str); 02417 if (!_dbus_header_set_field_basic (&real->message->header, 02418 DBUS_HEADER_FIELD_SIGNATURE, 02419 DBUS_TYPE_SIGNATURE, 02420 &v_STRING)) 02421 retval = FALSE; 02422 02423 _dbus_type_writer_remove_types (&real->u.writer); 02424 _dbus_string_free (str); 02425 dbus_free (str); 02426 02427 return retval; 02428 } 02429 02437 static void 02438 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real) 02439 { 02440 DBusString *str; 02441 02442 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02443 _dbus_assert (real->u.writer.type_str != NULL); 02444 _dbus_assert (real->sig_refcount > 0); 02445 02446 real->sig_refcount -= 1; 02447 02448 if (real->sig_refcount > 0) 02449 return; 02450 _dbus_assert (real->sig_refcount == 0); 02451 02452 str = real->u.writer.type_str; 02453 02454 _dbus_type_writer_remove_types (&real->u.writer); 02455 _dbus_string_free (str); 02456 dbus_free (str); 02457 } 02458 02459 #ifndef DBUS_DISABLE_CHECKS 02460 static dbus_bool_t 02461 _dbus_message_iter_append_check (DBusMessageRealIter *iter) 02462 { 02463 if (!_dbus_message_iter_check (iter)) 02464 return FALSE; 02465 02466 if (iter->message->locked) 02467 { 02468 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n"); 02469 return FALSE; 02470 } 02471 02472 return TRUE; 02473 } 02474 #endif /* DBUS_DISABLE_CHECKS */ 02475 02476 #ifdef HAVE_UNIX_FD_PASSING 02477 static int * 02478 expand_fd_array(DBusMessage *m, 02479 unsigned n) 02480 { 02481 _dbus_assert(m); 02482 02483 /* This makes space for adding n new fds to the array and returns a 02484 pointer to the place were the first fd should be put. */ 02485 02486 if (m->n_unix_fds + n > m->n_unix_fds_allocated) 02487 { 02488 unsigned k; 02489 int *p; 02490 02491 /* Make twice as much space as necessary */ 02492 k = (m->n_unix_fds + n) * 2; 02493 02494 /* Allocate at least four */ 02495 if (k < 4) 02496 k = 4; 02497 02498 p = dbus_realloc(m->unix_fds, k * sizeof(int)); 02499 if (p == NULL) 02500 return NULL; 02501 02502 m->unix_fds = p; 02503 m->n_unix_fds_allocated = k; 02504 } 02505 02506 return m->unix_fds + m->n_unix_fds; 02507 } 02508 #endif 02509 02529 dbus_bool_t 02530 dbus_message_iter_append_basic (DBusMessageIter *iter, 02531 int type, 02532 const void *value) 02533 { 02534 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02535 dbus_bool_t ret; 02536 02537 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02538 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02539 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE); 02540 _dbus_return_val_if_fail (value != NULL, FALSE); 02541 02542 #ifndef DBUS_DISABLE_CHECKS 02543 switch (type) 02544 { 02545 const char * const *string_p; 02546 const dbus_bool_t *bool_p; 02547 02548 case DBUS_TYPE_STRING: 02549 string_p = value; 02550 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE); 02551 break; 02552 02553 case DBUS_TYPE_OBJECT_PATH: 02554 string_p = value; 02555 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE); 02556 break; 02557 02558 case DBUS_TYPE_SIGNATURE: 02559 string_p = value; 02560 _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE); 02561 break; 02562 02563 case DBUS_TYPE_BOOLEAN: 02564 bool_p = value; 02565 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE); 02566 break; 02567 02568 default: 02569 { 02570 /* nothing to check, all possible values are allowed */ 02571 } 02572 } 02573 #endif 02574 02575 if (!_dbus_message_iter_open_signature (real)) 02576 return FALSE; 02577 02578 if (type == DBUS_TYPE_UNIX_FD) 02579 { 02580 #ifdef HAVE_UNIX_FD_PASSING 02581 int *fds; 02582 dbus_uint32_t u; 02583 02584 /* First step, include the fd in the fd list of this message */ 02585 if (!(fds = expand_fd_array(real->message, 1))) 02586 return FALSE; 02587 02588 *fds = _dbus_dup(*(int*) value, NULL); 02589 if (*fds < 0) 02590 return FALSE; 02591 02592 u = real->message->n_unix_fds; 02593 02594 /* Second step, write the index to the fd */ 02595 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) { 02596 _dbus_close(*fds, NULL); 02597 return FALSE; 02598 } 02599 02600 real->message->n_unix_fds += 1; 02601 u += 1; 02602 02603 /* Final step, update the header accordingly */ 02604 ret = _dbus_header_set_field_basic (&real->message->header, 02605 DBUS_HEADER_FIELD_UNIX_FDS, 02606 DBUS_TYPE_UINT32, 02607 &u); 02608 02609 /* If any of these operations fail the message is 02610 hosed. However, no memory or fds should be leaked since what 02611 has been added to message has been added to the message, and 02612 can hence be accounted for when the message is being 02613 freed. */ 02614 #else 02615 ret = FALSE; 02616 #endif 02617 } 02618 else 02619 { 02620 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value); 02621 } 02622 02623 if (!_dbus_message_iter_close_signature (real)) 02624 ret = FALSE; 02625 02626 return ret; 02627 } 02628 02664 dbus_bool_t 02665 dbus_message_iter_append_fixed_array (DBusMessageIter *iter, 02666 int element_type, 02667 const void *value, 02668 int n_elements) 02669 { 02670 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02671 dbus_bool_t ret; 02672 02673 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02674 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02675 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE); 02676 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE); 02677 _dbus_return_val_if_fail (value != NULL, FALSE); 02678 _dbus_return_val_if_fail (n_elements >= 0, FALSE); 02679 _dbus_return_val_if_fail (n_elements <= 02680 DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type), 02681 FALSE); 02682 02683 #ifndef DBUS_DISABLE_CHECKS 02684 if (element_type == DBUS_TYPE_BOOLEAN) 02685 { 02686 const dbus_bool_t * const *bools = value; 02687 int i; 02688 02689 for (i = 0; i < n_elements; i++) 02690 { 02691 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE); 02692 } 02693 } 02694 #endif 02695 02696 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements); 02697 02698 return ret; 02699 } 02700 02722 dbus_bool_t 02723 dbus_message_iter_open_container (DBusMessageIter *iter, 02724 int type, 02725 const char *contained_signature, 02726 DBusMessageIter *sub) 02727 { 02728 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02729 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02730 DBusString contained_str; 02731 02732 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02733 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02734 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE); 02735 _dbus_return_val_if_fail (sub != NULL, FALSE); 02736 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT && 02737 contained_signature == NULL) || 02738 (type == DBUS_TYPE_DICT_ENTRY && 02739 contained_signature == NULL) || 02740 (type == DBUS_TYPE_VARIANT && 02741 contained_signature != NULL) || 02742 (type == DBUS_TYPE_ARRAY && 02743 contained_signature != NULL), FALSE); 02744 02745 /* this would fail if the contained_signature is a dict entry, since 02746 * dict entries are invalid signatures standalone (they must be in 02747 * an array) 02748 */ 02749 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || 02750 (contained_signature == NULL || 02751 _dbus_check_is_valid_signature (contained_signature)), 02752 FALSE); 02753 02754 if (!_dbus_message_iter_open_signature (real)) 02755 return FALSE; 02756 02757 *real_sub = *real; 02758 02759 if (contained_signature != NULL) 02760 { 02761 _dbus_string_init_const (&contained_str, contained_signature); 02762 02763 return _dbus_type_writer_recurse (&real->u.writer, 02764 type, 02765 &contained_str, 0, 02766 &real_sub->u.writer); 02767 } 02768 else 02769 { 02770 return _dbus_type_writer_recurse (&real->u.writer, 02771 type, 02772 NULL, 0, 02773 &real_sub->u.writer); 02774 } 02775 } 02776 02777 02791 dbus_bool_t 02792 dbus_message_iter_close_container (DBusMessageIter *iter, 02793 DBusMessageIter *sub) 02794 { 02795 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02796 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02797 dbus_bool_t ret; 02798 02799 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE); 02800 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02801 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE); 02802 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE); 02803 02804 ret = _dbus_type_writer_unrecurse (&real->u.writer, 02805 &real_sub->u.writer); 02806 02807 if (!_dbus_message_iter_close_signature (real)) 02808 ret = FALSE; 02809 02810 return ret; 02811 } 02812 02824 void 02825 dbus_message_iter_abandon_container (DBusMessageIter *iter, 02826 DBusMessageIter *sub) 02827 { 02828 DBusMessageRealIter *real = (DBusMessageRealIter *)iter; 02829 #ifndef DBUS_DISABLE_CHECKS 02830 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub; 02831 02832 _dbus_return_if_fail (_dbus_message_iter_append_check (real)); 02833 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02834 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub)); 02835 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER); 02836 #endif 02837 02838 _dbus_message_iter_abandon_signature (real); 02839 } 02840 02857 void 02858 dbus_message_set_no_reply (DBusMessage *message, 02859 dbus_bool_t no_reply) 02860 { 02861 _dbus_return_if_fail (message != NULL); 02862 _dbus_return_if_fail (!message->locked); 02863 02864 _dbus_header_toggle_flag (&message->header, 02865 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED, 02866 no_reply); 02867 } 02868 02876 dbus_bool_t 02877 dbus_message_get_no_reply (DBusMessage *message) 02878 { 02879 _dbus_return_val_if_fail (message != NULL, FALSE); 02880 02881 return _dbus_header_get_flag (&message->header, 02882 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED); 02883 } 02884 02899 void 02900 dbus_message_set_auto_start (DBusMessage *message, 02901 dbus_bool_t auto_start) 02902 { 02903 _dbus_return_if_fail (message != NULL); 02904 _dbus_return_if_fail (!message->locked); 02905 02906 _dbus_header_toggle_flag (&message->header, 02907 DBUS_HEADER_FLAG_NO_AUTO_START, 02908 !auto_start); 02909 } 02910 02918 dbus_bool_t 02919 dbus_message_get_auto_start (DBusMessage *message) 02920 { 02921 _dbus_return_val_if_fail (message != NULL, FALSE); 02922 02923 return !_dbus_header_get_flag (&message->header, 02924 DBUS_HEADER_FLAG_NO_AUTO_START); 02925 } 02926 02927 02940 dbus_bool_t 02941 dbus_message_set_path (DBusMessage *message, 02942 const char *object_path) 02943 { 02944 _dbus_return_val_if_fail (message != NULL, FALSE); 02945 _dbus_return_val_if_fail (!message->locked, FALSE); 02946 _dbus_return_val_if_fail (object_path == NULL || 02947 _dbus_check_is_valid_path (object_path), 02948 FALSE); 02949 02950 return set_or_delete_string_field (message, 02951 DBUS_HEADER_FIELD_PATH, 02952 DBUS_TYPE_OBJECT_PATH, 02953 object_path); 02954 } 02955 02969 const char* 02970 dbus_message_get_path (DBusMessage *message) 02971 { 02972 const char *v; 02973 02974 _dbus_return_val_if_fail (message != NULL, NULL); 02975 02976 v = NULL; /* in case field doesn't exist */ 02977 _dbus_header_get_field_basic (&message->header, 02978 DBUS_HEADER_FIELD_PATH, 02979 DBUS_TYPE_OBJECT_PATH, 02980 (void *) &v); 02981 return v; 02982 } 02983 02993 dbus_bool_t 02994 dbus_message_has_path (DBusMessage *message, 02995 const char *path) 02996 { 02997 const char *msg_path; 02998 msg_path = dbus_message_get_path (message); 02999 03000 if (msg_path == NULL) 03001 { 03002 if (path == NULL) 03003 return TRUE; 03004 else 03005 return FALSE; 03006 } 03007 03008 if (path == NULL) 03009 return FALSE; 03010 03011 if (strcmp (msg_path, path) == 0) 03012 return TRUE; 03013 03014 return FALSE; 03015 } 03016 03037 dbus_bool_t 03038 dbus_message_get_path_decomposed (DBusMessage *message, 03039 char ***path) 03040 { 03041 const char *v; 03042 03043 _dbus_return_val_if_fail (message != NULL, FALSE); 03044 _dbus_return_val_if_fail (path != NULL, FALSE); 03045 03046 *path = NULL; 03047 03048 v = dbus_message_get_path (message); 03049 if (v != NULL) 03050 { 03051 if (!_dbus_decompose_path (v, strlen (v), 03052 path, NULL)) 03053 return FALSE; 03054 } 03055 return TRUE; 03056 } 03057 03071 dbus_bool_t 03072 dbus_message_set_interface (DBusMessage *message, 03073 const char *interface) 03074 { 03075 _dbus_return_val_if_fail (message != NULL, FALSE); 03076 _dbus_return_val_if_fail (!message->locked, FALSE); 03077 _dbus_return_val_if_fail (interface == NULL || 03078 _dbus_check_is_valid_interface (interface), 03079 FALSE); 03080 03081 return set_or_delete_string_field (message, 03082 DBUS_HEADER_FIELD_INTERFACE, 03083 DBUS_TYPE_STRING, 03084 interface); 03085 } 03086 03100 const char* 03101 dbus_message_get_interface (DBusMessage *message) 03102 { 03103 const char *v; 03104 03105 _dbus_return_val_if_fail (message != NULL, NULL); 03106 03107 v = NULL; /* in case field doesn't exist */ 03108 _dbus_header_get_field_basic (&message->header, 03109 DBUS_HEADER_FIELD_INTERFACE, 03110 DBUS_TYPE_STRING, 03111 (void *) &v); 03112 return v; 03113 } 03114 03122 dbus_bool_t 03123 dbus_message_has_interface (DBusMessage *message, 03124 const char *interface) 03125 { 03126 const char *msg_interface; 03127 msg_interface = dbus_message_get_interface (message); 03128 03129 if (msg_interface == NULL) 03130 { 03131 if (interface == NULL) 03132 return TRUE; 03133 else 03134 return FALSE; 03135 } 03136 03137 if (interface == NULL) 03138 return FALSE; 03139 03140 if (strcmp (msg_interface, interface) == 0) 03141 return TRUE; 03142 03143 return FALSE; 03144 03145 } 03146 03159 dbus_bool_t 03160 dbus_message_set_member (DBusMessage *message, 03161 const char *member) 03162 { 03163 _dbus_return_val_if_fail (message != NULL, FALSE); 03164 _dbus_return_val_if_fail (!message->locked, FALSE); 03165 _dbus_return_val_if_fail (member == NULL || 03166 _dbus_check_is_valid_member (member), 03167 FALSE); 03168 03169 return set_or_delete_string_field (message, 03170 DBUS_HEADER_FIELD_MEMBER, 03171 DBUS_TYPE_STRING, 03172 member); 03173 } 03174 03186 const char* 03187 dbus_message_get_member (DBusMessage *message) 03188 { 03189 const char *v; 03190 03191 _dbus_return_val_if_fail (message != NULL, NULL); 03192 03193 v = NULL; /* in case field doesn't exist */ 03194 _dbus_header_get_field_basic (&message->header, 03195 DBUS_HEADER_FIELD_MEMBER, 03196 DBUS_TYPE_STRING, 03197 (void *) &v); 03198 return v; 03199 } 03200 03208 dbus_bool_t 03209 dbus_message_has_member (DBusMessage *message, 03210 const char *member) 03211 { 03212 const char *msg_member; 03213 msg_member = dbus_message_get_member (message); 03214 03215 if (msg_member == NULL) 03216 { 03217 if (member == NULL) 03218 return TRUE; 03219 else 03220 return FALSE; 03221 } 03222 03223 if (member == NULL) 03224 return FALSE; 03225 03226 if (strcmp (msg_member, member) == 0) 03227 return TRUE; 03228 03229 return FALSE; 03230 03231 } 03232 03244 dbus_bool_t 03245 dbus_message_set_error_name (DBusMessage *message, 03246 const char *error_name) 03247 { 03248 _dbus_return_val_if_fail (message != NULL, FALSE); 03249 _dbus_return_val_if_fail (!message->locked, FALSE); 03250 _dbus_return_val_if_fail (error_name == NULL || 03251 _dbus_check_is_valid_error_name (error_name), 03252 FALSE); 03253 03254 return set_or_delete_string_field (message, 03255 DBUS_HEADER_FIELD_ERROR_NAME, 03256 DBUS_TYPE_STRING, 03257 error_name); 03258 } 03259 03270 const char* 03271 dbus_message_get_error_name (DBusMessage *message) 03272 { 03273 const char *v; 03274 03275 _dbus_return_val_if_fail (message != NULL, NULL); 03276 03277 v = NULL; /* in case field doesn't exist */ 03278 _dbus_header_get_field_basic (&message->header, 03279 DBUS_HEADER_FIELD_ERROR_NAME, 03280 DBUS_TYPE_STRING, 03281 (void *) &v); 03282 return v; 03283 } 03284 03298 dbus_bool_t 03299 dbus_message_set_destination (DBusMessage *message, 03300 const char *destination) 03301 { 03302 _dbus_return_val_if_fail (message != NULL, FALSE); 03303 _dbus_return_val_if_fail (!message->locked, FALSE); 03304 _dbus_return_val_if_fail (destination == NULL || 03305 _dbus_check_is_valid_bus_name (destination), 03306 FALSE); 03307 03308 return set_or_delete_string_field (message, 03309 DBUS_HEADER_FIELD_DESTINATION, 03310 DBUS_TYPE_STRING, 03311 destination); 03312 } 03313 03323 const char* 03324 dbus_message_get_destination (DBusMessage *message) 03325 { 03326 const char *v; 03327 03328 _dbus_return_val_if_fail (message != NULL, NULL); 03329 03330 v = NULL; /* in case field doesn't exist */ 03331 _dbus_header_get_field_basic (&message->header, 03332 DBUS_HEADER_FIELD_DESTINATION, 03333 DBUS_TYPE_STRING, 03334 (void *) &v); 03335 return v; 03336 } 03337 03352 dbus_bool_t 03353 dbus_message_set_sender (DBusMessage *message, 03354 const char *sender) 03355 { 03356 _dbus_return_val_if_fail (message != NULL, FALSE); 03357 _dbus_return_val_if_fail (!message->locked, FALSE); 03358 _dbus_return_val_if_fail (sender == NULL || 03359 _dbus_check_is_valid_bus_name (sender), 03360 FALSE); 03361 03362 return set_or_delete_string_field (message, 03363 DBUS_HEADER_FIELD_SENDER, 03364 DBUS_TYPE_STRING, 03365 sender); 03366 } 03367 03383 const char* 03384 dbus_message_get_sender (DBusMessage *message) 03385 { 03386 const char *v; 03387 03388 _dbus_return_val_if_fail (message != NULL, NULL); 03389 03390 v = NULL; /* in case field doesn't exist */ 03391 _dbus_header_get_field_basic (&message->header, 03392 DBUS_HEADER_FIELD_SENDER, 03393 DBUS_TYPE_STRING, 03394 (void *) &v); 03395 return v; 03396 } 03397 03416 const char* 03417 dbus_message_get_signature (DBusMessage *message) 03418 { 03419 const DBusString *type_str; 03420 int type_pos; 03421 03422 _dbus_return_val_if_fail (message != NULL, NULL); 03423 03424 get_const_signature (&message->header, &type_str, &type_pos); 03425 03426 return _dbus_string_get_const_data_len (type_str, type_pos, 0); 03427 } 03428 03429 static dbus_bool_t 03430 _dbus_message_has_type_interface_member (DBusMessage *message, 03431 int type, 03432 const char *interface, 03433 const char *member) 03434 { 03435 const char *n; 03436 03437 _dbus_assert (message != NULL); 03438 _dbus_assert (interface != NULL); 03439 _dbus_assert (member != NULL); 03440 03441 if (dbus_message_get_type (message) != type) 03442 return FALSE; 03443 03444 /* Optimize by checking the short member name first 03445 * instead of the longer interface name 03446 */ 03447 03448 n = dbus_message_get_member (message); 03449 03450 if (n && strcmp (n, member) == 0) 03451 { 03452 n = dbus_message_get_interface (message); 03453 03454 if (n == NULL || strcmp (n, interface) == 0) 03455 return TRUE; 03456 } 03457 03458 return FALSE; 03459 } 03460 03475 dbus_bool_t 03476 dbus_message_is_method_call (DBusMessage *message, 03477 const char *interface, 03478 const char *method) 03479 { 03480 _dbus_return_val_if_fail (message != NULL, FALSE); 03481 _dbus_return_val_if_fail (interface != NULL, FALSE); 03482 _dbus_return_val_if_fail (method != NULL, FALSE); 03483 /* don't check that interface/method are valid since it would be 03484 * expensive, and not catch many common errors 03485 */ 03486 03487 return _dbus_message_has_type_interface_member (message, 03488 DBUS_MESSAGE_TYPE_METHOD_CALL, 03489 interface, method); 03490 } 03491 03503 dbus_bool_t 03504 dbus_message_is_signal (DBusMessage *message, 03505 const char *interface, 03506 const char *signal_name) 03507 { 03508 _dbus_return_val_if_fail (message != NULL, FALSE); 03509 _dbus_return_val_if_fail (interface != NULL, FALSE); 03510 _dbus_return_val_if_fail (signal_name != NULL, FALSE); 03511 /* don't check that interface/name are valid since it would be 03512 * expensive, and not catch many common errors 03513 */ 03514 03515 return _dbus_message_has_type_interface_member (message, 03516 DBUS_MESSAGE_TYPE_SIGNAL, 03517 interface, signal_name); 03518 } 03519 03530 dbus_bool_t 03531 dbus_message_is_error (DBusMessage *message, 03532 const char *error_name) 03533 { 03534 const char *n; 03535 03536 _dbus_return_val_if_fail (message != NULL, FALSE); 03537 _dbus_return_val_if_fail (error_name != NULL, FALSE); 03538 /* don't check that error_name is valid since it would be expensive, 03539 * and not catch many common errors 03540 */ 03541 03542 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03543 return FALSE; 03544 03545 n = dbus_message_get_error_name (message); 03546 03547 if (n && strcmp (n, error_name) == 0) 03548 return TRUE; 03549 else 03550 return FALSE; 03551 } 03552 03563 dbus_bool_t 03564 dbus_message_has_destination (DBusMessage *message, 03565 const char *name) 03566 { 03567 const char *s; 03568 03569 _dbus_return_val_if_fail (message != NULL, FALSE); 03570 _dbus_return_val_if_fail (name != NULL, FALSE); 03571 /* don't check that name is valid since it would be expensive, and 03572 * not catch many common errors 03573 */ 03574 03575 s = dbus_message_get_destination (message); 03576 03577 if (s && strcmp (s, name) == 0) 03578 return TRUE; 03579 else 03580 return FALSE; 03581 } 03582 03598 dbus_bool_t 03599 dbus_message_has_sender (DBusMessage *message, 03600 const char *name) 03601 { 03602 const char *s; 03603 03604 _dbus_return_val_if_fail (message != NULL, FALSE); 03605 _dbus_return_val_if_fail (name != NULL, FALSE); 03606 /* don't check that name is valid since it would be expensive, and 03607 * not catch many common errors 03608 */ 03609 03610 s = dbus_message_get_sender (message); 03611 03612 if (s && strcmp (s, name) == 0) 03613 return TRUE; 03614 else 03615 return FALSE; 03616 } 03617 03627 dbus_bool_t 03628 dbus_message_has_signature (DBusMessage *message, 03629 const char *signature) 03630 { 03631 const char *s; 03632 03633 _dbus_return_val_if_fail (message != NULL, FALSE); 03634 _dbus_return_val_if_fail (signature != NULL, FALSE); 03635 /* don't check that signature is valid since it would be expensive, 03636 * and not catch many common errors 03637 */ 03638 03639 s = dbus_message_get_signature (message); 03640 03641 if (s && strcmp (s, signature) == 0) 03642 return TRUE; 03643 else 03644 return FALSE; 03645 } 03646 03669 dbus_bool_t 03670 dbus_set_error_from_message (DBusError *error, 03671 DBusMessage *message) 03672 { 03673 const char *str; 03674 03675 _dbus_return_val_if_fail (message != NULL, FALSE); 03676 _dbus_return_val_if_error_is_set (error, FALSE); 03677 03678 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 03679 return FALSE; 03680 03681 str = NULL; 03682 dbus_message_get_args (message, NULL, 03683 DBUS_TYPE_STRING, &str, 03684 DBUS_TYPE_INVALID); 03685 03686 dbus_set_error (error, dbus_message_get_error_name (message), 03687 str ? "%s" : NULL, str); 03688 03689 return TRUE; 03690 } 03691 03698 dbus_bool_t 03699 dbus_message_contains_unix_fds(DBusMessage *message) 03700 { 03701 #ifdef HAVE_UNIX_FD_PASSING 03702 _dbus_assert(message); 03703 03704 return message->n_unix_fds > 0; 03705 #else 03706 return FALSE; 03707 #endif 03708 } 03709 03728 #define INITIAL_LOADER_DATA_LEN 32 03729 03736 DBusMessageLoader* 03737 _dbus_message_loader_new (void) 03738 { 03739 DBusMessageLoader *loader; 03740 03741 loader = dbus_new0 (DBusMessageLoader, 1); 03742 if (loader == NULL) 03743 return NULL; 03744 03745 loader->refcount = 1; 03746 03747 loader->corrupted = FALSE; 03748 loader->corruption_reason = DBUS_VALID; 03749 03750 /* this can be configured by the app, but defaults to the protocol max */ 03751 loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH; 03752 03753 /* We set a very relatively conservative default here since due to how 03754 SCM_RIGHTS works we need to preallocate an fd array of the maximum 03755 number of unix fds we want to receive in advance. A 03756 try-and-reallocate loop is not possible. */ 03757 loader->max_message_unix_fds = 1024; 03758 03759 if (!_dbus_string_init (&loader->data)) 03760 { 03761 dbus_free (loader); 03762 return NULL; 03763 } 03764 03765 /* preallocate the buffer for speed, ignore failure */ 03766 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN); 03767 _dbus_string_set_length (&loader->data, 0); 03768 03769 #ifdef HAVE_UNIX_FD_PASSING 03770 loader->unix_fds = NULL; 03771 loader->n_unix_fds = loader->n_unix_fds_allocated = 0; 03772 loader->unix_fds_outstanding = FALSE; 03773 #endif 03774 03775 return loader; 03776 } 03777 03784 DBusMessageLoader * 03785 _dbus_message_loader_ref (DBusMessageLoader *loader) 03786 { 03787 loader->refcount += 1; 03788 03789 return loader; 03790 } 03791 03798 void 03799 _dbus_message_loader_unref (DBusMessageLoader *loader) 03800 { 03801 loader->refcount -= 1; 03802 if (loader->refcount == 0) 03803 { 03804 #ifdef HAVE_UNIX_FD_PASSING 03805 close_unix_fds(loader->unix_fds, &loader->n_unix_fds); 03806 dbus_free(loader->unix_fds); 03807 #endif 03808 _dbus_list_foreach (&loader->messages, 03809 (DBusForeachFunction) dbus_message_unref, 03810 NULL); 03811 _dbus_list_clear (&loader->messages); 03812 _dbus_string_free (&loader->data); 03813 dbus_free (loader); 03814 } 03815 } 03816 03835 void 03836 _dbus_message_loader_get_buffer (DBusMessageLoader *loader, 03837 DBusString **buffer) 03838 { 03839 _dbus_assert (!loader->buffer_outstanding); 03840 03841 *buffer = &loader->data; 03842 03843 loader->buffer_outstanding = TRUE; 03844 } 03845 03856 void 03857 _dbus_message_loader_return_buffer (DBusMessageLoader *loader, 03858 DBusString *buffer, 03859 int bytes_read) 03860 { 03861 _dbus_assert (loader->buffer_outstanding); 03862 _dbus_assert (buffer == &loader->data); 03863 03864 loader->buffer_outstanding = FALSE; 03865 } 03866 03877 dbus_bool_t 03878 _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, 03879 int **fds, 03880 unsigned *max_n_fds) 03881 { 03882 #ifdef HAVE_UNIX_FD_PASSING 03883 _dbus_assert (!loader->unix_fds_outstanding); 03884 03885 /* Allocate space where we can put the fds we read. We allocate 03886 space for max_message_unix_fds since this is an 03887 upper limit how many fds can be received within a single 03888 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic 03889 we are allocating the maximum possible array size right from the 03890 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed 03891 there is no better way. */ 03892 03893 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds) 03894 { 03895 int *a = dbus_realloc(loader->unix_fds, 03896 loader->max_message_unix_fds * sizeof(loader->unix_fds[0])); 03897 03898 if (!a) 03899 return FALSE; 03900 03901 loader->unix_fds = a; 03902 loader->n_unix_fds_allocated = loader->max_message_unix_fds; 03903 } 03904 03905 *fds = loader->unix_fds + loader->n_unix_fds; 03906 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds; 03907 03908 loader->unix_fds_outstanding = TRUE; 03909 return TRUE; 03910 #else 03911 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03912 return FALSE; 03913 #endif 03914 } 03915 03926 void 03927 _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, 03928 int *fds, 03929 unsigned n_fds) 03930 { 03931 #ifdef HAVE_UNIX_FD_PASSING 03932 _dbus_assert(loader->unix_fds_outstanding); 03933 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds); 03934 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated); 03935 03936 loader->n_unix_fds += n_fds; 03937 loader->unix_fds_outstanding = FALSE; 03938 #else 03939 _dbus_assert_not_reached("Platform doesn't support unix fd passing"); 03940 #endif 03941 } 03942 03943 /* 03944 * FIXME when we move the header out of the buffer, that memmoves all 03945 * buffered messages. Kind of crappy. 03946 * 03947 * Also we copy the header and body, which is kind of crappy. To 03948 * avoid this, we have to allow header and body to be in a single 03949 * memory block, which is good for messages we read and bad for 03950 * messages we are creating. But we could move_len() the buffer into 03951 * this single memory block, and move_len() will just swap the buffers 03952 * if you're moving the entire buffer replacing the dest string. 03953 * 03954 * We could also have the message loader tell the transport how many 03955 * bytes to read; so it would first ask for some arbitrary number like 03956 * 256, then if the message was incomplete it would use the 03957 * header/body len to ask for exactly the size of the message (or 03958 * blocks the size of a typical kernel buffer for the socket). That 03959 * way we don't get trailing bytes in the buffer that have to be 03960 * memmoved. Though I suppose we also don't have a chance of reading a 03961 * bunch of small messages at once, so the optimization may be stupid. 03962 * 03963 * Another approach would be to keep a "start" index into 03964 * loader->data and only delete it occasionally, instead of after 03965 * each message is loaded. 03966 * 03967 * load_message() returns FALSE if not enough memory OR the loader was corrupted 03968 */ 03969 static dbus_bool_t 03970 load_message (DBusMessageLoader *loader, 03971 DBusMessage *message, 03972 int byte_order, 03973 int fields_array_len, 03974 int header_len, 03975 int body_len) 03976 { 03977 dbus_bool_t oom; 03978 DBusValidity validity; 03979 const DBusString *type_str; 03980 int type_pos; 03981 DBusValidationMode mode; 03982 dbus_uint32_t n_unix_fds = 0; 03983 03984 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED; 03985 03986 oom = FALSE; 03987 03988 #if 0 03989 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */); 03990 #endif 03991 03992 /* 1. VALIDATE AND COPY OVER HEADER */ 03993 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0); 03994 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data)); 03995 03996 if (!_dbus_header_load (&message->header, 03997 mode, 03998 &validity, 03999 byte_order, 04000 fields_array_len, 04001 header_len, 04002 body_len, 04003 &loader->data, 0, 04004 _dbus_string_get_length (&loader->data))) 04005 { 04006 _dbus_verbose ("Failed to load header for new message code %d\n", validity); 04007 04008 /* assert here so we can catch any code that still uses DBUS_VALID to indicate 04009 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */ 04010 _dbus_assert (validity != DBUS_VALID); 04011 04012 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR) 04013 oom = TRUE; 04014 else 04015 { 04016 loader->corrupted = TRUE; 04017 loader->corruption_reason = validity; 04018 } 04019 goto failed; 04020 } 04021 04022 _dbus_assert (validity == DBUS_VALID); 04023 04024 /* 2. VALIDATE BODY */ 04025 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 04026 { 04027 get_const_signature (&message->header, &type_str, &type_pos); 04028 04029 /* Because the bytes_remaining arg is NULL, this validates that the 04030 * body is the right length 04031 */ 04032 validity = _dbus_validate_body_with_reason (type_str, 04033 type_pos, 04034 byte_order, 04035 NULL, 04036 &loader->data, 04037 header_len, 04038 body_len); 04039 if (validity != DBUS_VALID) 04040 { 04041 _dbus_verbose ("Failed to validate message body code %d\n", validity); 04042 04043 loader->corrupted = TRUE; 04044 loader->corruption_reason = validity; 04045 04046 goto failed; 04047 } 04048 } 04049 04050 /* 3. COPY OVER UNIX FDS */ 04051 _dbus_header_get_field_basic(&message->header, 04052 DBUS_HEADER_FIELD_UNIX_FDS, 04053 DBUS_TYPE_UINT32, 04054 &n_unix_fds); 04055 04056 #ifdef HAVE_UNIX_FD_PASSING 04057 04058 if (n_unix_fds > loader->n_unix_fds) 04059 { 04060 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n", 04061 n_unix_fds, loader->n_unix_fds); 04062 04063 loader->corrupted = TRUE; 04064 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04065 goto failed; 04066 } 04067 04068 /* If this was a recycled message there might still be 04069 some memory allocated for the fds */ 04070 dbus_free(message->unix_fds); 04071 04072 if (n_unix_fds > 0) 04073 { 04074 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0])); 04075 if (message->unix_fds == NULL) 04076 { 04077 _dbus_verbose ("Failed to allocate file descriptor array\n"); 04078 oom = TRUE; 04079 goto failed; 04080 } 04081 04082 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; 04083 loader->n_unix_fds -= n_unix_fds; 04084 memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds); 04085 } 04086 else 04087 message->unix_fds = NULL; 04088 04089 #else 04090 04091 if (n_unix_fds > 0) 04092 { 04093 _dbus_verbose ("Hmm, message claims to come with file descriptors " 04094 "but that's not supported on our platform, disconnecting.\n"); 04095 04096 loader->corrupted = TRUE; 04097 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS; 04098 goto failed; 04099 } 04100 04101 #endif 04102 04103 /* 3. COPY OVER BODY AND QUEUE MESSAGE */ 04104 04105 if (!_dbus_list_append (&loader->messages, message)) 04106 { 04107 _dbus_verbose ("Failed to append new message to loader queue\n"); 04108 oom = TRUE; 04109 goto failed; 04110 } 04111 04112 _dbus_assert (_dbus_string_get_length (&message->body) == 0); 04113 _dbus_assert (_dbus_string_get_length (&loader->data) >= 04114 (header_len + body_len)); 04115 04116 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0)) 04117 { 04118 _dbus_verbose ("Failed to move body into new message\n"); 04119 oom = TRUE; 04120 goto failed; 04121 } 04122 04123 _dbus_string_delete (&loader->data, 0, header_len + body_len); 04124 04125 /* don't waste more than 2k of memory */ 04126 _dbus_string_compact (&loader->data, 2048); 04127 04128 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len); 04129 _dbus_assert (_dbus_string_get_length (&message->body) == body_len); 04130 04131 _dbus_verbose ("Loaded message %p\n", message); 04132 04133 _dbus_assert (!oom); 04134 _dbus_assert (!loader->corrupted); 04135 _dbus_assert (loader->messages != NULL); 04136 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04137 04138 return TRUE; 04139 04140 failed: 04141 04142 /* Clean up */ 04143 04144 /* does nothing if the message isn't in the list */ 04145 _dbus_list_remove_last (&loader->messages, message); 04146 04147 if (oom) 04148 _dbus_assert (!loader->corrupted); 04149 else 04150 _dbus_assert (loader->corrupted); 04151 04152 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data)); 04153 04154 return FALSE; 04155 } 04156 04171 dbus_bool_t 04172 _dbus_message_loader_queue_messages (DBusMessageLoader *loader) 04173 { 04174 while (!loader->corrupted && 04175 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE) 04176 { 04177 DBusValidity validity; 04178 int byte_order, fields_array_len, header_len, body_len; 04179 04180 if (_dbus_header_have_message_untrusted (loader->max_message_size, 04181 &validity, 04182 &byte_order, 04183 &fields_array_len, 04184 &header_len, 04185 &body_len, 04186 &loader->data, 0, 04187 _dbus_string_get_length (&loader->data))) 04188 { 04189 DBusMessage *message; 04190 04191 _dbus_assert (validity == DBUS_VALID); 04192 04193 message = dbus_message_new_empty_header (); 04194 if (message == NULL) 04195 return FALSE; 04196 04197 if (!load_message (loader, message, 04198 byte_order, fields_array_len, 04199 header_len, body_len)) 04200 { 04201 dbus_message_unref (message); 04202 /* load_message() returns false if corrupted or OOM; if 04203 * corrupted then return TRUE for not OOM 04204 */ 04205 return loader->corrupted; 04206 } 04207 04208 _dbus_assert (loader->messages != NULL); 04209 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL); 04210 } 04211 else 04212 { 04213 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n", 04214 validity); 04215 if (validity != DBUS_VALID) 04216 { 04217 loader->corrupted = TRUE; 04218 loader->corruption_reason = validity; 04219 } 04220 return TRUE; 04221 } 04222 } 04223 04224 return TRUE; 04225 } 04226 04234 DBusMessage* 04235 _dbus_message_loader_peek_message (DBusMessageLoader *loader) 04236 { 04237 if (loader->messages) 04238 return loader->messages->data; 04239 else 04240 return NULL; 04241 } 04242 04251 DBusMessage* 04252 _dbus_message_loader_pop_message (DBusMessageLoader *loader) 04253 { 04254 return _dbus_list_pop_first (&loader->messages); 04255 } 04256 04265 DBusList* 04266 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader) 04267 { 04268 return _dbus_list_pop_first_link (&loader->messages); 04269 } 04270 04277 void 04278 _dbus_message_loader_putback_message_link (DBusMessageLoader *loader, 04279 DBusList *link) 04280 { 04281 _dbus_list_prepend_link (&loader->messages, link); 04282 } 04283 04293 dbus_bool_t 04294 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader) 04295 { 04296 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04297 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04298 return loader->corrupted; 04299 } 04300 04307 DBusValidity 04308 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader) 04309 { 04310 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) || 04311 (!loader->corrupted && loader->corruption_reason == DBUS_VALID)); 04312 04313 return loader->corruption_reason; 04314 } 04315 04322 void 04323 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader, 04324 long size) 04325 { 04326 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH) 04327 { 04328 _dbus_verbose ("clamping requested max message size %ld to %d\n", 04329 size, DBUS_MAXIMUM_MESSAGE_LENGTH); 04330 size = DBUS_MAXIMUM_MESSAGE_LENGTH; 04331 } 04332 loader->max_message_size = size; 04333 } 04334 04341 long 04342 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader) 04343 { 04344 return loader->max_message_size; 04345 } 04346 04353 void 04354 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader, 04355 long n) 04356 { 04357 if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS) 04358 { 04359 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n", 04360 n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS); 04361 n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS; 04362 } 04363 loader->max_message_unix_fds = n; 04364 } 04365 04372 long 04373 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) 04374 { 04375 return loader->max_message_unix_fds; 04376 } 04377 04378 static DBusDataSlotAllocator slot_allocator; 04379 _DBUS_DEFINE_GLOBAL_LOCK (message_slots); 04380 04395 dbus_bool_t 04396 dbus_message_allocate_data_slot (dbus_int32_t *slot_p) 04397 { 04398 return _dbus_data_slot_allocator_alloc (&slot_allocator, 04399 &_DBUS_LOCK_NAME (message_slots), 04400 slot_p); 04401 } 04402 04414 void 04415 dbus_message_free_data_slot (dbus_int32_t *slot_p) 04416 { 04417 _dbus_return_if_fail (*slot_p >= 0); 04418 04419 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 04420 } 04421 04435 dbus_bool_t 04436 dbus_message_set_data (DBusMessage *message, 04437 dbus_int32_t slot, 04438 void *data, 04439 DBusFreeFunction free_data_func) 04440 { 04441 DBusFreeFunction old_free_func; 04442 void *old_data; 04443 dbus_bool_t retval; 04444 04445 _dbus_return_val_if_fail (message != NULL, FALSE); 04446 _dbus_return_val_if_fail (slot >= 0, FALSE); 04447 04448 retval = _dbus_data_slot_list_set (&slot_allocator, 04449 &message->slot_list, 04450 slot, data, free_data_func, 04451 &old_free_func, &old_data); 04452 04453 if (retval) 04454 { 04455 /* Do the actual free outside the message lock */ 04456 if (old_free_func) 04457 (* old_free_func) (old_data); 04458 } 04459 04460 return retval; 04461 } 04462 04471 void* 04472 dbus_message_get_data (DBusMessage *message, 04473 dbus_int32_t slot) 04474 { 04475 void *res; 04476 04477 _dbus_return_val_if_fail (message != NULL, NULL); 04478 04479 res = _dbus_data_slot_list_get (&slot_allocator, 04480 &message->slot_list, 04481 slot); 04482 04483 return res; 04484 } 04485 04499 int 04500 dbus_message_type_from_string (const char *type_str) 04501 { 04502 if (strcmp (type_str, "method_call") == 0) 04503 return DBUS_MESSAGE_TYPE_METHOD_CALL; 04504 if (strcmp (type_str, "method_return") == 0) 04505 return DBUS_MESSAGE_TYPE_METHOD_RETURN; 04506 else if (strcmp (type_str, "signal") == 0) 04507 return DBUS_MESSAGE_TYPE_SIGNAL; 04508 else if (strcmp (type_str, "error") == 0) 04509 return DBUS_MESSAGE_TYPE_ERROR; 04510 else 04511 return DBUS_MESSAGE_TYPE_INVALID; 04512 } 04513 04527 const char * 04528 dbus_message_type_to_string (int type) 04529 { 04530 switch (type) 04531 { 04532 case DBUS_MESSAGE_TYPE_METHOD_CALL: 04533 return "method_call"; 04534 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 04535 return "method_return"; 04536 case DBUS_MESSAGE_TYPE_SIGNAL: 04537 return "signal"; 04538 case DBUS_MESSAGE_TYPE_ERROR: 04539 return "error"; 04540 default: 04541 return "invalid"; 04542 } 04543 } 04544 04557 dbus_bool_t 04558 dbus_message_marshal (DBusMessage *msg, 04559 char **marshalled_data_p, 04560 int *len_p) 04561 { 04562 DBusString tmp; 04563 dbus_bool_t was_locked; 04564 04565 _dbus_return_val_if_fail (msg != NULL, FALSE); 04566 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE); 04567 _dbus_return_val_if_fail (len_p != NULL, FALSE); 04568 04569 if (!_dbus_string_init (&tmp)) 04570 return FALSE; 04571 04572 /* Ensure the message is locked, to ensure the length header is filled in. */ 04573 was_locked = msg->locked; 04574 04575 if (!was_locked) 04576 dbus_message_lock (msg); 04577 04578 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0)) 04579 goto fail; 04580 04581 *len_p = _dbus_string_get_length (&tmp); 04582 04583 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p)) 04584 goto fail; 04585 04586 *len_p = _dbus_string_get_length (&tmp); 04587 04588 if (!_dbus_string_steal_data (&tmp, marshalled_data_p)) 04589 goto fail; 04590 04591 _dbus_string_free (&tmp); 04592 04593 if (!was_locked) 04594 msg->locked = FALSE; 04595 04596 return TRUE; 04597 04598 fail: 04599 _dbus_string_free (&tmp); 04600 04601 if (!was_locked) 04602 msg->locked = FALSE; 04603 04604 return FALSE; 04605 } 04606 04619 DBusMessage * 04620 dbus_message_demarshal (const char *str, 04621 int len, 04622 DBusError *error) 04623 { 04624 DBusMessageLoader *loader; 04625 DBusString *buffer; 04626 DBusMessage *msg; 04627 04628 _dbus_return_val_if_fail (str != NULL, NULL); 04629 04630 loader = _dbus_message_loader_new (); 04631 04632 if (loader == NULL) 04633 return NULL; 04634 04635 _dbus_message_loader_get_buffer (loader, &buffer); 04636 _dbus_string_append_len (buffer, str, len); 04637 _dbus_message_loader_return_buffer (loader, buffer, len); 04638 04639 if (!_dbus_message_loader_queue_messages (loader)) 04640 goto fail_oom; 04641 04642 if (_dbus_message_loader_get_is_corrupted (loader)) 04643 goto fail_corrupt; 04644 04645 msg = _dbus_message_loader_pop_message (loader); 04646 04647 if (!msg) 04648 goto fail_oom; 04649 04650 _dbus_message_loader_unref (loader); 04651 return msg; 04652 04653 fail_corrupt: 04654 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)", 04655 _dbus_validity_to_error_message (loader->corruption_reason)); 04656 _dbus_message_loader_unref (loader); 04657 return NULL; 04658 04659 fail_oom: 04660 _DBUS_SET_OOM (error); 04661 _dbus_message_loader_unref (loader); 04662 return NULL; 04663 } 04664 04678 int 04679 dbus_message_demarshal_bytes_needed(const char *buf, 04680 int len) 04681 { 04682 DBusString str; 04683 int byte_order, fields_array_len, header_len, body_len; 04684 DBusValidity validity = DBUS_VALID; 04685 int have_message; 04686 04687 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE) 04688 return 0; 04689 04690 if (len > DBUS_MAXIMUM_MESSAGE_LENGTH) 04691 len = DBUS_MAXIMUM_MESSAGE_LENGTH; 04692 _dbus_string_init_const_len (&str, buf, len); 04693 04694 validity = DBUS_VALID; 04695 have_message 04696 = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH, 04697 &validity, &byte_order, 04698 &fields_array_len, 04699 &header_len, 04700 &body_len, 04701 &str, 0, 04702 len); 04703 _dbus_string_free (&str); 04704 04705 if (validity == DBUS_VALID) 04706 { 04707 _dbus_assert (have_message || (header_len + body_len) > len); 04708 (void) have_message; /* unused unless asserting */ 04709 return header_len + body_len; 04710 } 04711 else 04712 { 04713 return -1; /* broken! */ 04714 } 04715 } 04716 04719 /* tests in dbus-message-util.c */
1.7.5.1