基础线协议

注意: 如果你正打算使用 libwayland,那么本章节选读,可自由转跳到第 2.2 章节。

线协议是由 32 位值所组成的流,使用主机的字节顺序进行编码(例如 x86 系列 CPU 上的小端序)。如下表示原始类型的值:

  • int, uint: 32 位有符号或无符号整型
  • fixed: 24 位整数 + 8 位小数的定点数
  • object: 32 位对象 ID
  • new_id: 32 位对象 ID,收到对象时分配

除了上面这些基本类型之外,下面还有一些常用的类型:

  • string: 字符串,以 32 位整数为前缀,指定其长度(以字节为单位),而后是字符串内容和 NUL 终止符,并用未定义的数据填充满 32 位。没有指定编码,但实际上是使用 UTF-8。

  • array: 任意的数据块,以 32 位整形作为前缀按位指定其长度,随后是数组逐字内容和 NUL 结束符,用未定义的数据填充不满 32 位长度的部分。

  • fd: 主传输上的 0-bit 值,在 Unix 域套接字信息(msg_control)中使用辅助数据,将文件描述符从一段传输到另一端。

  • enum: 一个单独的值(或者 bitmap)用于枚举已知常量,编码为 32 位整形。

消息

线协议是使用这些原语构建而成的消息流。每个消息都是对 object 起作用的一个事(服务端到客户端)件或者请求(客户端到服务端)。

消息头由两个部分组成。第一个是起作用的对象 ID。第二个是两个 16 位值;高 16 位读音消息的大小(包括头本身),低 16 位事件或请求的操作码。其参数基于双方事先约定的消息签名。接收方查找对象 ID 以及由其操作码定义的事件或请求,以确定消息的签名和性质。

msg header
object IDmsg size (upper 16bits)code (lower 16bits)

为了解析消息,客户端和服务端必须先创建对象。作为 Wayland 的显示单例已预先分配对象 ID,可用于引导其他对象。我们将在第四章中对此进行讨论,而下一章将讨论什么是接口,以及假设您已经协商了对象 ID 的情况下请求和事件是如何工作,下见后文。

对象 ID

当消息带着 new_id 参数来的时候,发送方将为其分配一个对象 ID(用于该对象的接口是通过其他参数建立的,或者是针对该请求或事件预先约定的)。此对象 ID 可以用在后续消息中使用,作为信息头的第一个字或者 object_id 参数。客户端从 10xFEFFFFFF 范围内分配 ID,服务端在 0xFF0000000xFFFFFFFF 内分配 ID。ID 从下限开始,并随着每次新对象的分配而递增。

对象 ID 为 0 表示一个空对象;也就是说不存在对象或缺少显式声明。

传输

迄今为止,所有已知的 Wayland 实现都工作在 Unix 域套接字上。尤其是出于一个原因而使用它:文件描述符消息。Unix 套接字是能够在进程之间传输文件描述符的最为实用的传输方式,并且对于大量数据传输而言是十分必要的(主要如键映射、像素缓冲和剪贴板内容)。从理论上讲,可以使用其他传输方式(如 TCP),但需要有人来找出另一种传输块数据的方式。

要找到连接的 Unix 套接字,大多数实现只需要执行 libwayland 的操作:

  1. 如果已经设置了 WAYLAND_SOCKET,则说明已经在其上建立了文件描述符编号,并假设父进程为我们配置了连接。
  2. 如果已经设置了 WAYLAND_DISPLAY,则与 XDG_RUNTIME_DIR 路径连接以建立 Unix 套接字。
  3. 假定套接字名称为 wayland-0,并与 XDG_RUNTIME_DIR 路径连接以建立 Unix 套接字。
  4. 建议放弃。