LINUX.ORG.RU

Как бы вы на C «разобрали» сообщение DBus?


0

1

Вот реальное сообщение, описывающее блочное устройство, полученное через DBus:

method return sender=:1.28 -> dest=:1.81 reply_serial=2
   array [
      dict entry(
         string "Device"
         variant             array of bytes [
               2f 64 65 76 2f 73 64 64 31 00
            ]
      )
      dict entry(
         string "PreferredDevice"
         variant             array of bytes [
               2f 64 65 76 2f 73 64 64 31 00
            ]
      )
      dict entry(
         string "Symlinks"
         variant             array [
               array of bytes [
                  2f 64 65 76 2f 64 69 73 6b 2f 62 79 2d 69 64 2f 75 73 62 2d
                  50 72 6f 6c 69 66 69 63 5f 54 65 63 68 6e 6f 6c 6f 67 79 5f
                  49 6e 63 2e 5f 55 53 42 5f 4d 61 73 73 5f 53 74 6f 72 61 67
                  65 5f 44 65 76 69 63 65 2d 70 61 72 74 31 00
               ]
               array of bytes [
                  2f 64 65 76 2f 64 69 73 6b 2f 62 79 2d 6c 61 62 65 6c 2f 43
                  4f 52 53 41 49 52 00
               ]
               array of bytes [
                  2f 64 65 76 2f 64 69 73 6b 2f 62 79 2d 70 61 74 68 2f 70 63
                  69 2d 30 30 30 30 3a 30 30 3a 31 61 2e 30 2d 75 73 62 2d 30
                  3a 31 2e 34 2e 31 3a 31 2e 30 2d 73 63 73 69 2d 30 3a 30 3a
                  30 3a 30 2d 70 61 72 74 31 00
               ]
               array of bytes [
                  2f 64 65 76 2f 64 69 73 6b 2f 62 79 2d 75 75 69 64 2f 44 38
                  30 30 2d 37 32 45 30 00
               ]
            ]
      )
      dict entry(
         string "DeviceNumber"
         variant             uint64 2097
      )
      dict entry(
         string "Id"
         variant             string "by-uuid-D800-72E0"
      )
      dict entry(
         string "Size"
         variant             uint64 1040171008
      )
      dict entry(
         string "ReadOnly"
         variant             boolean false
      )
      dict entry(
         string "Drive"
         variant             object path "/org/freedesktop/UDisks2/drives/Prolific_Technology_Inc_2e_USB_Mass_Storage_Device_Prolific_Technology_Inc_2e_USB_Mass_Storage_Device"
      )
      dict entry(
         string "MDRaid"
         variant             object path "/"
      )
      dict entry(
         string "MDRaidMember"
         variant             object path "/"
      )
      dict entry(
         string "IdUsage"
         variant             string "filesystem"
      )
      dict entry(
         string "IdType"
         variant             string "vfat"
      )
      dict entry(
         string "IdVersion"
         variant             string "FAT16"
      )
      dict entry(
         string "IdLabel"
         variant             string "CORSAIR"
      )
      dict entry(
         string "IdUUID"
         variant             string "D800-72E0"
      )
      dict entry(
         string "Configuration"
         variant             array [
            ]
      )
      dict entry(
         string "CryptoBackingDevice"
         variant             object path "/"
      )
      dict entry(
         string "HintPartitionable"
         variant             boolean true
      )
      dict entry(
         string "HintSystem"
         variant             boolean false
      )
      dict entry(
         string "HintIgnore"
         variant             boolean false
      )
      dict entry(
         string "HintAuto"
         variant             boolean true
      )
      dict entry(
         string "HintName"
         variant             string ""
      )
      dict entry(
         string "HintIconName"
         variant             string ""
      )
      dict entry(
         string "HintSymbolicIconName"
         variant             string ""
      )
   ]
Для не особо посвященных пояснение. Это массив из некоторого числа элементов типа dict entry. Каждый элемент типа dict entry состоит из элементов типа string и variant. Элемент variant содержит любой иной элемент (строку, или массив, или булевское значение).

Libdbus дает следующие инструменты. Можно получить первый интератор сообщения. Можно получить тип итератора. Можно получить следующий итератор сообщения. Если итератор имеет составную структуру (array, variant и пр.), то можно получить первый субитератор этого составного итератора, а с ним работать аналогично.

Собственно, чтобы просто это дело напечатать (приведен вывод утилиты dbus-send), пишем функцию, которая в цикле получает очередной итератор, анализирует его тип, и, если итератор составной уходит в рекурсию, если простой печатает.

Но задача стоит иначе. Надо проанализировать итераторы типа dict entry, и в зависимости от того, что там лежит в string, поместить значение итератора variant в соответствующее поле структуры. Ну к примеру: string «Device», сохраняем array of bytes [2f 64 65 76 2f 73 64 64 31 00] в поле device.

Собственно, задачу то решил. Но как-то громоздко получилось. Может предложите что-нибудь элегантное и простое. Бывает же такое, что упрешься в одно решение, и не видишь ничего вокруг.

★★★

Последнее исправление: zloy_starper (всего исправлений: 1)

как-то громоздко получилось

А что именно смущает? Много кода?

На чистом С я бы наверное делал что-то типа такого:

#define MAX_NAME_LENGTH 128

void
dict_array(void *data)
{
        /* ... */
}

void
dict_uint64(void *data)
{
        /* ... */
}

void
dict_string(void *data)
{
        /* ... */
}


struct dict_entry
{
        char name[MAX_NAME_LENGTH];
        void (*processor_ptr)(void *); /* указатель на обработчик variant */
} entries[] =
 {
  {"Device", &dict_array},
  {"PreferredDevice", &dict_array},
  {"DeviceNumber", &dict_string},
  {"Id", &dict_string},
  {"Size", &dict_uint64},
  /* ... */
  {"", 0}
 };

И для каждой string вызываем свою функцию-обработчик.

Или, если это нужно делать быстро взял бы re2c, получилось бы еще и компактнее:

/*!re2c
   /* ... */
   "Device"           { return dict_array(...); }
   "PreferredDevice"  { return dict_array(...); }
   "DeviceNumber"     { return dict_string(...); }
   "Id"               { return dict_string(...); }
   "Size"             { return dict_uint64(...); }
*/
anonymous
()
Ответ на: комментарий от Anon

Можно. И может быть сделаю. Но: - с Udisks версии 1 я это уже сделал. Но там каждое свойство получается по отдельности. Теперь логично доработать это для использования с Udisks версии 2. - если делать это через udev, то надо будет делать фактически свою версию Udisks. Собственно почему бы и нет. Но опять нужен будет протокол обмена с клиентами.

zloy_starper ★★★
() автор топика
Ответ на: комментарий от anonymous

Ну разве что сделать структуру с указателями на функции-обработчики мне не пришло в голову. Пожалуй так будет более компактно и нагляднее.

zloy_starper ★★★
() автор топика

use glib, motherfucker!

anonymous
()
Ответ на: комментарий от anonymous

DBus это ад, даже с высокоуровневой оберткой.

Не могу не согласиться. Из последнего, что меня «порадовало»: Напоролся на seg fault. Замучался искать, где мой косяк. Дело усугублялось еще тем, что, когда все построено на цикле обработке событий, очень трудно найти место, откуда ошибка зародилась. Но на другом компе, где, видимо, DBus был посвежее, я таки вдруг получил сообщение о внутренней ошибке. Оказалось в пути к объекту я пропустил слэш в самом начале имени.

zloy_starper ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.