二、BLUEZ编程

The BlueZ D-Bus services are exported through the system message bus. Every D-Bus enabled desktop has a system message bus instance running. This bus is used to broadcast system events, such as new hardware devices, network connection status, and so forth. The session message bus is not suitable for this architecture since the Bluetooth hardware/connections are shared by all desktop sessions.

BluezD-bus服务通过系统消息总线提供。每个D - Bus使桌面有一个系统消息总线实例运行。这个bus是用来广播系统时间,如新的硬件设备、网络连接状态等等。会话消息总线对这种体系结构是不适合的,因为蓝牙硬件/连接被所有桌面会话共享。

The BlueZ D-Bus Architecture goal are:

·Abstract Bluetooth HCI commands/events

·Provide an easy interface to setup Bluetooth adapter and manage the services

BluezD-bus体系结构的目标:

l抽象hci层命令和事件。

l提供简单的接口来启动蓝牙适配器和管理蓝牙服务。

The hcid is the main entity of the architecture. It implements methods to setup theBluetooth adapters, retrieve remote device properties, control the pairing procedure and control the services registration/searches. The following figure shows a high level relationship between the entities.

Hcid是该体系结构的主体。它实现启动蓝牙适配器的方法、获取远端设备属性、控制配对过程和控制服务的注册和搜索。下图显示了一个高层次的实体之间的关系。

2.2D-Bus介绍

什么是D-Bus

D-BUS 是一种进程间通信的方式,从架构上来说,分为三层:

① 一个库,libdbus,允许2个进程间交换信息。

② 一个消息总线守护进程,它使用libdbus库。其他进程都可以与它连接。它可以将消息从一个进程发给另外任意数量的其他进程。现在有一些基于特定应用框架的dbus库函数封装,例如libdbus-gliblibdbus-qt,也有与一些语言绑定的形式,例如Python等。这些封装的API旨在令D-BUS编程更加简单,libdbus倾向于提供更低层次的调用。很多libdbus API只在绑定的组件中可用。

③ libdbus仅支持一对一的连接,就像原始 socket通讯方式一样。但它传递的不是以字节为单位的数据流,而是具有一定意义的消息包。消息的消息头部表示消息种类,消息体用来装载数据。 Libdbus也可以允许实现特定的传输通道,从而来完成比如像认证之类的应用细节(libdbus also abstracts the exact transport used (sockets vs. whatever else), and handles details such as authentication.)。

消息总线守护进程将D-bus上连接的所有程序构成一个轮形hubLibdbus为中心,它和应用程序建立一对一的连接。每个应用程序通过通道发送消息到消息总线,然后总线进程将消息转发到其他连接到hub的应用程序。可以把消息总线理解为一个路由器。Dbus服务在一个操作系统中存在多个进程。第一个进程是一个全局进程,就如sendmailApache的系统守护进程一样。这个进程具有高度的安全限制,一般用于系统进程间的通讯。其他的dbus进程都是用户进程,针对于每个登录的用户建立。这些实例允许用户会话中的应用程序相互通信。Dbus全局进程和用户进程是相互独立的,他们并没有内在的依赖关系。

D-Bus应用

有很多种IPC或者网络通信系统,如:CORBADCEDCOMDCOPXML-RPCSOAPMBUSICE等。Dbus的目的主要是下面两点:

1、在同一个桌面会话中,进行桌面应用程序之间的通讯。

2、桌面程序和内核或者守护进程之间通信。

D-Bus概念

对象路径(Native Objects and Object Paths):D-Bus的底层接口,和libdbus相关,它提供一种叫对象路径(object path),用于让高层接口绑定到各个对象中去,允许远端应用程序指向他们。Object path就像一个文件路径。

方法和信号(Methods and Signals):每个对象都有一些成员,有两种成员:方法(methods)和信号(signals),在对象中,方法可以被调用。信号会被广播,感兴趣的对象可以处理这个信号,同时信号中也可以带有相关的数据。

接口(Interfaces):每个对象都有一个或者多个接口,一个接口就是多个方法和信号的集合。这个概念和Glib, Qt或者Java中的是一致的。接口定义了对象实例的类型。dbus使用简单的命名空间字符串来表示接口,如org.freedesktop.Introspectable。可以说dbus接口相当于C++中的纯虚类。

代理(Proxies):使用代理对象就是让调用者感觉在直接使用远程对象一样。d-bus的底层接口完成了一些比较低级和繁琐的调用过程,比如必须先调用创建方法形成消息包,然后发送,然后等待接受和处理返回的消息。所以,高层的接口就可以使用代理对象提供的接口屏蔽这些细节。所以,当调用代理对象的方法时,代理内部会转换成dbus的方法调用,等待消息返回,对返回结果解包,返回给相应的方法。可以看看下面的例子,使用dbus底层接口编写的代码:

Message message = new Message(”/remote/object/path”, “MethodName”, arg1, arg2);
Connection connection = getBusConnection();
connection.send(message);
Message reply = connection.waitForReply(message);
if (reply.isError()) {

} else {
Object returnValue = reply.getReturnValue();
}

使用代理对象编写的代码:

Proxy proxy = new Proxy(getBusConnection(), “/remote/object/path”);
Object returnValue = proxy.MethodName(arg1, arg2);

客户端代码减少很多。

总线名称(Bus Names):当一个应用程序连接上bus daemon时,daemon会分配一个唯一的名字给它。以冒号(:)开始,这些名字在daemon的生命周期中是不会改变的,可以认为这些名字就是一个 IP地址。当这个名字映射到应用程序的连接上时,应用程序可以说拥有这个名字。同时应用可以声明额外的容易理解的名字,比如可以取一个名字 com.mycompany.TextEditor,可以认为这些名字就是一个域名。其他应用程序可以往这个名字发送消息,执行各种方法。

名字还有第二个重要的用途,可以用于跟踪应用程序的生命周期。当应用退出(或者崩溃)时,与bus的连接将被OS内核关掉,bus将会发送通知,告诉剩余的应用程序,该程序已经丢失了它的名字。名字还可以检测应用是否已经启动,这可以用来实现单实例启动程序。

地址(Addresses):使用d-bus的应用程序既可以是server也可以是clientserver监听到来的连接,client连接到server,一旦连接建立,消息就可以流转。如果使用dbus daemon,所有的应用程序都是clientdaemon监听所有的连接,应用程序初始化连接到daemondbus地址指明server将要监听的地方,client将要连接的地方,例如,地址:unix:path=/tmp/abcdef表明 server将在/tmp/abcdef路径下监听unix域的socketclient也将连接到这个socket。一个地址也可以指明是TCP /IPsocket,或者是其他的。

当使用bus daemon时,libdbus会从环境变量中(DBUS_SESSION_BUS_ADDRESS)自动认识会话daemon”的地址。如果是系统 daemon,它会检查指定的socket路径获得地址,也可以使用环境变量(DBUS_SESSION_BUS_ADDRESS)进行设定。当dbus中不使用daemon时,需要定义哪一个应用是server,哪一个应用是client,同时要指明server的地址,这不是很通常的做法。

D-bus工作原理

Calling a Method – Behind the Scenes
dbus中调用一个方法包含了两条消息,进程A向进程B发送方法调用消息,进程B向进程A发送应答消息。所有的消息都由daemon进行分派,每个调用的消息都有一个不同的序列号,返回消息包含这个序列号,以方便调用者匹配调用消息与应答消息。调用消息包含一些参数,应答消息可能包含错误标识,或者包含方法的返回数据。

方法调用的一般流程:

1.使用不同语言绑定的dbus高层接口,都提供了一些代理对象,调用其他进程里面的远端对象就像是在本地进程中的调用一样。应用调用代理上的方法,代理将构造一个方法调用消息给远端的进程。

2.DBUS的底层接口中,应用需要自己构造方法调用消息(method call message),而不能使用代理。

3.方法调用消息里面的内容有:目的进程的bus name,方法的名字,方法的参数,目的进程的对象路径,以及可选的接口名称。

4.方法调用消息是发送到bus daemon中的。

5.bus daemon查找目标的bus name,如果找到,就把这个方法发送到该进程中,否则,daemon会产生错误消息,作为应答消息给发送进程。

6.目标进程解开消息,在dbus底层接口中,会立即调用方法,然后发送方法的应答消息给daemon。在dbus高层接口中,会先检测对象路径,接口,方法名称,然后把它转换成对应的对象(如GObjectQT中的QObject等)的方法,然后再将应答结果转换成应答消息发给daemon

7.bus daemon接受到应答消息,将把应答消息直接发给发出调用消息的进程。

8.应答消息中可以包容很多返回值,也可以标识一个错误发生,当使用绑定时,应答消息将转换为代理对象的返回值,或者进入异常。

bus daemon不对消息重新排序,如果发送了两条消息到同一个进程,他们将按照发送顺序接受到。接受进程并需要按照顺序发出应答消息,例如在多线程中处理这些消息,应答消息的发出是没有顺序的。消息都有一个序列号可以与应答消息进行配对。

Emitting a Signal – Behind the Scenes
dbus中一个信号包含一条信号消息,一个进程发给多个进程。也就是说,信号是单向的广播。信号可以包含一些参数,但是作为广播,它是没有返回值的。

信号触发者是不了解信号接受者的,接受者向daemon注册感兴趣的信号,注册规则是”match rules”,记录触发者名字和信号名字。daemon只向注册了这个信号的进程发送信号。

信号的一般流程如下:

1.当使用dbus底层接口时,信号需要应用自己创建和发送到daemon,使用dbus高层接口时,可以使用相关对象进行发送,如Glib里面提供的信号触发机制。

2.信号包含的内容有:信号的接口名称,信号名称,发送进程的bus name,以及其他参数。

3.任何进程都可以依据”match rules”注册相关的信号,daemon有一张注册的列表。

4.daemon检测信号,决定哪些进程对这个信号感兴趣,然后把信号发送给这些进程

5.每个进程收到信号后,如果是使用了dbus高层接口,可以选择触发代理对象上的信号。如果是dbus底层接口,需要检查发送者名称和信号名称,然后决定怎么做。

2.3Bluez的安全接口

pin_helper concept has been removed starting with bluez-utils 3.X. and has been replaced with a feature called passkey agents. An application that wants to handle passkey requests must use the "hcid" security interface to register a passkey agent. Currently, two types of passkey agents are supported: default and device specific. A "specific" passkey agent handles all passkey requests for a given remote device while a default handles all requests for which a specific agent was not found. "specific" passkey agents are useful to address pre-defined passkey values or environments where the user interaction is not allowed/difficult.

When theCreateBonding method is called the "hcid" daemon will verify if there is a link key stored in the file system. If it is available an error is returned, and if not, a D-Bus message is sent to the registered passkey agent asking for a passkey.

Each Passkey Agent is represented by a D-Bus object path. The "hcid" distinguishes the agents based on their unique bus names and their object paths.

Pin_help的理念在bluez-util 3.x时已经被移除,并被密钥代理所代替。任何想处理密钥请求的应用程序必须使用hcid安全接口来注册密钥代理。现在支持两种类型的密钥代理:默认和设备特定。一个"特定"的密钥代理处理所有远端的密钥请求,一个默认的密钥代理,处理特定的代理所没有发现的所有密钥请求。"特定"的密钥代理对处理那些和用户交互困难或者不允许用户交互的设备的预定义的密钥值或环境非常有用。

CreateBonding方法被调用时,hcid守护进程将确认当前的文件系统中是否保存了链接密钥,若可以找到,就返回一个错误。若找不到,D-Bus消息将被发出来为密钥请求的设备,注册一个密钥代理。每个密钥代理被D-Bus对象路径所体现,hcid依据唯一的总线名称和对象路径来区分代理。

Architecture

·Step 1: Represents the passkey agent registration

·Step 2: Represents a client callingCreateBonding

·Step 3: Represents the hcid asking for a passkey valu

体系结构

l第一步:表示密钥代理注册

l第二步:表示客户调用CreateBonding

l第三步:代表hcid请求密钥值。

Message Flow

In the following figure, the "CreateBonding" method call is hidden. The "PIN Request" HCI event is generated when there is not a link available in the file system. In this case "Link Key Request Negative Reply" command is sent triggering the "Pin Request" event.

在下面得图表中,CreateBonding方法的调用被隐藏。当没有一个可用链接时,"PIN Request"HCI层事件被产生,在这种情况下,"Link Key Request Negative Reply"命令被发送来回应"Pin Request" 事件。

·Step 1: Represents the D-Bus message sent to register the default/device specific passkey agent.

·Step 2: Represents the HCI "PIN Request" event sent by the Bluetooth Host Controller.

·Step 3: Represents the D-Bus message sent to the default/device speficic passkey agent requesting a passkey.

·Step 4: Represents the "Auth Complete" event where the status contains "LMP Response Timeout"(The remote didn't type the passkey).

·Step 5: Represents the "hcid" issuing a "Cancel" to a previous Request call.

·Step 6: Represents the D-Bus message sent to release the passkey agent: basically sent when the hcid exits.

l第一步:D-Bus发送消息来注册默认的或者特定的密钥代理。

l第二步:蓝牙主机控制器发送HCI"PIN Request"事件。

l第三步:D-Bus发送消息到默认的或者特定的密钥代理,请求密钥。

l第四步:"Auth Complete"完成事件,如果这种状态包含"LMP Response Timeout"

l第五步:hcid发出“Cancel”命令给D-Bus

l第六步:当hcid退出时,D - Bus的信息发送到释放密钥代理

2.4Bluez适配器接口

Description

The "Adapter" interface provides methods to setup the local adapter(s), search remote devices, pairing and search for services.

This interface is considered stable and no change is planned.

For each available adapter the hcid register an adapter object instance provided in the path "/org/bluez/hci{0, 1, 2, ...}".

适配器接口提供,启动适配器、搜索设别、配对、和搜索服务的方法。这个接口被认为是稳定的,没有改变计划。对每个可用的适配器,hcid为其注册一个适配器对象实例,在路径 "/org/bluez/hci{0, 1, 2, ...}"里。

2.5Bluez配对

Description

Services that need ask the user to accept/reject an operation such as accept OBEX objects or accept an incoming connection can use theSecurity API to request the userspace registered authorization agent responsible.

Development warnings/recommendations

1Just one Authorization request per time is allowed.

2NotConnected error is returned if a connection is not found between the devices is not found.

Trusted Devices

The BlueZ daemon keeps a list of trusted devices. Trusted means that authorization is not required to accept incoming connections or other operations that need the user response. Once a given device is added to the list, the BlueZ daemon will reply authorized without call the Authorization agent.

Authorization Agent

Authorization agents are applications responsible for address authorization requests. For more information check the BlueZ D-Bus API and implementation references:

·utils/daemon/auth-agent.c is a authorization agent implementation able to handle device specific and default

·bluez-gnome passkey/authorization agent implementation distributed by the BlueZ community

Canceling

For security reason, only the requestor can cancel a pending authorization operation.

2.6Bluez绑定

Description

The purpose of bonding is to create a relation between two Bluetooth devices based on a common link key (a bond). The link key is created and exchanged(pairing) during the bonding procedure and is expected to be stored by both Bluetooth devices, to be used for future authentication[definition from Bluetooth Core Spec].

The Bonding procedure is done through the BlueZAdapter interface.

Development warnings/recommendations

1Just one Bonding request per time is allowed.

2Bonding is not allowed if there is a discovery running.

3Pending remote name is canceled if a CreateBonding message is received.

4The Bonding takes some seconds, therefore it is recommended set a D-Bus callback to handle the message reply for this operation.

Passkey Agent

Currently, two types of passkey agents are supported:

5Device Specific: handles all passkey requests for a given remote device

6Default: Handles the remaining requests(not addressed by device specific agents)

For more information check the BlueZ D-Bus API and implementation references:

·utils/daemon/passkey-agent.c is a passkey agent implementation able to handle device specific and default

·bluez-gnome passkey agent implementation distributed by the BlueZ community=

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值