zeerd's blog         Search     Categories     Tags     Feed

闲来生雅趣,无事乐逍遥。对窗相望雪,一盏茶香飘。

connman的agent实现原理简述

#Connman #WIFI @Program


Contents:
当进行wifi连接时,会需要提供密码等信息。这就需要有一个可实现的交互机制。
connman的处理方法是,要求客户端程序按着api-agent.txt的要求,自己实现一个dbus接口,挂在system bus上面。
实际上就是一种回调机制。当connman需要客户数据时,就会调用agent的接口去向用户索取。

下面总结一下通过gdbus和c语言实现与connman的交互。
这里主要是在进行wifi的连接认证工作。

其实就是实现了一个最简单版本的simple-agent。
主要做了两件事情:
1、注册Agent
2、当接受到connman来的请求时,做成密码信息发送回去

下面的代码用于实现目的一,也就是注册Agent。
这里是借助connman-manager.xml生成的gdbus接口。
首先,需要挂到connman的dbus上。注意,需要挂到system bus。

GDBusConnection * c;
NetConnmanManager *proxy;
GError *err = NULL;

c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &err);
proxy = net_connman_manager_proxy_new_sync(c,
G_DBUS_PROXY_FLAGS_NONE,
"net.connman",
"/",
NULL,
&err);


然后就是注册,同样的借助connman-manager.xml生成的gdbus接口。
    net_connman_manager_call_register_agent_sync(
proxy,
path, // something like "/net/connman/service/wifi_xxxxx_yyyyy_managed_psk"
NULL,
&error);


其次,起到关键作用的就是这个RequestInput函数了。
生成密码信息,并且返回给connman。
static gboolean on_handle_request_input (  
NetConnmanAgent *object,
GDBusMethodInvocation *invocation,
const gchar *arg_unnamed_arg0,
GVariant *arg_unnamed_arg1,
gpointer user_data)
{
gchar * value[PASS_MAX];

scanf("%s", value);

GVariantBuilder * _builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));

GVariant *_value = g_variant_new("s", value);
g_variant_builder_add (_builder, "{sv}", "Passphrase", _value);
GVariant *res = g_variant_new("a{sv}", _builder);

net_connman_agent_complete_request_input( object, invocation, res );

return TRUE;
}

最后附上xml文件和使用方法:
connman-agent.xml
<?xml version="1.0" encoding="UTF-8" ?>

<node name="/test/Agent">
<interface name="net.connman.Agent">
<method name="ReportError">
<annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
<arg type="o" direction="in"/>
<arg type="s" direction="in"/>
</method>

<method name="RequestInput">
<annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
<arg type="o" direction="in"/>
<arg type="a{sv}" direction="in"/>
<arg type="a{sv}" direction="out"/>
</method>

<method name="RequestBrowser">
<annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
<arg type="o" direction="in"/>
<arg type="s" direction="in"/>
</method>

<method name="Cancel">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
</method>

<method name="Release">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
</method>
</interface>
</node>


connman-manager.xml
<?xml version="1.0" encoding="UTF-8" ?>

<node name="/">
<interface name="net.connman.Manager">
<method name="RegisterAgent">
<arg name="path" type="o" direction="in"/>
</method>
<method name="UnregisterAgent">
<arg name="path" type="o" direction="in"/>
</method>
</interface>
</node>


使用方法:
gdbus-codegen  --generate-c-code net_connman_agent connman-agent.xml
gdbus-codegen --generate-c-code net_connman_manager connman-manager.xml


追记:
可以通过下面命令查询任意dbus接口的详细信息:
dbus-send --session --type=method_call --print-reply --dest=com.xxx.yyy /com/xxx/yyy org.freedesktop.DBus.Introspectable.Introspect