/* * Open a new entry in an a{sv} (map from string to variant). * * This must be paired with a call to either _dbus_asv_close_entry() * or _dbus_asv_abandon_entry(). * * If this function fails, the a{sv} must be abandoned, for instance * with _dbus_asv_abandon(). * * @param arr_iter the iterator which is appending to the array * @param entry_iter will be initialized to append to the dict-entry * @param key a UTF-8 key for the map * @param type the type of the variant value, e.g. DBUS_TYPE_STRING_AS_STRING * @param var_iter will be initialized to append (i.e. write) to the variant * @returns #TRUE on success, or #FALSE if not enough memory */ static dbus_bool_t _dbus_asv_open_entry (DBusMessageIter *arr_iter, DBusMessageIter *entry_iter, const char *key, const char *type, DBusMessageIter *var_iter) { if (!dbus_message_iter_open_container (arr_iter, DBUS_TYPE_DICT_ENTRY, NULL, entry_iter)) return FALSE; if (!dbus_message_iter_append_basic (entry_iter, DBUS_TYPE_STRING, &key)) { dbus_message_iter_abandon_container (arr_iter, entry_iter); return FALSE; } if (!dbus_message_iter_open_container (entry_iter, DBUS_TYPE_VARIANT, type, var_iter)) { dbus_message_iter_abandon_container (arr_iter, entry_iter); return FALSE; } return TRUE; }
/* * Closes an a{sv} entry after unsuccessfully appending a value. * You must also abandon the a{sv} itself (for instance with * _dbus_asv_abandon()), and abandon whatever larger data structure * the a{sv} was embedded in. * * @param iter the iterator which is appending to the message or other data structure containing the a{sv} * @param arr_iter the iterator appending to the array, will be closed * @returns #TRUE on success, or #FALSE if not enough memory */ static void _dbus_asv_abandon_entry (DBusMessageIter *arr_iter, DBusMessageIter *entry_iter, DBusMessageIter *var_iter) { dbus_message_iter_abandon_container (entry_iter, var_iter); dbus_message_iter_abandon_container (arr_iter, entry_iter); }
/** * PropertiesChangedSignal() synthetizes and sends the * org.freedesktop.DBus.Properties.PropertiesChanged signal */ static DBusHandlerResult PropertiesChangedSignal( intf_thread_t *p_intf, vlc_dictionary_t *p_changed_properties ) { DBusConnection *p_conn = p_intf->p_sys->p_conn; DBusMessageIter changed_properties, invalidated_properties; const char *psz_interface_name = DBUS_MPRIS_PLAYER_INTERFACE; char **ppsz_properties = NULL; SIGNAL_INIT( DBUS_INTERFACE_PROPERTIES, DBUS_MPRIS_OBJECT_PATH, "PropertiesChanged" ); OUT_ARGUMENTS; ADD_STRING( &psz_interface_name ); if( !dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "{sv}", &changed_properties ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; ppsz_properties = vlc_dictionary_all_keys( p_changed_properties ); if( unlikely(!ppsz_properties) ) { dbus_message_iter_abandon_container( &args, &changed_properties ); return DBUS_HANDLER_RESULT_NEED_MEMORY; } for( int i = 0; ppsz_properties[i]; i++ ) { PROPERTY_MAPPING_BEGIN PROPERTY_ENTRY( Metadata, "a{sv}" ) PROPERTY_ENTRY( PlaybackStatus, "s" ) PROPERTY_ENTRY( LoopStatus, "s" ) PROPERTY_ENTRY( Rate, "d" ) PROPERTY_ENTRY( Shuffle, "b" ) PROPERTY_ENTRY( Volume, "d" ) PROPERTY_ENTRY( CanSeek, "b" ) PROPERTY_ENTRY( CanPlay, "b" ) PROPERTY_ENTRY( CanPause, "b" ) PROPERTY_MAPPING_END free( ppsz_properties[i] ); } free( ppsz_properties ); if( !dbus_message_iter_close_container( &args, &changed_properties ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( !dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "s", &invalidated_properties ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( !dbus_message_iter_close_container( &args, &invalidated_properties ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; SIGNAL_SEND; }
/** * PropertiesChangedSignal: synthetizes and sends the * org.freedesktop.DBus.Properties.PropertiesChanged signal */ static DBusHandlerResult PropertiesChangedSignal( intf_thread_t *p_intf, vlc_dictionary_t *p_changed_properties ) { DBusConnection *p_conn = p_intf->p_sys->p_conn; DBusMessageIter changed_properties, invalidated_properties; const char *psz_interface_name = DBUS_MPRIS_TRACKLIST_INTERFACE; char **ppsz_properties = NULL; int i_properties = 0; SIGNAL_INIT( DBUS_INTERFACE_PROPERTIES, DBUS_MPRIS_OBJECT_PATH, "PropertiesChanged" ); OUT_ARGUMENTS; ADD_STRING( &psz_interface_name ); if( unlikely(!dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "{sv}", &changed_properties )) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( unlikely(!dbus_message_iter_close_container( &args, &changed_properties )) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( unlikely(!dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "s", &invalidated_properties )) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; i_properties = vlc_dictionary_keys_count( p_changed_properties ); ppsz_properties = vlc_dictionary_all_keys( p_changed_properties ); if( unlikely(!ppsz_properties) ) { dbus_message_iter_abandon_container( &args, &invalidated_properties ); return DBUS_HANDLER_RESULT_NEED_MEMORY; } for( int i = 0; i < i_properties; i++ ) { if( !strcmp( ppsz_properties[i], "Tracks" ) ) dbus_message_iter_append_basic( &invalidated_properties, DBUS_TYPE_STRING, &ppsz_properties[i] ); free( ppsz_properties[i] ); } free( ppsz_properties ); if( unlikely(!dbus_message_iter_close_container( &args, &invalidated_properties )) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; SIGNAL_SEND; }
/* * Closes an a{sv} entry after successfully appending the value. * * If this function fails, the a{sv} must be abandoned, for instance * with _dbus_asv_abandon(). * * @param arr_iter the iterator which is appending to the array * @param entry_iter the iterator appending to the dict-entry, will be closed * @param var_iter the iterator appending to the variant, will be closed * @returns #TRUE on success, or #FALSE if not enough memory */ static dbus_bool_t _dbus_asv_close_entry (DBusMessageIter *arr_iter, DBusMessageIter *entry_iter, DBusMessageIter *var_iter) { if (!dbus_message_iter_close_container (entry_iter, var_iter)) { dbus_message_iter_abandon_container (arr_iter, entry_iter); return FALSE; } if (!dbus_message_iter_close_container (arr_iter, entry_iter)) return FALSE; return TRUE; }
/** * PropertiesChangedSignal() synthetizes and sends the * org.freedesktop.DBus.Properties.PropertiesChanged signal */ static DBusHandlerResult PropertiesChangedSignal( intf_thread_t *p_intf, vlc_dictionary_t *p_changed_properties ) { DBusConnection *p_conn = p_intf->p_sys->p_conn; DBusMessageIter changed_properties, invalidated_properties; const char *psz_interface_name = DBUS_MPRIS_ROOT_INTERFACE; SIGNAL_INIT( DBUS_INTERFACE_PROPERTIES, DBUS_MPRIS_OBJECT_PATH, "PropertiesChanged" ); OUT_ARGUMENTS; ADD_STRING( &psz_interface_name ); if( !dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "{sv}", &changed_properties ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( vlc_dictionary_has_key( p_changed_properties, "Fullscreen" ) ) { if( AddProperty( p_intf, &changed_properties, "Fullscreen", "b", MarshalFullscreen ) != VLC_SUCCESS ) { dbus_message_iter_abandon_container( &args, &changed_properties ); return DBUS_HANDLER_RESULT_NEED_MEMORY; } } if( !dbus_message_iter_close_container( &args, &changed_properties ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( !dbus_message_iter_open_container( &args, DBUS_TYPE_ARRAY, "s", &invalidated_properties ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; if( !dbus_message_iter_close_container( &args, &invalidated_properties ) ) return DBUS_HANDLER_RESULT_NEED_MEMORY; SIGNAL_SEND; }
static int MarshalTracks( intf_thread_t *p_intf, DBusMessageIter *container ) { DBusMessageIter tracks; char *psz_track_id = NULL; playlist_t *p_playlist = p_intf->p_sys->p_playlist; input_item_t *p_input = NULL; dbus_message_iter_open_container( container, DBUS_TYPE_ARRAY, "o", &tracks ); PL_LOCK; for( int i = 0; i < playlist_CurrentSize( p_playlist ); i++ ) { p_input = p_playlist->current.p_elems[i]->p_input; if( ( -1 == asprintf( &psz_track_id, MPRIS_TRACKID_FORMAT, p_input->i_id ) ) || !dbus_message_iter_append_basic( &tracks, DBUS_TYPE_OBJECT_PATH, &psz_track_id ) ) { PL_UNLOCK; dbus_message_iter_abandon_container( container, &tracks ); return VLC_ENOMEM; } free( psz_track_id ); } PL_UNLOCK; if( !dbus_message_iter_close_container( container, &tracks ) ) return VLC_ENOMEM; return VLC_SUCCESS; }
static int my_com_netsplit_Nih_Test_size_get (NihDBusObject * object, NihDBusMessage * message, DBusMessageIter *iter) { DBusMessageIter variter; uint32_t value; nih_assert (object != NULL); nih_assert (message != NULL); nih_assert (iter != NULL); /* Call the handler function */ if (my_test_get_size (object->data, message, &value) < 0) return -1; /* Append a variant onto the message to contain the property value. */ if (! dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "u", &variter)) { nih_error_raise_no_memory (); return -1; } /* Marshal a uint32_t onto the message */ if (! dbus_message_iter_append_basic (&variter, DBUS_TYPE_UINT32, &value)) { dbus_message_iter_abandon_container (iter, &variter); nih_error_raise_no_memory (); return -1; } /* Finish the variant */ if (! dbus_message_iter_close_container (iter, &variter)) { nih_error_raise_no_memory (); return -1; } return 0; }
/** * @ingroup DBusMessageInternals * Unit test for DBusMessage. * * @returns #TRUE on success. */ dbus_bool_t _dbus_message_test (const char *test_data_dir) { DBusMessage *message, *message_without_unix_fds; DBusMessageLoader *loader; int i; const char *data; DBusMessage *copy; const char *name1; const char *name2; const dbus_uint32_t our_uint32_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 }; const dbus_int32_t our_int32_array[] = { 0x12345678, -0x23456781, 0x34567812, -0x45678123 }; const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array; const dbus_int32_t *v_ARRAY_INT32 = our_int32_array; #ifdef DBUS_HAVE_INT64 const dbus_uint64_t our_uint64_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 }; const dbus_int64_t our_int64_array[] = { 0x12345678, -0x23456781, 0x34567812, -0x45678123 }; const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array; const dbus_int64_t *v_ARRAY_INT64 = our_int64_array; #endif const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" }; const char **v_ARRAY_STRING = our_string_array; const double our_double_array[] = { 0.1234, 9876.54321, -300.0 }; const double *v_ARRAY_DOUBLE = our_double_array; const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 }; const unsigned char *v_ARRAY_BYTE = our_byte_array; const dbus_bool_t our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE }; const dbus_bool_t *v_ARRAY_BOOLEAN = our_boolean_array; char sig[64]; const char *s; const char *v_STRING; double v_DOUBLE; dbus_int16_t v_INT16; dbus_uint16_t v_UINT16; dbus_int32_t v_INT32; dbus_uint32_t v_UINT32; #ifdef DBUS_HAVE_INT64 dbus_int64_t v_INT64; dbus_uint64_t v_UINT64; #endif unsigned char v_BYTE; unsigned char v2_BYTE; dbus_bool_t v_BOOLEAN; DBusMessageIter iter, array_iter, struct_iter; #ifdef HAVE_UNIX_FD_PASSING int v_UNIX_FD; #endif char **decomposed; message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService", "/org/freedesktop/TestPath", "Foo.TestInterface", "TestMethod"); _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService")); _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface", "TestMethod")); _dbus_assert (strcmp (dbus_message_get_path (message), "/org/freedesktop/TestPath") == 0); dbus_message_set_serial (message, 1234); /* string length including nul byte not a multiple of 4 */ if (!dbus_message_set_sender (message, "org.foo.bar1")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1")); dbus_message_set_reply_serial (message, 5678); _dbus_verbose_bytes_of_string (&message->header.data, 0, _dbus_string_get_length (&message->header.data)); _dbus_verbose_bytes_of_string (&message->body, 0, _dbus_string_get_length (&message->body)); if (!dbus_message_set_sender (message, NULL)) _dbus_assert_not_reached ("out of memory"); _dbus_verbose_bytes_of_string (&message->header.data, 0, _dbus_string_get_length (&message->header.data)); _dbus_verbose_bytes_of_string (&message->body, 0, _dbus_string_get_length (&message->body)); _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1")); _dbus_assert (dbus_message_get_serial (message) == 1234); _dbus_assert (dbus_message_get_reply_serial (message) == 5678); _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService")); _dbus_assert (dbus_message_get_no_reply (message) == FALSE); dbus_message_set_no_reply (message, TRUE); _dbus_assert (dbus_message_get_no_reply (message) == TRUE); dbus_message_set_no_reply (message, FALSE); _dbus_assert (dbus_message_get_no_reply (message) == FALSE); /* Set/get some header fields */ if (!dbus_message_set_path (message, "/foo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_path (message), "/foo") == 0); if (!dbus_message_set_interface (message, "org.Foo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_interface (message), "org.Foo") == 0); if (!dbus_message_set_member (message, "Bar")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_member (message), "Bar") == 0); /* Set/get them with longer values */ if (!dbus_message_set_path (message, "/foo/bar")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_path (message), "/foo/bar") == 0); if (!dbus_message_set_interface (message, "org.Foo.Bar")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_interface (message), "org.Foo.Bar") == 0); if (!dbus_message_set_member (message, "BarFoo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_member (message), "BarFoo") == 0); /* Realloc shorter again */ if (!dbus_message_set_path (message, "/foo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_path (message), "/foo") == 0); if (!dbus_message_set_interface (message, "org.Foo")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_interface (message), "org.Foo") == 0); if (!dbus_message_set_member (message, "Bar")) _dbus_assert_not_reached ("out of memory"); _dbus_assert (strcmp (dbus_message_get_member (message), "Bar") == 0); /* Path decomposing */ dbus_message_set_path (message, NULL); dbus_message_get_path_decomposed (message, &decomposed); _dbus_assert (decomposed == NULL); dbus_free_string_array (decomposed); dbus_message_set_path (message, "/"); dbus_message_get_path_decomposed (message, &decomposed); _dbus_assert (decomposed != NULL); _dbus_assert (decomposed[0] == NULL); dbus_free_string_array (decomposed); dbus_message_set_path (message, "/a/b"); dbus_message_get_path_decomposed (message, &decomposed); _dbus_assert (decomposed != NULL); _dbus_assert (strcmp (decomposed[0], "a") == 0); _dbus_assert (strcmp (decomposed[1], "b") == 0); _dbus_assert (decomposed[2] == NULL); dbus_free_string_array (decomposed); dbus_message_set_path (message, "/spam/eggs"); dbus_message_get_path_decomposed (message, &decomposed); _dbus_assert (decomposed != NULL); _dbus_assert (strcmp (decomposed[0], "spam") == 0); _dbus_assert (strcmp (decomposed[1], "eggs") == 0); _dbus_assert (decomposed[2] == NULL); dbus_free_string_array (decomposed); dbus_message_unref (message); /* Test the vararg functions */ message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService", "/org/freedesktop/TestPath", "Foo.TestInterface", "TestMethod"); dbus_message_set_serial (message, 1); dbus_message_set_reply_serial (message, 5678); v_INT16 = -0x123; v_UINT16 = 0x123; v_INT32 = -0x12345678; v_UINT32 = 0x12300042; #ifdef DBUS_HAVE_INT64 v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd); v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd); #endif v_STRING = "Test string"; v_DOUBLE = 3.14159; v_BOOLEAN = TRUE; v_BYTE = 42; v2_BYTE = 24; #ifdef HAVE_UNIX_FD_PASSING v_UNIX_FD = 1; #endif dbus_message_append_args (message, DBUS_TYPE_INT16, &v_INT16, DBUS_TYPE_UINT16, &v_UINT16, DBUS_TYPE_INT32, &v_INT32, DBUS_TYPE_UINT32, &v_UINT32, #ifdef DBUS_HAVE_INT64 DBUS_TYPE_INT64, &v_INT64, DBUS_TYPE_UINT64, &v_UINT64, #endif DBUS_TYPE_STRING, &v_STRING, DBUS_TYPE_DOUBLE, &v_DOUBLE, DBUS_TYPE_BOOLEAN, &v_BOOLEAN, DBUS_TYPE_BYTE, &v_BYTE, DBUS_TYPE_BYTE, &v2_BYTE, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32, _DBUS_N_ELEMENTS (our_uint32_array), DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32, _DBUS_N_ELEMENTS (our_int32_array), #ifdef DBUS_HAVE_INT64 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64, _DBUS_N_ELEMENTS (our_uint64_array), DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64, _DBUS_N_ELEMENTS (our_int64_array), #endif DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE, _DBUS_N_ELEMENTS (our_double_array), DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE, _DBUS_N_ELEMENTS (our_byte_array), DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN, _DBUS_N_ELEMENTS (our_boolean_array), DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING, _DBUS_N_ELEMENTS (our_string_array), DBUS_TYPE_INVALID); i = 0; sig[i++] = DBUS_TYPE_INT16; sig[i++] = DBUS_TYPE_UINT16; sig[i++] = DBUS_TYPE_INT32; sig[i++] = DBUS_TYPE_UINT32; #ifdef DBUS_HAVE_INT64 sig[i++] = DBUS_TYPE_INT64; sig[i++] = DBUS_TYPE_UINT64; #endif sig[i++] = DBUS_TYPE_STRING; sig[i++] = DBUS_TYPE_DOUBLE; sig[i++] = DBUS_TYPE_BOOLEAN; sig[i++] = DBUS_TYPE_BYTE; sig[i++] = DBUS_TYPE_BYTE; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_UINT32; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_INT32; #ifdef DBUS_HAVE_INT64 sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_UINT64; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_INT64; #endif sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_DOUBLE; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_BYTE; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_BOOLEAN; sig[i++] = DBUS_TYPE_ARRAY; sig[i++] = DBUS_TYPE_STRING; message_without_unix_fds = dbus_message_copy(message); _dbus_assert(message_without_unix_fds); #ifdef HAVE_UNIX_FD_PASSING dbus_message_append_args (message, DBUS_TYPE_UNIX_FD, &v_UNIX_FD, DBUS_TYPE_INVALID); sig[i++] = DBUS_TYPE_UNIX_FD; #endif sig[i++] = DBUS_TYPE_INVALID; _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig)); _dbus_verbose ("HEADER\n"); _dbus_verbose_bytes_of_string (&message->header.data, 0, _dbus_string_get_length (&message->header.data)); _dbus_verbose ("BODY\n"); _dbus_verbose_bytes_of_string (&message->body, 0, _dbus_string_get_length (&message->body)); _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n", sig, dbus_message_get_signature (message)); s = dbus_message_get_signature (message); _dbus_assert (dbus_message_has_signature (message, sig)); _dbus_assert (strcmp (s, sig) == 0); verify_test_message (message); copy = dbus_message_copy (message); _dbus_assert (dbus_message_get_reply_serial (message) == dbus_message_get_reply_serial (copy)); _dbus_assert (message->header.padding == copy->header.padding); _dbus_assert (_dbus_string_get_length (&message->header.data) == _dbus_string_get_length (©->header.data)); _dbus_assert (_dbus_string_get_length (&message->body) == _dbus_string_get_length (©->body)); verify_test_message (copy); name1 = dbus_message_get_interface (message); name2 = dbus_message_get_interface (copy); _dbus_assert (strcmp (name1, name2) == 0); name1 = dbus_message_get_member (message); name2 = dbus_message_get_member (copy); _dbus_assert (strcmp (name1, name2) == 0); dbus_message_unref (copy); /* Message loader test */ dbus_message_lock (message); loader = _dbus_message_loader_new (); /* check ref/unref */ _dbus_message_loader_ref (loader); _dbus_message_loader_unref (loader); /* Write the header data one byte at a time */ data = _dbus_string_get_const_data (&message->header.data); for (i = 0; i < _dbus_string_get_length (&message->header.data); i++) { DBusString *buffer; _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, data[i]); _dbus_message_loader_return_buffer (loader, buffer, 1); } /* Write the body data one byte at a time */ data = _dbus_string_get_const_data (&message->body); for (i = 0; i < _dbus_string_get_length (&message->body); i++) { DBusString *buffer; _dbus_message_loader_get_buffer (loader, &buffer); _dbus_string_append_byte (buffer, data[i]); _dbus_message_loader_return_buffer (loader, buffer, 1); } #ifdef HAVE_UNIX_FD_PASSING { int *unix_fds; unsigned n_unix_fds; /* Write unix fd */ _dbus_message_loader_get_unix_fds(loader, &unix_fds, &n_unix_fds); _dbus_assert(n_unix_fds > 0); _dbus_assert(message->n_unix_fds == 1); unix_fds[0] = _dbus_dup(message->unix_fds[0], NULL); _dbus_assert(unix_fds[0] >= 0); _dbus_message_loader_return_unix_fds(loader, unix_fds, 1); } #endif dbus_message_unref (message); /* Now pop back the message */ if (!_dbus_message_loader_queue_messages (loader)) _dbus_assert_not_reached ("no memory to queue messages"); if (_dbus_message_loader_get_is_corrupted (loader)) _dbus_assert_not_reached ("message loader corrupted"); message = _dbus_message_loader_pop_message (loader); if (!message) _dbus_assert_not_reached ("received a NULL message"); if (dbus_message_get_reply_serial (message) != 5678) _dbus_assert_not_reached ("reply serial fields differ"); dbus_message_unref (message); /* ovveride the serial, since it was reset by dbus_message_copy() */ dbus_message_set_serial(message_without_unix_fds, 8901); dbus_message_lock (message_without_unix_fds); verify_test_message (message_without_unix_fds); { /* Marshal and demarshal the message. */ DBusMessage *message2; DBusError error = DBUS_ERROR_INIT; char *marshalled = NULL; int len = 0; char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx"; if (!dbus_message_marshal (message_without_unix_fds, &marshalled, &len)) _dbus_assert_not_reached ("failed to marshal message"); _dbus_assert (len != 0); _dbus_assert (marshalled != NULL); _dbus_assert (dbus_message_demarshal_bytes_needed (marshalled, len) == len); message2 = dbus_message_demarshal (marshalled, len, &error); _dbus_assert (message2 != NULL); _dbus_assert (!dbus_error_is_set (&error)); verify_test_message (message2); dbus_message_unref (message2); dbus_free (marshalled); /* Demarshal invalid message. */ message2 = dbus_message_demarshal ("invalid", 7, &error); _dbus_assert (message2 == NULL); _dbus_assert (dbus_error_is_set (&error)); dbus_error_free (&error); /* Demarshal invalid (empty) message. */ message2 = dbus_message_demarshal ("", 0, &error); _dbus_assert (message2 == NULL); _dbus_assert (dbus_error_is_set (&error)); dbus_error_free (&error); /* Bytes needed to demarshal empty message: 0 (more) */ _dbus_assert (dbus_message_demarshal_bytes_needed ("", 0) == 0); /* Bytes needed to demarshal invalid message: -1 (error). */ _dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1); } dbus_message_unref (message_without_unix_fds); _dbus_message_loader_unref (loader); check_memleaks (); _dbus_check_fdleaks(); /* Check that we can abandon a container */ message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService", "/org/freedesktop/TestPath", "Foo.TestInterface", "Method"); dbus_message_iter_init_append (message, &iter); _dbus_assert (dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, (DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING), &array_iter)); _dbus_assert (dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)); s = "peaches"; _dbus_assert (dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &s)); /* uh-oh, error, try and unwind */ dbus_message_iter_abandon_container (&array_iter, &struct_iter); dbus_message_iter_abandon_container (&array_iter, &iter); dbus_message_unref (message); /* Load all the sample messages from the message factory */ { DBusMessageDataIter diter; DBusMessageData mdata; int count; reset_validities_seen (); count = 0; _dbus_message_data_iter_init (&diter); while (_dbus_message_data_iter_get_and_next (&diter, &mdata)) { if (!dbus_internal_do_not_use_try_message_data (&mdata.data, mdata.expected_validity)) { _dbus_warn ("expected validity %d and did not get it\n", mdata.expected_validity); _dbus_assert_not_reached ("message data failed"); } _dbus_message_data_free (&mdata); count += 1; } printf ("%d sample messages tested\n", count); print_validities_seen (FALSE); print_validities_seen (TRUE); } check_memleaks (); _dbus_check_fdleaks(); /* Now load every message in test_data_dir if we have one */ if (test_data_dir == NULL) return TRUE; return dbus_internal_do_not_use_foreach_message_file (test_data_dir, (DBusForeachMessageFileFunc) dbus_internal_do_not_use_try_message_file, NULL); }
int my_method_sync (const void * parent, NihDBusProxy * proxy, const int32_t *value, size_t value_len) { DBusMessage * method_call; DBusMessageIter iter; DBusError error; DBusMessage * reply; DBusMessageIter value_iter; nih_assert (proxy != NULL); nih_assert ((value_len == 0) || (value != NULL)); /* Construct the method call message. */ method_call = dbus_message_new_method_call (proxy->name, proxy->path, "com.netsplit.Nih.Test", "Method"); if (! method_call) nih_return_no_memory_error (-1); dbus_message_set_auto_start (method_call, proxy->auto_start); dbus_message_iter_init_append (method_call, &iter); /* Marshal an array onto the message */ if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "i", &value_iter)) { dbus_message_unref (method_call); nih_return_no_memory_error (-1); } for (size_t value_i = 0; value_i < value_len; value_i++) { int32_t value_element; value_element = value[value_i]; /* Marshal a int32_t onto the message */ if (! dbus_message_iter_append_basic (&value_iter, DBUS_TYPE_INT32, &value_element)) { dbus_message_iter_abandon_container (&iter, &value_iter); dbus_message_unref (method_call); nih_return_no_memory_error (-1); } } if (! dbus_message_iter_close_container (&iter, &value_iter)) { dbus_message_unref (method_call); nih_return_no_memory_error (-1); } /* Send the message, and wait for the reply. */ dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (proxy->connection, method_call, -1, &error); if (! reply) { dbus_message_unref (method_call); if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) { nih_error_raise_no_memory (); } else { nih_dbus_error_raise (error.name, error.message); } dbus_error_free (&error); return -1; } dbus_message_unref (method_call); /* Iterate the arguments of the reply */ dbus_message_iter_init (reply, &iter); if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) { dbus_message_unref (reply); nih_return_error (-1, NIH_DBUS_INVALID_ARGS, _(NIH_DBUS_INVALID_ARGS_STR)); } dbus_message_unref (reply); return 0; }
/** * Closes an a{sv} after unsuccessfully appending a value. * * You must also abandon whatever larger data structure (message, etc.) * the a{sv} was embedded in. * * @param iter the iterator which is appending to the message or other data structure containing the a{sv} * @param arr_iter the iterator appending to the array, will be closed */ void _dbus_asv_abandon (DBusMessageIter *iter, DBusMessageIter *arr_iter) { dbus_message_iter_abandon_container (iter, arr_iter); }
/** Helper for appending GConfValue to dbus message * * @param reply DBusMessage under construction * @param conf GConfValue to be added to the reply * * @return TRUE if the value was succesfully appended, or FALSE on failure */ static gboolean append_gconf_value_to_dbus_message(DBusMessage *reply, GConfValue *conf) { const char *sig = 0; DBusMessageIter body, variant, array; if( !(sig = value_signature(conf)) ) { goto bailout_message; } dbus_message_iter_init_append(reply, &body); if( !dbus_message_iter_open_container(&body, DBUS_TYPE_VARIANT, sig, &variant) ) { goto bailout_message; } switch( conf->type ) { case GCONF_VALUE_STRING: { const char *arg = gconf_value_get_string(conf) ?: ""; dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &arg); } break; case GCONF_VALUE_INT: { dbus_int32_t arg = gconf_value_get_int(conf); dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &arg); } break; case GCONF_VALUE_FLOAT: { double arg = gconf_value_get_float(conf); dbus_message_iter_append_basic(&variant, DBUS_TYPE_DOUBLE, &arg); } break; case GCONF_VALUE_BOOL: { dbus_bool_t arg = gconf_value_get_bool(conf); dbus_message_iter_append_basic(&variant, DBUS_TYPE_BOOLEAN, &arg); } break; case GCONF_VALUE_LIST: if( !(sig = type_signature(gconf_value_get_list_type(conf))) ) { goto bailout_variant; } if( !dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, sig, &array) ) { goto bailout_variant; } switch( gconf_value_get_list_type(conf) ) { case GCONF_VALUE_STRING: { int cnt = 0; const char **arg = string_array_from_gconf_value(conf, &cnt); for( int i = 0; i < cnt; ++i ) { const char *str = arg[i]; dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &str); } g_free(arg); } break; case GCONF_VALUE_INT: { int cnt = 0; dbus_int32_t *arg = int_array_from_gconf_value(conf, &cnt); dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_INT32, &arg, cnt); g_free(arg); } break; case GCONF_VALUE_FLOAT: { int cnt = 0; double *arg = float_array_from_gconf_value(conf, &cnt); dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_DOUBLE, &arg, cnt); g_free(arg); } break; case GCONF_VALUE_BOOL: { int cnt = 0; dbus_bool_t *arg = bool_array_from_gconf_value(conf, &cnt); dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BOOLEAN, &arg, cnt); g_free(arg); } break; default: goto bailout_array; } if( !dbus_message_iter_close_container(&variant, &array) ) { goto bailout_variant; } break; default: goto bailout_variant; } if( !dbus_message_iter_close_container(&body, &variant) ) { goto bailout_message; } return TRUE; bailout_array: dbus_message_iter_abandon_container(&variant, &array); bailout_variant: dbus_message_iter_abandon_container(&body, &variant); bailout_message: return FALSE; }
DBusHandlerResult my_com_netsplit_Nih_Test_Method_method (NihDBusObject * object, NihDBusMessage *message) { DBusMessageIter iter; DBusMessage * reply; MyMethodStructure *structure; DBusMessageIter structure_iter; const char * structure_item0; uint32_t structure_item1; nih_assert (object != NULL); nih_assert (message != NULL); /* Iterate the arguments to the message and demarshal into arguments * for our own function call. */ dbus_message_iter_init (message->message, &iter); if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) { reply = dbus_message_new_error (message->message, DBUS_ERROR_INVALID_ARGS, "Invalid arguments to Method method"); if (! reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; if (! dbus_connection_send (message->connection, reply, NULL)) { dbus_message_unref (reply); return DBUS_HANDLER_RESULT_NEED_MEMORY; } dbus_message_unref (reply); return DBUS_HANDLER_RESULT_HANDLED; } /* Call the handler function */ nih_error_push_context (); if (my_method (object->data, message, &structure) < 0) { NihError *err; err = nih_error_get (); if (err->number == ENOMEM) { nih_free (err); nih_error_pop_context (); return DBUS_HANDLER_RESULT_NEED_MEMORY; } else if (err->number == NIH_DBUS_ERROR) { NihDBusError *dbus_err = (NihDBusError *)err; reply = NIH_MUST (dbus_message_new_error (message->message, dbus_err->name, err->message)); nih_free (err); nih_error_pop_context (); NIH_MUST (dbus_connection_send (message->connection, reply, NULL)); dbus_message_unref (reply); return DBUS_HANDLER_RESULT_HANDLED; } else { reply = NIH_MUST (dbus_message_new_error (message->message, DBUS_ERROR_FAILED, err->message)); nih_free (err); nih_error_pop_context (); NIH_MUST (dbus_connection_send (message->connection, reply, NULL)); dbus_message_unref (reply); return DBUS_HANDLER_RESULT_HANDLED; } } nih_error_pop_context (); /* If the sender doesn't care about a reply, don't bother wasting * effort constructing and sending one. */ if (dbus_message_get_no_reply (message->message)) return DBUS_HANDLER_RESULT_HANDLED; do { __label__ enomem; /* Construct the reply message. */ reply = dbus_message_new_method_return (message->message); if (! reply) goto enomem; dbus_message_iter_init_append (reply, &iter); /* Marshal a structure onto the message */ if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &structure_iter)) { dbus_message_unref (reply); reply = NULL; goto enomem; } structure_item0 = structure->item0; /* Marshal a char * onto the message */ if (! dbus_message_iter_append_basic (&structure_iter, DBUS_TYPE_STRING, &structure_item0)) { dbus_message_iter_abandon_container (&iter, &structure_iter); dbus_message_unref (reply); reply = NULL; goto enomem; } structure_item1 = structure->item1; /* Marshal a uint32_t onto the message */ if (! dbus_message_iter_append_basic (&structure_iter, DBUS_TYPE_UINT32, &structure_item1)) { dbus_message_iter_abandon_container (&iter, &structure_iter); dbus_message_unref (reply); reply = NULL; goto enomem; } if (! dbus_message_iter_close_container (&iter, &structure_iter)) { dbus_message_unref (reply); reply = NULL; goto enomem; } enomem: __attribute__ ((unused)); } while (! reply); /* Send the reply, appending it to the outgoing queue. */ NIH_MUST (dbus_connection_send (message->connection, reply, NULL)); dbus_message_unref (reply); return DBUS_HANDLER_RESULT_HANDLED; }