DBusイントロスペクション メモ
Web::Dashを作るときにLensサービスのインタフェースを調べたりLensの通信を傍受したりしたのでそのメモ。
そもそもDBusとはなんたるかについてはうすださんの記事が詳しくて分かりやすい。
- http://www.usupi.org/sysad/175.html - 「D-Bus の存在を感じてみる」
- http://www.usupi.org/sysad/176.html - 「D-Bus の存在をもう少し感じてみる」
バスを見つける
DBusを使うにはまずは使いたいサービスがつながっているバスを見つける必要がある。標準のバスとしてはsystem busとsession busがあり、大抵のサービスはどちらかのバスにつながっている。
system busはシステム全体で共有されるバス。Ubuntuのデフォルトの設定ではdbus-daemonが/var/run/dbus/system_bus_socketにUNIXドメインソケットを作ってそいつを通じて通信するみたい。
session busはユーザセッションごとに作成されるバスで、デスクトップアプリケーションなんかは普通こっちのバスを使う。session busを使うプロセスは、環境変数DBUS_SESSION_BUS_ADDRESSで示される接続先につなぐことで通信を行う。Ubuntuの場合、DBUS_SESSION_BUS_ADDRESSは「抽象名前空間」に属する独特のUNIXドメインソケットとなるようだ。なのでファイルシステムのどこを探してもそれらしいソケットは見当たらない。
まれに、system busもsession busも使わず独自のバスを立てるアプリケーションが存在する。例えばiBusは自前でバスを立てる。iBusのバス名は~/.config/ibus/busディレクトリ以下のファイルに記述されている。(参考: http://linux.lsdev.sil.org/blog/?p=58)
サービスとオブジェクトを見つける
次に、バスに接続されているサービス及びサービス内のオブジェクトを見つける。
とりあえず確認したい場合はGUIアプリケーションのD-Feetを使うといい。
D-Feetはバス名を指定すればそのバスにつながっているサービスとオブジェクトを列挙して表示してくれる。また、オブジェクトの持つメソッドとシグナルも列挙してくれるし、メソッドを実行することもできる。
プログラムからサービス名のリストを取得したい場合は、org.freedesktop.DBus.ListNamesメソッドを使う。
$ dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames
あるサービス内のオブジェクトを全て列挙したい場合は、ルートオブジェクト(/)を起点として再帰的にorg.freedesktop.DBus.Introspectable.Introspectメソッドを呼び出せばいい。Introspectメソッドの戻り値(XMLドキュメント)にはそのオブジェクトの子オブジェクトの名前が含まれるので、それを利用して木構造を走査できる。
$ dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply / org.freedesktop.DBus.Introspectable.Introspect
DBus通信を傍受する
既存のプロセスが行っているDBus通信(メソッドコールやシグナル)を傍受するにはdbus-monitorコマンドを使う。
com.canonical.Unity.Lens.Filesサービスを宛て先とする通信を傍受する。
$ dbus-monitor --session "destination='com.canonical.Unity.Lens.Files'"
com.canonical.Unity.Lens.Filesサービスが送信元の通信を傍受する。シグナルでブロードキャストされる通信も傍受できる。
$ dbus-monitor --session "sender='com.canonical.Unity.Lens.Files'"
多分、セキュリティ上の理由で傍受できない通信もあるんだと思う。