diff options
| author | Havoc Pennington <hp@redhat.com> | 2006-10-21 17:08:08 +0000 | 
|---|---|---|
| committer | Havoc Pennington <hp@redhat.com> | 2006-10-21 17:08:08 +0000 | 
| commit | afa4ffbd852686633086569cd34942917c5c49af (patch) | |
| tree | 5b7919a3255aac947f1a4ef130bafadb508db3a9 | |
| parent | 65fcbd62876f435f08bbcb6ff4596545b8c87bbd (diff) | |
2006-10-21  Havoc Pennington  <hp@redhat.com>
	* dbus/dbus-message.h: put #ifndef DBUS_DISABLE_DEPRECATED around
	dbus_message_iter_get_array_len().
	* throughout: documentation improvements.
| -rw-r--r-- | ChangeLog | 7 | ||||
| -rw-r--r-- | dbus/dbus-bus.c | 217 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 9 | ||||
| -rw-r--r-- | dbus/dbus-errors.c | 36 | ||||
| -rw-r--r-- | dbus/dbus-marshal-recursive.c | 6 | ||||
| -rw-r--r-- | dbus/dbus-memory.c | 51 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 655 | ||||
| -rw-r--r-- | dbus/dbus-message.h | 5 | ||||
| -rw-r--r-- | dbus/dbus-timeout.c | 3 | ||||
| -rw-r--r-- | dbus/dbus-watch.c | 3 | ||||
| -rw-r--r-- | doc/dbus-specification.xml | 12 | 
11 files changed, 675 insertions, 329 deletions
@@ -1,3 +1,10 @@ +2006-10-21  Havoc Pennington  <hp@redhat.com> + +	* dbus/dbus-message.h: put #ifndef DBUS_DISABLE_DEPRECATED around  +	dbus_message_iter_get_array_len(). + +	* throughout: documentation improvements. +  2006-10-20  Havoc Pennington  <hp@redhat.com>  	* doc/TODO: remove the int64 thing from 1.0 since it doesn't diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index 1661f246..b2072b88 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -36,6 +36,21 @@   * @ingroup DBus   * @brief Functions for communicating with the message bus   * + * dbus_bus_get() allows all modules and libraries in a given + * process to share the same connection to the bus daemon by storing + * the connection globally. + * + * All other functions in this module are just convenience functions; + * most of them invoke methods on the bus daemon, by sending method + * call messages to #DBUS_SERVICE_DBUS. These convenience functions + * often make blocking method calls. If you don't want to block, + * you can send the method call messages manually in the same way + * you would any other method call message. + * + * This module is the only one in libdbus that's specific to + * communicating with the message bus daemon. The rest of the API can + * also be used for connecting to another application directly. + *    * @todo right now the default address of the system bus is hardcoded,   * so if you change it in the global config file suddenly you have to   * set DBUS_SYSTEM_BUS_ADDRESS env variable.  Might be nice if the @@ -472,6 +487,11 @@ internal_bus_get (DBusBusType  type,   * will exit if the connection closes. You can undo this   * by calling dbus_connection_set_exit_on_disconnect() yourself   * after you get the connection. + * + * dbus_bus_get() calls dbus_bus_register() for you. + *  + * If returning a newly-created connection, this function will block + * until authentication and bus registration are complete.   *    * @param type bus type   * @param error address where an error can be returned. @@ -485,11 +505,11 @@ dbus_bus_get (DBusBusType  type,  }  /** - * Connects to a bus daemon and registers the client with it as with dbus_bus_register(). - * Unlike dbus_bus_get(), always creates a new connection. This connection - * will not be saved or recycled by libdbus. Caller owns a reference - * to the bus and must either close it or know it to be closed - * prior to releasing this reference. + * Connects to a bus daemon and registers the client with it as with + * dbus_bus_register().  Unlike dbus_bus_get(), always creates a new + * connection. This connection will not be saved or recycled by + * libdbus. Caller owns a reference to the bus and must either close + * it or know it to be closed prior to releasing this reference.   *   * See dbus_connection_open_private() for more details on when to   * close and unref this connection. @@ -500,6 +520,11 @@ dbus_bus_get (DBusBusType  type,   * by calling dbus_connection_set_exit_on_disconnect() yourself   * after you get the connection.   * + * dbus_bus_get_private() calls dbus_bus_register() for you. + * + * This function will block until authentication and bus registration + * are complete. + *   * @param type bus type   * @param error address where an error can be returned.   * @returns a DBusConnection with new ref @@ -519,6 +544,13 @@ dbus_bus_get_private (DBusBusType  type,   *   * If you use dbus_bus_get() or dbus_bus_get_private() this   * function will be called for you. + * + * If you open a bus connection with dbus_connection_open() or + * dbus_connection_open_private() you will have to dbus_bus_register() + * yourself, or make the appropriate registration method calls + * yourself. + * + * This function will block until registration is complete.   *    * @param connection the connection   * @param error place to store errors @@ -598,9 +630,11 @@ dbus_bus_register (DBusConnection *connection,  /** - * Sets the unique name of the connection.  Can only be used if you - * registered with the bus manually (i.e. if you did not call - * dbus_bus_register()). Can only be called once per connection. + * Sets the unique name of the connection, as assigned by the message + * bus.  Can only be used if you registered with the bus manually + * (i.e. if you did not call dbus_bus_register()). Can only be called + * once per connection.  After the unique name is set, you can get it + * with dbus_bus_get_unique_name().   *   * @param connection the connection   * @param unique_name the unique name @@ -626,11 +660,17 @@ dbus_bus_set_unique_name (DBusConnection *connection,  }  /** - * Gets the unique name of the connection.  Only possible after the - * connection has been registered with the message bus. + * Gets the unique name of the connection as assigned by the message + * bus. Only possible after the connection has been registered with + * the message bus.   * - * The name remains valid for the duration of the connection and + * The name remains valid until the connection is freed, and   * should not be freed by the caller. + * + * There are two ways to set the unique name; one is + * dbus_bus_register(), the other is dbus_bus_set_unique_name(). + * You are responsible for calling dbus_bus_set_unique_name() + * if you register by hand instead of using dbus_bus_register().   *    * @param connection the connection   * @returns the unique name or NULL on error @@ -650,16 +690,22 @@ dbus_bus_get_unique_name (DBusConnection *connection)  }  /** - * Asks the bus to return the uid of the named - * connection. + * Asks the bus to return the uid of the named connection. + * Only works on UNIX; only works for connections on the same + * machine as the bus. If you are not on the same machine + * as the bus, then calling this is probably a bad idea, + * since the uid will mean little to your application.   * - * Not going to work on Windows, the bus should return - * an error then. + * For the system message bus you're guaranteed to be on the same + * machine since it only listens on a UNIX domain socket (at least, + * as shipped by default). + * + * This function will just return an error on Windows.   *    * @param connection the connection   * @param name a name owned by the connection   * @param error location to store the error - * @returns a result code, -1 if error is set + * @returns the unix user id, or ((unsigned)-1) if error is set   */   unsigned long  dbus_bus_get_unix_user (DBusConnection *connection, @@ -734,17 +780,46 @@ dbus_bus_get_unix_user (DBusConnection *connection,   * result codes are discussed here, but the specification is the   * canonical version of this information.   * - * The #DBUS_NAME_FLAG_ALLOW_REPLACEMENT flag indicates that the caller - * will allow other services to take over the name from the current owner. + * First you should know that for each bus name, the bus stores + * a queue of connections that would like to own it. Only + * one owns it at a time - called the primary owner. If the primary + * owner releases the name or disconnects, then the next owner in the + * queue atomically takes over. + * + * So for example if you have an application org.freedesktop.TextEditor + * and multiple instances of it can be run, you can have all of them + * sitting in the queue. The first one to start up will receive messages + * sent to org.freedesktop.TextEditor, but if that one exits another + * will become the primary owner and receive messages. + * + * The queue means you don't need to manually watch for the current owner to + * disappear and then request the name again. + * + * When requesting a name, you can specify several flags. + *  + * #DBUS_NAME_FLAG_ALLOW_REPLACEMENT and #DBUS_NAME_FLAG_DO_NOT_QUEUE + * are properties stored by the bus for this connection with respect to + * each requested bus name. These properties are stored even if the + * connection is queued and does not become the primary owner. + * You can update these flags by calling RequestName again (even if + * you already own the name). + * + * #DBUS_NAME_FLAG_ALLOW_REPLACEMENT means that another requestor of the + * name can take it away from you by specifying #DBUS_NAME_FLAG_REPLACE_EXISTING. + * + * #DBUS_NAME_FLAG_DO_NOT_QUEUE means that if you aren't the primary owner, + * you don't want to be queued up - you only care about being the + * primary owner.   * - * The #DBUS_NAME_FLAG_REPLACE_EXISTING flag indicates that the caller - * would like to take over the name from the current owner. - * If the current name owner did not use #DBUS_NAME_FLAG_ALLOW_REPLACEMENT - * then this flag indicates that the caller would like to be placed - * in the queue to own the name when the current owner lets go. + * Unlike the other two flags, #DBUS_NAME_FLAG_REPLACE_EXISTING is a property + * of the individual RequestName call, i.e. the bus does not persistently + * associate it with the connection-name pair. If a RequestName call includes + * the #DBUS_NAME_FLAG_REPLACE_EXISTING flag, and the current primary + * owner has #DBUS_NAME_FLAG_ALLOW_REPLACEMENT set, then the current primary + * owner will be kicked off.   *   * If no flags are given, an application will receive the requested - * name only if the name is currently unowned; it will NOT give + * name only if the name is currently unowned; and it will NOT give   * up the name if another application asks to take it over using   * #DBUS_NAME_FLAG_REPLACE_EXISTING.   * @@ -770,7 +845,9 @@ dbus_bus_get_unix_user (DBusConnection *connection,   * #DBUS_NAME_FLAG_REPLACE_EXISTING.   *   * #DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER happens if an application - * requests a name it already owns. + * requests a name it already owns. (Re-requesting a name is useful if + * you want to change the #DBUS_NAME_FLAG_ALLOW_REPLACEMENT or + * #DBUS_NAME_FLAG_DO_NOT_QUEUE settings.)   *   * When a service represents an application, say "text editor," then   * it should specify #DBUS_NAME_FLAG_ALLOW_REPLACEMENT if it wants @@ -779,7 +856,19 @@ dbus_bus_get_unix_user (DBusConnection *connection,   * specify #DBUS_NAME_FLAG_REPLACE_EXISTING to either take over   * (last-started-wins) or be queued up (first-started-wins) according   * to whether #DBUS_NAME_FLAG_ALLOW_REPLACEMENT was given. - *  + * + * Conventionally, single-instance applications often offer a command + * line option called --replace which means to replace the current + * instance.  To implement this, always set + * #DBUS_NAME_FLAG_ALLOW_REPLACEMENT when you request your + * application's bus name.  When you lose ownership of your bus name, + * you need to exit.  Look for the signal "NameLost" from + * #DBUS_SERVICE_DBUS and #DBUS_INTERFACE_DBUS (the signal's first + * argument is the bus name that was lost).  If starting up without + * --replace, do not specify #DBUS_NAME_FLAG_REPLACE_EXISTING, and + * exit if you fail to become the bus name owner. If --replace is + * given, ask to replace the old owner. + *   * @param connection the connection   * @param name the name to request   * @param flags flags @@ -855,10 +944,18 @@ dbus_bus_request_name (DBusConnection *connection,  /** - * Asks the bus to unassign the given name to this connection by invoking - * the ReleaseName method on the bus. This method is fully documented - * in the D-Bus specification. + * Asks the bus to unassign the given name from this connection by + * invoking the ReleaseName method on the bus. The "ReleaseName" + * method is canonically documented in the D-Bus specification.   * + * Possible results are: #DBUS_RELEASE_NAME_REPLY_RELEASED + * which means you owned the name or were in the queue to own it, + * and and now you don't own it and aren't in the queue. + * #DBUS_RELEASE_NAME_REPLY_NOT_OWNER which means someone else + * owns the name so you can't release it. + * #DBUS_RELEASE_NAME_REPLY_NON_EXISTENT + * which means nobody owned the name. + *    * @param connection the connection   * @param name the name to remove    * @param error location to store the error @@ -930,8 +1027,17 @@ dbus_bus_release_name (DBusConnection *connection,  }  /** - * Checks whether a certain name has an owner. + * Asks the bus whether a certain name has an owner.   * + * Using this can easily result in a race condition, + * since an owner can appear or disappear after you + * call this. + * + * If you want to request a name, just request it; + * if you want to avoid replacing a current owner, + * don't specify #DBUS_NAME_FLAG_REPLACE_EXISTING and + * you will get an error if there's already an owner. + *    * @param connection the connection   * @param name the name   * @param error location to store any errors @@ -1000,6 +1106,12 @@ dbus_bus_name_has_owner (DBusConnection *connection,   * The flags parameter is for future expansion, currently you should   * specify 0.   * + * It's often easier to avoid explicitly starting services, and + * just send a method call to the service's bus name instead. + * Method calls start a service to handle them by default + * unless you call dbus_message_set_auto_start() to disable this + * behavior. + *    * @param connection the connection   * @param name the name we want the new service to request   * @param flags the flags (should always be 0 for now) @@ -1119,11 +1231,13 @@ send_no_return_values (DBusConnection *connection,   * path='/bar/foo',destination=':452345.34'"   *   * Possible keys you can match on are type, sender,  - * interface, member, path, destination and the special - * arg keys.  Excluding a key from the rule indicates  - * a wildcard match.  For instance excluding the + * interface, member, path, destination and numbered + * keys to match message args (keys are 'arg0', 'arg1', etc.). + * Omitting a key from the rule indicates  + * a wildcard match.  For instance omitting   * the member from a match rule but adding a sender would - * let all messages from that sender through.   + * let all messages from that sender through regardless of + * the member.   *   * Matches are inclusive not exclusive so as long as one    * rule matches the message will get through.  It is important @@ -1132,12 +1246,31 @@ send_no_return_values (DBusConnection *connection,   * can cause performance problems such as draining batteries   * on embedded platforms.   * - * The special arg keys are used for further restricting the  - * match based on the parameters sent by the signal or method. - * For instance arg1='foo' will check the first argument,  - * arg2='bar' the second and so on.  For performance reasons - * there is a set limit on the highest number parameter that - * can be checked which is set in dbus-protocol.h + * If you match message args ('arg0', 'arg1', and so forth) + * only string arguments will match. That is, arg0='5' means + * match the string "5" not the integer 5. + * + * Currently there is no way to match against non-string arguments. + * + * Matching on interface is tricky because method call + * messages only optionally specify the interface. + * If a message omits the interface, then it will NOT match + * if the rule specifies an interface name. This means match + * rules on method calls should not usually give an interface. + * + * However, signal messages are required to include the interface + * so when matching signals usually you should specify the interface + * in the match rule. + *  + * For security reasons, you can match arguments only up to + * #DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER. + * + * Match rules have a maximum length of #DBUS_MAXIMUM_MATCH_RULE_LENGTH + * bytes. + * + * Both of these maximums are much higher than you're likely to need, + * they only exist because the D-Bus bus daemon has fixed limits on + * all resource usage.   *   * @param connection connection to the message bus   * @param rule textual form of match rule @@ -1181,6 +1314,10 @@ dbus_bus_add_match (DBusConnection *connection,   * recently-added identical rule gets removed).  The "rule" argument   * is the string form of a match rule.   * + * The bus compares match rules semantically, not textually, so + * whitespace and ordering don't have to be identical to + * the rule you passed to dbus_bus_add_match(). + *    * If you pass #NULL for the error, this function will not   * block; otherwise it will. See detailed explanation in   * docs for dbus_bus_add_match(). diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 69afd100..81c7cadf 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2940,16 +2940,19 @@ _dbus_connection_send_unlocked_no_update (DBusConnection *connection,   * The function will never fail for other reasons; even if the   * connection is disconnected, you can queue an outgoing message,   * though obviously it won't be sent. + * + * The message serial is used by the remote application to send a + * reply; see dbus_message_get_serial() or the D-Bus specification.   *    * @param connection the connection.   * @param message the message to write. - * @param client_serial return location for client serial. + * @param serial return location for message serial, or #NULL if you don't care   * @returns #TRUE on success.   */  dbus_bool_t  dbus_connection_send (DBusConnection *connection,                        DBusMessage    *message, -                      dbus_uint32_t  *client_serial) +                      dbus_uint32_t  *serial)  {    _dbus_return_val_if_fail (connection != NULL, FALSE);    _dbus_return_val_if_fail (message != NULL, FALSE); @@ -2958,7 +2961,7 @@ dbus_connection_send (DBusConnection *connection,    return _dbus_connection_send_and_unlock (connection,  					   message, -					   client_serial); +					   serial);  }  static dbus_bool_t diff --git a/dbus/dbus-errors.c b/dbus/dbus-errors.c index fb230852..a20610a6 100644 --- a/dbus/dbus-errors.c +++ b/dbus/dbus-errors.c @@ -124,6 +124,9 @@ message_from_error (const char *error)   *   }   * @endcode   * + * By convention, all functions allow #NULL instead of a DBusError*, + * so callers who don't care about the error can ignore it. + *    * There are some rules. An error passed to a D-Bus function must   * always be unset; you can't pass in an error that's already set.  If   * a function has a return code indicating whether an error occurred, @@ -137,13 +140,19 @@ message_from_error (const char *error)   * You can check the specific error that occurred using   * dbus_error_has_name().   *  + * Errors will not be set for programming errors, such as passing + * invalid arguments to the libdbus API. Instead, libdbus will print + * warnings, exit on a failed assertion, or even crash in those cases + * (in other words, incorrect use of the API results in undefined + * behavior, possibly accompanied by helpful debugging output if + * you're lucky). + *    * @{   */  /** - * Initializes a DBusError structure. Does not allocate - * any memory; the error only needs to be freed - * if it is set at some point.  + * Initializes a DBusError structure. Does not allocate any memory; + * the error only needs to be freed if it is set at some point.   *   * @param error the DBusError.   */ @@ -190,11 +199,15 @@ dbus_error_free (DBusError *error)  /**   * Assigns an error name and message to a DBusError.  Does nothing if - * error is #NULL. The message may be NULL, which means a default - * message will be deduced from the name. If the error name is unknown - * to D-Bus the default message will be totally useless, though. + * error is #NULL. The message may be #NULL, which means a default + * message will be deduced from the name. The default message will be + * totally useless, though, so using a #NULL message is not recommended.   * - * @param error the error. + * Because this function does not copy the error name or message, you + * must ensure the name and message are global data that won't be + * freed. You probably want dbus_set_error() instead, in most cases. + *  + * @param error the error.or #NULL   * @param name the error name (not copied!!!)   * @param message the error message (not copied!!!)   */ @@ -297,14 +310,15 @@ dbus_error_is_set (const DBusError *error)   * Assigns an error name and message to a DBusError.   * Does nothing if error is #NULL.   * - * The format may be NULL, which means a default message will be - * deduced from the name. If the error name is unknown to D-Bus the - * default message will be totally useless, though. + * The format may be #NULL, which means a (pretty much useless) + * default message will be deduced from the name. This is not a good + * idea, just go ahead and provide a useful error message. It won't + * hurt you.   *   * If no memory can be allocated for the error message,    * an out-of-memory error message will be set instead.   * - * @param error the error. + * @param error the error.or #NULL   * @param name the error name   * @param format printf-style format string.   */ diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c index 501e9a53..bcea4c36 100644 --- a/dbus/dbus-marshal-recursive.c +++ b/dbus/dbus-marshal-recursive.c @@ -560,7 +560,7 @@ array_reader_next (DBusTypeReader *reader,    _dbus_assert (reader->value_pos >= reader->u.array.start_pos);    switch (_dbus_first_type_in_signature (reader->type_str, -                                   reader->type_pos)) +                                         reader->type_pos))      {      case DBUS_TYPE_DICT_ENTRY:      case DBUS_TYPE_STRUCT: @@ -875,10 +875,10 @@ _dbus_type_reader_read_basic (const DBusTypeReader    *reader,  }  /** - * Returns the number of values remaining in the current array reader. + * Returns the number of bytes in the array.   *   * @param reader the reader to read from - * @returns the number of elements remaining in the array + * @returns the number of bytes in the array   */  int  _dbus_type_reader_get_array_length (const DBusTypeReader  *reader) diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c index fbc02c1e..f2400af7 100644 --- a/dbus/dbus-memory.c +++ b/dbus/dbus-memory.c @@ -430,6 +430,9 @@ set_guards (void       *real_block,   * on all platforms. Returns #NULL if the allocation fails.   * The memory must be released with dbus_free().   * + * dbus_malloc() memory is NOT safe to free with regular free() from + * the C library. Free it with dbus_free() only. + *   * @param bytes number of bytes to allocate   * @return allocated memory, or #NULL if the allocation fails.   */ @@ -481,6 +484,9 @@ dbus_malloc (size_t bytes)   * return #NULL if bytes is zero on all platforms. Returns #NULL if the   * allocation fails.  The memory must be released with dbus_free().   * + * dbus_malloc0() memory is NOT safe to free with regular free() from + * the C library. Free it with dbus_free() only. + *   * @param bytes number of bytes to allocate   * @return allocated memory, or #NULL if the allocation fails.   */ @@ -741,16 +747,41 @@ _dbus_register_shutdown_func (DBusShutdownFunction  func,   */  /** - * The D-Bus library keeps some internal global variables, for example - * to cache the username of the current process.  This function is - * used to free these global variables.  It is really useful only for - * leak-checking cleanliness and the like. WARNING: this function is - * NOT thread safe, it must be called while NO other threads are using - * D-Bus. You cannot continue using D-Bus after calling this function, - * as it does things like free global mutexes created by - * dbus_threads_init(). To use a D-Bus function after calling - * dbus_shutdown(), you have to start over from scratch, e.g. calling - * dbus_threads_init() again. + * Frees all memory allocated internally by libdbus and + * reverses the effects of dbus_threads_init(). libdbus keeps internal + * global variables, for example caches and thread locks, and it + * can be useful to free these internal data structures. + * + * dbus_shutdown() does NOT free memory that was returned + * to the application. It only returns libdbus-internal + * data structures. + * + * You MUST free all memory and release all reference counts + * returned to you by libdbus prior to calling dbus_shutdown(). + * + * You can't continue to use any D-Bus objects, such as connections, + * that were allocated prior to dbus_shutdown(). You can, however, + * start over; call dbus_threads_init() again, create new connections, + * and so forth. + * + * WARNING: dbus_shutdown() is NOT thread safe, it must be called + * while NO other threads are using D-Bus. (Remember, you have to free + * all D-Bus objects and memory before you call dbus_shutdown(), so no + * thread can be using libdbus.) + * + * The purpose of dbus_shutdown() is to allow applications to get + * clean output from memory leak checkers. dbus_shutdown() may also be + * useful if you want to dlopen() libdbus instead of linking to it, + * and want to be able to unload the library again. + * + * There is absolutely no requirement to call dbus_shutdown() - in fact, + * most applications won't bother and should not feel guilty. + *  + * You have to know that nobody is using libdbus in your application's + * process before you can call dbus_shutdown(). One implication of this + * is that calling dbus_shutdown() from a library is almost certainly + * wrong, since you don't know what the rest of the app is up to. + *    */  void  dbus_shutdown (void) diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index aa6f65bd..7e53ce12 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -579,18 +579,229 @@ dbus_message_cache_or_finalize (DBusMessage *message)      dbus_message_finalize (message);  } +/** + * Implementation of the varargs arg-getting functions. + * dbus_message_get_args() is the place to go for complete + * documentation. + * + * @see dbus_message_get_args + * @param iter the message iter + * @param error error to be filled in + * @param first_arg_type type of the first argument + * @param var_args return location for first argument, followed by list of type/location pairs + * @returns #FALSE if error was set + */ +dbus_bool_t +_dbus_message_iter_get_args_valist (DBusMessageIter *iter, +                                    DBusError       *error, +                                    int              first_arg_type, +                                    va_list          var_args) +{ +  DBusMessageRealIter *real = (DBusMessageRealIter *)iter; +  int spec_type, msg_type, i; +  dbus_bool_t retval; + +  _dbus_assert (_dbus_message_iter_check (real)); + +  retval = FALSE; + +  spec_type = first_arg_type; +  i = 0; + +  while (spec_type != DBUS_TYPE_INVALID) +    { +      msg_type = dbus_message_iter_get_arg_type (iter); + +      if (msg_type != spec_type) +	{ +          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, +                          "Argument %d is specified to be of type \"%s\", but " +                          "is actually of type \"%s\"\n", i, +                          _dbus_type_to_string (spec_type), +                          _dbus_type_to_string (msg_type)); + +          goto out; +	} + +      if (dbus_type_is_basic (spec_type)) +        { +          DBusBasicValue *ptr; + +          ptr = va_arg (var_args, DBusBasicValue*); + +          _dbus_assert (ptr != NULL); + +          _dbus_type_reader_read_basic (&real->u.reader, +                                        ptr); +        } +      else if (spec_type == DBUS_TYPE_ARRAY) +        { +          int element_type; +          int spec_element_type; +          const DBusBasicValue **ptr; +          int *n_elements_p; +          DBusTypeReader array; + +          spec_element_type = va_arg (var_args, int); +          element_type = _dbus_type_reader_get_element_type (&real->u.reader); + +          if (spec_element_type != element_type) +            { +              dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, +                              "Argument %d is specified to be an array of \"%s\", but " +                              "is actually an array of \"%s\"\n", +                              i, +                              _dbus_type_to_string (spec_element_type), +                              _dbus_type_to_string (element_type)); + +              goto out; +            } + +          if (dbus_type_is_fixed (spec_element_type)) +            { +              ptr = va_arg (var_args, const DBusBasicValue**); +              n_elements_p = va_arg (var_args, int*); + +              _dbus_assert (ptr != NULL); +              _dbus_assert (n_elements_p != NULL); + +              _dbus_type_reader_recurse (&real->u.reader, &array); + +              _dbus_type_reader_read_fixed_multi (&array, +                                                  ptr, n_elements_p); +            } +          else if (spec_element_type == DBUS_TYPE_STRING || +                   spec_element_type == DBUS_TYPE_SIGNATURE || +                   spec_element_type == DBUS_TYPE_OBJECT_PATH) +            { +              char ***str_array_p; +              int n_elements; +              char **str_array; + +              str_array_p = va_arg (var_args, char***); +              n_elements_p = va_arg (var_args, int*); + +              _dbus_assert (str_array_p != NULL); +              _dbus_assert (n_elements_p != NULL); + +              /* Count elements in the array */ +              _dbus_type_reader_recurse (&real->u.reader, &array); + +              n_elements = 0; +              while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) +                { +                  ++n_elements; +                  _dbus_type_reader_next (&array); +                } + +              str_array = dbus_new0 (char*, n_elements + 1); +              if (str_array == NULL) +                { +                  _DBUS_SET_OOM (error); +                  goto out; +                } + +              /* Now go through and dup each string */ +              _dbus_type_reader_recurse (&real->u.reader, &array); + +              i = 0; +              while (i < n_elements) +                { +                  const char *s; +                  _dbus_type_reader_read_basic (&array, +                                                &s); +                   +                  str_array[i] = _dbus_strdup (s); +                  if (str_array[i] == NULL) +                    { +                      dbus_free_string_array (str_array); +                      _DBUS_SET_OOM (error); +                      goto out; +                    } +                   +                  ++i; +                   +                  if (!_dbus_type_reader_next (&array)) +                    _dbus_assert (i == n_elements); +                } + +              _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); +              _dbus_assert (i == n_elements); +              _dbus_assert (str_array[i] == NULL); + +              *str_array_p = str_array; +              *n_elements_p = n_elements; +            } +#ifndef DBUS_DISABLE_CHECKS +          else +            { +              _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", +                          _DBUS_FUNCTION_NAME); +              goto out; +            } +#endif +        } +#ifndef DBUS_DISABLE_CHECKS +      else +        { +          _dbus_warn ("you can only read arrays and basic types with %s for now\n", +                      _DBUS_FUNCTION_NAME); +          goto out; +        } +#endif + +      spec_type = va_arg (var_args, int); +      if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) +        { +          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, +                          "Message has only %d arguments, but more were expected", i); +          goto out; +        } + +      i++; +    } + +  retval = TRUE; + + out: + +  return retval; +} +  /** @} */  /**   * @defgroup DBusMessage DBusMessage   * @ingroup  DBus - * @brief Message to be sent or received over a DBusConnection. + * @brief Message to be sent or received over a #DBusConnection.   *   * A DBusMessage is the most basic unit of communication over a   * DBusConnection. A DBusConnection represents a stream of messages   * received from a remote application, and a stream of messages   * sent to a remote application.   * + * A message has a message type, returned from + * dbus_message_get_type().  This indicates whether the message is a + * method call, a reply to a method call, a signal, or an error reply. + * + * A message has header fields such as the sender, destination, method + * or signal name, and so forth. DBusMessage has accessor functions for + * these, such as dbus_message_get_member(). + * + * Convenience functions dbus_message_is_method_call(), dbus_message_is_signal(), + * and dbus_message_is_error() check several header fields at once and are + * slightly more efficient than checking the header fields with individual + * accessor functions. + * + * Finally, a message has arguments. The number and types of arguments + * are in the message's signature header field (accessed with + * dbus_message_get_signature()).  Simple argument values are usually + * retrieved with dbus_message_get_args() but more complex values such + * as structs may require the use of #DBusMessageIter. + * + * The D-Bus specification goes into some more detail about header fields and + * message types. + *    * @{   */ @@ -604,12 +815,16 @@ dbus_message_cache_or_finalize (DBusMessage *message)  /**   * Returns the serial of a message or 0 if none has been specified.   * The message's serial number is provided by the application sending - * the message and is used to identify replies to this message.  All - * messages received on a connection will have a serial, but messages - * you haven't sent yet may return 0. + * the message and is used to identify replies to this message. + * + * All messages received on a connection will have a serial provided + * by the remote application. + * + * For messages you're sending, dbus_connection_send() will assign a + * serial and return it to you.   *   * @param message the message - * @returns the client serial + * @returns the serial   */  dbus_uint32_t  dbus_message_get_serial (DBusMessage *message) @@ -620,11 +835,11 @@ dbus_message_get_serial (DBusMessage *message)  }  /** - * Sets the reply serial of a message (the client serial - * of the message this is a reply to). + * Sets the reply serial of a message (the serial of the message this + * is a reply to).   *   * @param message the message - * @param reply_serial the client serial + * @param reply_serial the serial we're replying to   * @returns #FALSE if not enough memory   */  dbus_bool_t @@ -748,8 +963,12 @@ dbus_message_new_empty_header (void)   * Types include #DBUS_MESSAGE_TYPE_METHOD_CALL,   * #DBUS_MESSAGE_TYPE_SIGNAL, and so forth.   * + * Usually you want to use dbus_message_new_method_call(), + * dbus_message_new_method_return(), dbus_message_new_signal(), + * or dbus_message_new_error() instead. + *    * @param message_type type of message - * @returns new message or #NULL If no memory + * @returns new message or #NULL if no memory   */  DBusMessage*  dbus_message_new (int message_type) @@ -781,14 +1000,18 @@ dbus_message_new (int message_type)   * context (no message bus). The interface may be #NULL, which means   * that if multiple methods with the given name exist it is undefined   * which one will be invoked. -  * + * + * The path and method names may not be #NULL. + * + * Destination, path, interface, and method name can't contain + * any invalid characters (see the D-Bus specification). + *    * @param destination name that the message should be sent to or #NULL   * @param path object path the message should be sent to - * @param interface interface to invoke method on + * @param interface interface to invoke method on, or #NULL   * @param method method to invoke   *   * @returns a new DBusMessage, free with dbus_message_unref() - * @see dbus_message_unref()   */  DBusMessage*  dbus_message_new_method_call (const char *destination, @@ -826,10 +1049,8 @@ dbus_message_new_method_call (const char *destination,   * Constructs a message that is a reply to a method call. Returns   * #NULL if memory can't be allocated for the message.   * - * @param method_call the message which the created - * message is a reply to. + * @param method_call the message being replied to   * @returns a new DBusMessage, free with dbus_message_unref() - * @see dbus_message_new_method_call(), dbus_message_unref()   */  DBusMessage*  dbus_message_new_method_return (DBusMessage *method_call) @@ -870,14 +1091,16 @@ dbus_message_new_method_return (DBusMessage *method_call)  /**   * Constructs a new message representing a signal emission. Returns   * #NULL if memory can't be allocated for the message.  A signal is - * identified by its originating interface, and the name of the - * signal. + * identified by its originating object path, interface, and the name + * of the signal.   * + * Path, interface, and signal name must all be valid (the D-Bus + * specification defines the syntax of these fields). + *    * @param path the path to the object emitting the signal   * @param interface the interface the signal is emitted from   * @param name name of the signal   * @returns a new DBusMessage, free with dbus_message_unref() - * @see dbus_message_unref()   */  DBusMessage*  dbus_message_new_signal (const char *path, @@ -911,13 +1134,18 @@ dbus_message_new_signal (const char *path,  }  /** - * Creates a new message that is an error reply to a certain message. - * Error replies are possible in response to method calls primarily. + * Creates a new message that is an error reply to another message. + * Error replies are most common in response to method calls, but + * can be returned in reply to any message.   * - * @param reply_to the original message + * The error name must be a valid error name according to the syntax + * given in the D-Bus specification. If you don't want to make + * up an error name just use #DBUS_ERROR_FAILED. + * + * @param reply_to the message we're replying to   * @param error_name the error name - * @param error_message the error message string or #NULL for none - * @returns a new error message + * @param error_message the error message string (or #NULL for none, but please give a message) + * @returns a new error message object, free with dbus_message_unref()   */  DBusMessage*  dbus_message_new_error (DBusMessage *reply_to, @@ -975,8 +1203,11 @@ dbus_message_new_error (DBusMessage *reply_to,  }  /** - * Creates a new message that is an error reply to a certain message. - * Error replies are possible in response to method calls primarily. + * Creates a new message that is an error reply to another message, allowing + * you to use printf formatting. + * + * See dbus_message_new_error() for details - this function is the same + * aside from the printf formatting.   *   * @param reply_to the original message   * @param error_name the error name @@ -1024,8 +1255,8 @@ dbus_message_new_error_printf (DBusMessage *reply_to,   * outgoing message queue and thus not modifiable) the new message   * will not be locked.   * - * @param message the message. - * @returns the new message. + * @param message the message + * @returns the new message.or #NULL if not enough memory   */  DBusMessage *  dbus_message_copy (const DBusMessage *message) @@ -1077,7 +1308,7 @@ dbus_message_copy (const DBusMessage *message)  /**   * Increments the reference count of a DBusMessage.   * - * @param message The message + * @param message the message   * @returns the message   * @see dbus_message_unref   */ @@ -1097,9 +1328,10 @@ dbus_message_ref (DBusMessage *message)  }  /** - * Decrements the reference count of a DBusMessage. + * Decrements the reference count of a DBusMessage, freeing the + * message if the count reaches 0.   * - * @param message The message + * @param message the message   * @see dbus_message_ref   */  void @@ -1127,8 +1359,7 @@ dbus_message_unref (DBusMessage *message)   * #DBUS_MESSAGE_TYPE_METHOD_CALL, #DBUS_MESSAGE_TYPE_METHOD_RETURN,   * #DBUS_MESSAGE_TYPE_ERROR, #DBUS_MESSAGE_TYPE_SIGNAL, but other   * types are allowed and all code must silently ignore messages of - * unknown type. #DBUS_MESSAGE_TYPE_INVALID will never be returned, - * however. + * unknown type. #DBUS_MESSAGE_TYPE_INVALID will never be returned.   *   * @param message the message   * @returns the type of the message @@ -1156,8 +1387,10 @@ dbus_message_get_type (DBusMessage *message)   *   * dbus_int32_t v_INT32 = 42;   * const char *v_STRING = "Hello World"; - * DBUS_TYPE_INT32, &v_INT32, - * DBUS_TYPE_STRING, &v_STRING, + * dbus_message_append_args (message, + *                           DBUS_TYPE_INT32, &v_INT32, + *                           DBUS_TYPE_STRING, &v_STRING, + *                           DBUS_TYPE_INVALID);   * @endcode   *   * To append an array of fixed-length basic types, pass in the @@ -1167,7 +1400,9 @@ dbus_message_get_type (DBusMessage *message)   * @code   * const dbus_int32_t array[] = { 1, 2, 3 };   * const dbus_int32_t *v_ARRAY = array; - * DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3 + * dbus_message_append_args (message, + *                           DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3, + *                           DBUS_TYPE_INVALID);   * @endcode   *   * @warning in C, given "int array[]", "&array == array" (the @@ -1178,7 +1413,8 @@ dbus_message_get_type (DBusMessage *message)   * const char *array = "Hello" and then use &array though.   *   * The last argument to this function must be #DBUS_TYPE_INVALID, - * marking the end of the argument list. + * marking the end of the argument list. If you don't do this + * then libdbus won't know to stop and will read invalid memory.   *   * String/signature/path arrays should be passed in as "const char***   * address_of_array" and "int n_elements" @@ -1213,8 +1449,7 @@ dbus_message_append_args (DBusMessage *message,  }  /** - * This function takes a va_list for use by language bindings. - * It's otherwise the same as dbus_message_append_args(). + * Like dbus_message_append_args() but takes a va_list for use by language bindings.   *   * @todo for now, if this function fails due to OOM it will leave   * the message half-written and you have to discard the message @@ -1353,12 +1588,15 @@ dbus_message_append_args_valist (DBusMessage *message,   * followed by a pointer to where the value should be stored. The list   * is terminated with #DBUS_TYPE_INVALID.   * - * The returned values are constant; do not free them. They point - * into the #DBusMessage. + * Except for string arrays, the returned values are constant; do not + * free them. They point into the #DBusMessage.   *   * If the requested arguments are not present, or do not have the   * requested types, then an error will be set.   * + * If more arguments than requested are present, the requested + * arguments are returned and the extra arguments are ignored. + *    * @todo support DBUS_TYPE_STRUCT and DBUS_TYPE_VARIANT and complex arrays   *   * @param message the message @@ -1387,8 +1625,7 @@ dbus_message_get_args (DBusMessage     *message,  }  /** - * This function takes a va_list for use by language bindings. It is - * otherwise the same as dbus_message_get_args(). + * Like dbus_message_get_args but takes a va_list for use by language bindings.   *   * @see dbus_message_get_args   * @param message the message @@ -1434,6 +1671,20 @@ _dbus_message_iter_init_common (DBusMessage         *message,   * Initializes a #DBusMessageIter for reading the arguments of the   * message passed in.   * + * When possible, dbus_message_get_args() is much more convenient. + * Some types of argument can only be read with #DBusMessageIter + * however. + * + * The easiest way to iterate is like this:  + * @code + * dbus_message_iter_init (&iter); + * while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) + *   dbus_message_iter_next (&iter); + * @endcode + * + * #DBusMessageIter contains no allocated memory; it need not be + * freed, and can be copied by assignment or memcpy(). + *    * @param message the message   * @param iter pointer to an iterator to initialize   * @returns #FALSE if the message has no arguments @@ -1469,7 +1720,7 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)  {    if (iter == NULL)      { -      _dbus_warn ("dbus message iterator is NULL\n"); +      _dbus_warn_check_failed ("dbus message iterator is NULL\n");        return FALSE;      } @@ -1477,7 +1728,7 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)      {        if (iter->u.reader.byte_order != iter->message->byte_order)          { -          _dbus_warn ("dbus message changed byte order since iterator was created\n"); +          _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");            return FALSE;          }        /* because we swap the message into compiler order when you init an iter */ @@ -1487,7 +1738,7 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)      {        if (iter->u.writer.byte_order != iter->message->byte_order)          { -          _dbus_warn ("dbus message changed byte order since append iterator was created\n"); +          _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");            return FALSE;          }        /* because we swap the message into compiler order when you init an iter */ @@ -1495,13 +1746,13 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)      }    else      { -      _dbus_warn ("dbus message iterator looks uninitialized or corrupted\n"); +      _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");        return FALSE;      }    if (iter->changed_stamp != iter->message->changed_stamp)      { -      _dbus_warn ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n"); +      _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");        return FALSE;      } @@ -1513,8 +1764,7 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)   * Checks if an iterator has any more fields.   *   * @param iter the message iter - * @returns #TRUE if there are more fields - * following + * @returns #TRUE if there are more fields following   */  dbus_bool_t  dbus_message_iter_has_next (DBusMessageIter *iter) @@ -1626,6 +1876,8 @@ dbus_message_iter_recurse (DBusMessageIter  *iter,   * recurse into a variant and determine the signature of   * the variant's value.   * + * The returned string must be freed with dbus_free(). + *    * @param iter the message iterator   * @returns the contained signature, or NULL if out of memory   */ @@ -1677,10 +1929,12 @@ dbus_message_iter_get_signature (DBusMessageIter *iter)   * #endif   * @endcode   * - * To avoid the #DBUS_HAVE_INT64 conditional, create a struct or - * something that occupies at least 8 bytes, e.g. you could use a - * struct with two int32 values in it. dbus_uint64_t is just one - * example of a type that's large enough to hold any possible value. + * You can skip the #DBUS_HAVE_INT64 conditional unless you care about + * some sort of really obscure platform. If you do know about such a + * platform and want your code to work on it, create a struct + * that occupies at least 8 bytes. dbus_uint64_t is just + * one example of a type that's large enough to hold any possible + * value.   *   * Be sure you have somehow checked that   * dbus_message_iter_get_arg_type() matches the type you are @@ -1704,10 +1958,22 @@ dbus_message_iter_get_basic (DBusMessageIter  *iter,  }  /** - * Returns the number of elements in the array; + * Returns the number of bytes in the array as marshaled in the wire + * protocol. The iterator must currently be inside an array-typed + * value. + * + * This function is deprecated on the grounds that it is stupid.  Why + * would you want to know how many bytes are in the array as marshaled + * in the wire protocol?  For now, use the n_elements returned from + * dbus_message_iter_get_fixed_array() instead, or iterate over the + * array values and count them.   * + * @todo introduce a variant of this get_n_elements that returns + * the number of elements, though with a non-fixed array it will not + * be very efficient, so maybe it's not good. + *    * @param iter the iterator - * @returns the number of elements in the array + * @returns the number of bytes in the array   */  int  dbus_message_iter_get_array_len (DBusMessageIter *iter) @@ -1725,13 +1991,17 @@ dbus_message_iter_get_array_len (DBusMessageIter *iter)   * such as integers, bool, double. The block read will be from the   * current position in the array until the end of the array.   * - * This function should only be used if #dbus_type_is_fixed returns + * This function should only be used if dbus_type_is_fixed() returns   * #TRUE for the element type.   *   * The value argument should be the address of a location to store the   * returned array. So for int32 it should be a "const dbus_int32_t**"   * The returned value is by reference and should not be freed.   * + * Because the array is not copied, this function runs in + * constant time and is fast; it's much preferred over walking the + * entire array with an iterator. + *    * @param iter the iterator   * @param value location to store the block   * @param n_elements number of elements in the block @@ -1754,202 +2024,12 @@ dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,  }  /** - * This function takes a va_list for use by language bindings and is - * otherwise the same as dbus_message_iter_get_args(). - * dbus_message_get_args() is the place to go for complete - * documentation. - * - * @see dbus_message_get_args - * @param iter the message iter - * @param error error to be filled in - * @param first_arg_type type of the first argument - * @param var_args return location for first argument, followed by list of type/location pairs - * @returns #FALSE if error was set - */ -dbus_bool_t -_dbus_message_iter_get_args_valist (DBusMessageIter *iter, -                                    DBusError       *error, -                                    int              first_arg_type, -                                    va_list          var_args) -{ -  DBusMessageRealIter *real = (DBusMessageRealIter *)iter; -  int spec_type, msg_type, i; -  dbus_bool_t retval; - -  _dbus_assert (_dbus_message_iter_check (real)); - -  retval = FALSE; - -  spec_type = first_arg_type; -  i = 0; - -  while (spec_type != DBUS_TYPE_INVALID) -    { -      msg_type = dbus_message_iter_get_arg_type (iter); - -      if (msg_type != spec_type) -	{ -          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, -                          "Argument %d is specified to be of type \"%s\", but " -                          "is actually of type \"%s\"\n", i, -                          _dbus_type_to_string (spec_type), -                          _dbus_type_to_string (msg_type)); - -          goto out; -	} - -      if (dbus_type_is_basic (spec_type)) -        { -          DBusBasicValue *ptr; - -          ptr = va_arg (var_args, DBusBasicValue*); - -          _dbus_assert (ptr != NULL); - -          _dbus_type_reader_read_basic (&real->u.reader, -                                        ptr); -        } -      else if (spec_type == DBUS_TYPE_ARRAY) -        { -          int element_type; -          int spec_element_type; -          const DBusBasicValue **ptr; -          int *n_elements_p; -          DBusTypeReader array; - -          spec_element_type = va_arg (var_args, int); -          element_type = _dbus_type_reader_get_element_type (&real->u.reader); - -          if (spec_element_type != element_type) -            { -              dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, -                              "Argument %d is specified to be an array of \"%s\", but " -                              "is actually an array of \"%s\"\n", -                              i, -                              _dbus_type_to_string (spec_element_type), -                              _dbus_type_to_string (element_type)); - -              goto out; -            } - -          if (dbus_type_is_fixed (spec_element_type)) -            { -              ptr = va_arg (var_args, const DBusBasicValue**); -              n_elements_p = va_arg (var_args, int*); - -              _dbus_assert (ptr != NULL); -              _dbus_assert (n_elements_p != NULL); - -              _dbus_type_reader_recurse (&real->u.reader, &array); - -              _dbus_type_reader_read_fixed_multi (&array, -                                                  ptr, n_elements_p); -            } -          else if (spec_element_type == DBUS_TYPE_STRING || -                   spec_element_type == DBUS_TYPE_SIGNATURE || -                   spec_element_type == DBUS_TYPE_OBJECT_PATH) -            { -              char ***str_array_p; -              int n_elements; -              char **str_array; - -              str_array_p = va_arg (var_args, char***); -              n_elements_p = va_arg (var_args, int*); - -              _dbus_assert (str_array_p != NULL); -              _dbus_assert (n_elements_p != NULL); - -              /* Count elements in the array */ -              _dbus_type_reader_recurse (&real->u.reader, &array); - -              n_elements = 0; -              while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) -                { -                  ++n_elements; -                  _dbus_type_reader_next (&array); -                } - -              str_array = dbus_new0 (char*, n_elements + 1); -              if (str_array == NULL) -                { -                  _DBUS_SET_OOM (error); -                  goto out; -                } - -              /* Now go through and dup each string */ -              _dbus_type_reader_recurse (&real->u.reader, &array); - -              i = 0; -              while (i < n_elements) -                { -                  const char *s; -                  _dbus_type_reader_read_basic (&array, -                                                &s); -                   -                  str_array[i] = _dbus_strdup (s); -                  if (str_array[i] == NULL) -                    { -                      dbus_free_string_array (str_array); -                      _DBUS_SET_OOM (error); -                      goto out; -                    } -                   -                  ++i; -                   -                  if (!_dbus_type_reader_next (&array)) -                    _dbus_assert (i == n_elements); -                } - -              _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID); -              _dbus_assert (i == n_elements); -              _dbus_assert (str_array[i] == NULL); - -              *str_array_p = str_array; -              *n_elements_p = n_elements; -            } -#ifndef DBUS_DISABLE_CHECKS -          else -            { -              _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n", -                          _DBUS_FUNCTION_NAME); -              goto out; -            } -#endif -        } -#ifndef DBUS_DISABLE_CHECKS -      else -        { -          _dbus_warn ("you can only read arrays and basic types with %s for now\n", -                      _DBUS_FUNCTION_NAME); -          goto out; -        } -#endif - -      spec_type = va_arg (var_args, int); -      if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID) -        { -          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, -                          "Message has only %d arguments, but more were expected", i); -          goto out; -        } - -      i++; -    } - -  retval = TRUE; - - out: - -  return retval; -} - -/**   * Initializes a #DBusMessageIter for appending arguments to the end   * of a message.   *   * @todo If appending any of the arguments fails due to lack of - * memory, generally the message is hosed and you have to start over - * building the whole message. + * memory, the message is hosed and you have to start over building + * the whole message.   *   * @param message the message   * @param iter pointer to an iterator to initialize @@ -2099,7 +2179,7 @@ _dbus_message_iter_append_check (DBusMessageRealIter *iter)    if (iter->message->locked)      { -      _dbus_warn ("dbus append iterator can't be used: message is locked (has already been sent)\n"); +      _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");        return FALSE;      } @@ -2322,6 +2402,11 @@ dbus_message_iter_close_container (DBusMessageIter *iter,   * message successfully arrived at the remote end. Normally you know a   * message was received when you receive the reply to it.   * + * The flag is #FALSE by default, that is by default the other end is + * required to reply. + * + * On the protocol level this toggles #DBUS_HEADER_FLAG_NO_REPLY_EXPECTED + *    * @param message the message   * @param no_reply #TRUE if no reply is desired   */ @@ -2360,6 +2445,10 @@ dbus_message_get_no_reply (DBusMessage *message)   * starting up, or fails to start up. In case of failure, the reply   * will be an error.   * + * The flag is set to #TRUE by default, i.e. auto starting is the default. + * + * On the protocol level this toggles #DBUS_HEADER_FLAG_NO_AUTO_START + *    * @param message the message   * @param auto_start #TRUE if auto-starting is desired   */ @@ -2397,6 +2486,9 @@ dbus_message_get_auto_start (DBusMessage *message)   * DBUS_MESSAGE_TYPE_METHOD_CALL) or the one a signal is being   * emitted from (for DBUS_MESSAGE_TYPE_SIGNAL).   * + * The path must contain only valid characters as defined + * in the D-Bus specification. + *   * @param message the message   * @param object_path the path or #NULL to unset   * @returns #FALSE if not enough memory @@ -2422,6 +2514,11 @@ dbus_message_set_path (DBusMessage   *message,   * DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted from (for   * DBUS_MESSAGE_TYPE_SIGNAL). Returns #NULL if none.   * + * See also dbus_message_get_path_decomposed(). + * + * The returned string becomes invalid if the message is + * modified, since it points into the wire-marshaled message data. + *    * @param message the message   * @returns the path (should not be freed) or #NULL   */ @@ -2441,7 +2538,9 @@ dbus_message_get_path (DBusMessage   *message)  }  /** - * Checks if the message has a path + * Checks if the message has a particular object path.  The object + * path is the destination object for a method call or the emitting + * object for a signal.   *   * @param message the message   * @param path the path name @@ -2482,6 +2581,8 @@ dbus_message_has_path (DBusMessage   *message,   * So the path "/foo/bar" becomes { "foo", "bar", NULL }   * and the path "/" becomes { NULL }.   * + * See also dbus_message_get_path(). + *    * @todo this could be optimized by using the len from the message   * instead of calling strlen() again   * @@ -2516,6 +2617,9 @@ dbus_message_get_path_decomposed (DBusMessage   *message,   * the interface a signal is being emitted from   * (for DBUS_MESSAGE_TYPE_SIGNAL).   * + * The interface name must contain only valid characters as defined + * in the D-Bus specification. + *    * @param message the message   * @param interface the interface or #NULL to unset   * @returns #FALSE if not enough memory @@ -2543,6 +2647,9 @@ dbus_message_set_interface (DBusMessage  *message,   * The interface name is fully-qualified (namespaced).   * Returns #NULL if none.   * + * The returned string becomes invalid if the message is + * modified, since it points into the wire-marshaled message data. + *   * @param message the message   * @returns the message interface (should not be freed) or #NULL   */ @@ -2566,7 +2673,7 @@ dbus_message_get_interface (DBusMessage *message)   *   * @param message the message   * @param interface the interface name - * @returns #TRUE if there is a interface field in the header + * @returns #TRUE if the interface field in the header matches   */  dbus_bool_t  dbus_message_has_interface (DBusMessage   *message, @@ -2597,7 +2704,9 @@ dbus_message_has_interface (DBusMessage   *message,   * Sets the interface member being invoked   * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted   * (DBUS_MESSAGE_TYPE_SIGNAL). - * The interface name is fully-qualified (namespaced). + * + * The member name must contain only valid characters as defined + * in the D-Bus specification.   *   * @param message the message   * @param member the member or #NULL to unset @@ -2624,6 +2733,9 @@ dbus_message_set_member (DBusMessage  *message,   * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted   * (DBUS_MESSAGE_TYPE_SIGNAL). Returns #NULL if none.   * + * The returned string becomes invalid if the message is + * modified, since it points into the wire-marshaled message data. + *    * @param message the message   * @returns the member name (should not be freed) or #NULL   */ @@ -2678,6 +2790,9 @@ dbus_message_has_member (DBusMessage   *message,   * Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).   * The name is fully-qualified (namespaced).   * + * The error name must contain only valid characters as defined + * in the D-Bus specification. + *   * @param message the message   * @param error_name the name or #NULL to unset   * @returns #FALSE if not enough memory @@ -2702,6 +2817,9 @@ dbus_message_set_error_name (DBusMessage  *message,   * Gets the error name (DBUS_MESSAGE_TYPE_ERROR only)   * or #NULL if none.   * + * The returned string becomes invalid if the message is + * modified, since it points into the wire-marshaled message data. + *    * @param message the message   * @returns the error name (should not be freed) or #NULL   */ @@ -2726,6 +2844,9 @@ dbus_message_get_error_name (DBusMessage *message)   * assigned by the bus to each connection, or a well-known name   * specified in advance.   * + * The destination name must contain only valid characters as defined + * in the D-Bus specification. + *    * @param message the message   * @param destination the destination name or #NULL to unset   * @returns #FALSE if not enough memory @@ -2749,6 +2870,9 @@ dbus_message_set_destination (DBusMessage  *message,  /**   * Gets the destination of a message or #NULL if there is none set.   * + * The returned string becomes invalid if the message is + * modified, since it points into the wire-marshaled message data. + *   * @param message the message   * @returns the message destination (should not be freed) or #NULL   */ @@ -2770,6 +2894,13 @@ dbus_message_get_destination (DBusMessage *message)  /**   * Sets the message sender.   * + * The sender must be a valid bus name as defined in the D-Bus + * specification. + * + * Usually you don't want to call this. The message bus daemon will + * call it to set the origin of each message. If you aren't implementing + * a message bus daemon you shouldn't need to set the sender. + *   * @param message the message   * @param sender the sender or #NULL to unset   * @returns #FALSE if not enough memory @@ -2795,6 +2926,13 @@ dbus_message_set_sender (DBusMessage  *message,   * message, or #NULL if unknown or inapplicable. The sender is filled   * in by the message bus.   * + * Note, the returned sender is always the unique bus name. + * Connections may own multiple other bus names, but those + * are not found in the sender field. + *  + * The returned string becomes invalid if the message is + * modified, since it points into the wire-marshaled message data. + *   * @param message the message   * @returns the unique name of the sender or #NULL   */ @@ -2818,13 +2956,16 @@ dbus_message_get_sender (DBusMessage *message)   * message payload. The signature includes only "in" arguments for   * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for   * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from - * what you might expect (it does not include the signature of the + * what you might expect (that is, it does not include the signature of the   * entire C++-style method).   *   * The signature is a string made up of type codes such as   * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also   * the value of #DBUS_TYPE_INVALID).   * + * The returned string becomes invalid if the message is + * modified, since it points into the wire-marshaled message data. + *   * @param message the message   * @returns the type signature   */ @@ -2907,9 +3048,7 @@ dbus_message_is_method_call (DBusMessage *message,  /**   * Checks whether the message is a signal with the given interface and   * member fields.  If the message is not #DBUS_MESSAGE_TYPE_SIGNAL, or - * has a different interface or member field, returns #FALSE.  If the - * interface field in the message is missing, it is assumed to match - * any interface you pass in to this function. + * has a different interface or member field, returns #FALSE.   *   * @param message the message   * @param interface the name to check (must not be #NULL) @@ -3064,7 +3203,7 @@ dbus_message_has_signature (DBusMessage   *message,  /**   * Sets a #DBusError based on the contents of the given   * message. The error is only set if the message - * is an error message, as in DBUS_MESSAGE_TYPE_ERROR. + * is an error message, as in #DBUS_MESSAGE_TYPE_ERROR.   * The name of the error is set to the name of the message,   * and the error message is set to the first argument   * if the argument exists and is a string. @@ -3081,7 +3220,7 @@ dbus_message_has_signature (DBusMessage   *message,   *   * @param error the error to set   * @param message the message to set it from - * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message + * @returns #TRUE if the message had type #DBUS_MESSAGE_TYPE_ERROR   */  dbus_bool_t  dbus_set_error_from_message (DBusError   *error, diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index f0e80a67..b0351758 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -163,7 +163,12 @@ void        dbus_message_iter_recurse          (DBusMessageIter *iter,                                                  DBusMessageIter *sub);  void        dbus_message_iter_get_basic        (DBusMessageIter *iter,                                                  void            *value); +#ifndef DBUS_DISABLE_DEPRECATED +/* This function returns the wire protocol size of the array in bytes, + * you do not want to know that probably + */  int         dbus_message_iter_get_array_len    (DBusMessageIter *iter); +#endif  void        dbus_message_iter_get_fixed_array  (DBusMessageIter *iter,                                                  void            *value,                                                  int             *n_elements); diff --git a/dbus/dbus-timeout.c b/dbus/dbus-timeout.c index 72784660..e4b71e26 100644 --- a/dbus/dbus-timeout.c +++ b/dbus/dbus-timeout.c @@ -384,6 +384,9 @@ _dbus_timeout_list_toggle_timeout (DBusTimeoutList           *timeout_list,   * Types and functions related to DBusTimeout. A timeout   * represents a timeout that the main loop needs to monitor,   * as in Qt's QTimer or GLib's g_timeout_add(). + * + * Use dbus_connection_set_timeout_functions() or dbus_server_set_timeout_functions() + * to be notified when libdbus needs to add or remove timeouts.   *    * @{   */ diff --git a/dbus/dbus-watch.c b/dbus/dbus-watch.c index a7a5adba..ebbb7ed2 100644 --- a/dbus/dbus-watch.c +++ b/dbus/dbus-watch.c @@ -465,6 +465,9 @@ _dbus_watch_set_handler (DBusWatch        *watch,   * Types and functions related to DBusWatch. A watch represents   * a file descriptor that the main loop needs to monitor,   * as in Qt's QSocketNotifier or GLib's g_io_add_watch(). + * + * Use dbus_connection_set_watch_functions() or dbus_server_set_watch_functions() + * to be notified when libdbus needs to add or remove watches.   *    * @{   */ diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index 41d3fb9b..977734d7 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -1184,7 +1184,8 @@            A signal emission is simply a single message of type <literal>SIGNAL</literal>.            It must have three header fields: <literal>PATH</literal> giving the object             the signal was emitted from, plus <literal>INTERFACE</literal> and <literal>MEMBER</literal> giving -          the fully-qualified name of the signal. +          the fully-qualified name of the signal. The <literal>INTERFACE</literal> header is required +          for signals, though it is optional for method calls.          </para>        </sect3> @@ -3014,7 +3015,9 @@                    <entry><literal>interface</literal></entry>                    <entry>An interface name (see <xref linkend="message-protocol-names-interface"/>)</entry>                    <entry>Match messages sent over or to a particular interface.  An example of an -                  interface match is interface='org.freedesktop.Hal.Manager'</entry> +                  interface match is interface='org.freedesktop.Hal.Manager'. +                  If a message omits the interface header, it must not match any rule  +                  that specifies this key.</entry>                  </row>                  <row>                    <entry><literal>member</literal></entry> @@ -3035,12 +3038,13 @@                    example of a destination match is destination=':1.0'</entry>                  </row>                  <row> -                  <entry><literal>arg[1, 2, 3, ...]</literal></entry> +                  <entry><literal>arg[0, 1, 2, 3, ...]</literal></entry>                    <entry>Any string</entry>                    <entry>Arg matches are special and are used for further restricting the                     match based on the arguments in the body of a message.  As of this time                    only string arguments can be matched.  An example of an argument match  -                  would be arg3='Foo'.</entry> +                  would be arg3='Foo'. Only argument indexes from 0 to 63 should be  +                  accepted.</entry>                  </row>                </tbody>              </tgroup>  | 
